From: Jaroslav Kysela Date: Tue, 1 Dec 2015 14:06:25 +0000 (+0100) Subject: WEBUI: Add initial UI level handling for idnode panels X-Git-Tag: v4.2.1~1423 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=022c96bf518d099320c78028aeb9791996082965;p=thirdparty%2Ftvheadend.git WEBUI: Add initial UI level handling for idnode panels --- diff --git a/src/channels.c b/src/channels.c index f049fd5dc..080ac33f1 100644 --- a/src/channels.c +++ b/src/channels.c @@ -359,6 +359,7 @@ const idclass_t channel_class = { .name = N_("Automatically name from network"), .off = offsetof(channel_t, ch_autoname), .set = channel_class_autoname_set, + .opts = PO_ADVANCED, .opts = PO_NOSAVE, }, { @@ -384,19 +385,21 @@ const idclass_t channel_class = { .name = N_("User icon"), .off = offsetof(channel_t, ch_icon), .notify = channel_class_icon_notify, + .opts = PO_ADVANCED, }, { .type = PT_STR, .id = "icon_public_url", .name = N_("Icon URL"), .get = channel_class_get_icon, - .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN, + .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN | PO_EXPERT, }, { .type = PT_BOOL, .id = "epgauto", .name = N_("Automatically map EPG source"), .off = offsetof(channel_t, ch_epgauto), + .opts = PO_ADVANCED, }, { .type = PT_STR, @@ -406,7 +409,7 @@ const idclass_t channel_class = { .set = channel_class_epggrab_set, .get = channel_class_epggrab_get, .list = channel_class_epggrab_list, - .opts = PO_NOSAVE, + .opts = PO_NOSAVE | PO_ADVANCED, }, { .type = PT_INT, @@ -439,6 +442,7 @@ const idclass_t channel_class = { .set = channel_class_services_set, .list = channel_class_services_enum, .rend = channel_class_services_rend, + .opts = PO_ADVANCED }, { .type = PT_STR, @@ -448,7 +452,8 @@ const idclass_t channel_class = { .get = channel_class_tags_get, .set = channel_class_tags_set, .list = channel_tag_class_get_list, - .rend = channel_class_tags_rend + .rend = channel_class_tags_rend, + .opts = PO_ADVANCED }, { .type = PT_STR, @@ -457,7 +462,7 @@ const idclass_t channel_class = { .get = channel_class_bouquet_get, .set = channel_class_bouquet_set, .list = bouquet_class_get_list, - .opts = PO_RDONLY + .opts = PO_RDONLY | PO_ADVANCED }, { .type = PT_STR, @@ -466,7 +471,7 @@ const idclass_t channel_class = { .set = channel_class_epg_parent_set, .list = channel_class_get_list, .off = offsetof(channel_t, ch_epg_parent), - .opts = PO_ADVANCED + .opts = PO_EXPERT }, {} } @@ -1279,6 +1284,7 @@ const idclass_t channel_tag_class = { .id = "index", .name = N_("Sort index"), .off = offsetof(channel_tag_t, ct_index), + .opts = PO_ADVANCED, }, { .type = PT_STR, @@ -1291,12 +1297,14 @@ const idclass_t channel_tag_class = { .id = "internal", .name = N_("Internal"), .off = offsetof(channel_tag_t, ct_internal), + .opts = PO_ADVANCED }, { .type = PT_BOOL, .id = "private", .name = N_("Private"), .off = offsetof(channel_tag_t, ct_private), + .opts = PO_ADVANCED }, { .type = PT_STR, @@ -1304,19 +1312,21 @@ const idclass_t channel_tag_class = { .name = N_("Icon (full URL)"), .off = offsetof(channel_tag_t, ct_icon), .notify = channel_tag_class_icon_notify, + .opts = PO_ADVANCED }, { .type = PT_STR, .id = "icon_public_url", .name = N_("Icon URL"), .get = channel_tag_class_get_icon, - .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN, + .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN | PO_EXPERT, }, { .type = PT_BOOL, .id = "titled_icon", .name = N_("Icon has title"), .off = offsetof(channel_tag_t, ct_titled_icon), + .opts = PO_ADVANCED }, { .type = PT_STR, diff --git a/src/config.c b/src/config.c index ef891cd9c..fee044033 100644 --- a/src/config.c +++ b/src/config.c @@ -1948,7 +1948,7 @@ const idclass_t config_class = { .id = "version", .name = N_("Configuration version"), .off = offsetof(config_t, version), - .opts = PO_RDONLY | PO_HIDDEN, + .opts = PO_RDONLY | PO_HIDDEN | PO_EXPERT, .group = 1 }, { @@ -1956,7 +1956,7 @@ const idclass_t config_class = { .id = "full_version", .name = N_("Last updated from"), .off = offsetof(config_t, full_version), - .opts = PO_RDONLY | PO_HIDDEN, + .opts = PO_RDONLY | PO_HIDDEN | PO_EXPERT, .group = 1 }, { @@ -1979,6 +1979,7 @@ const idclass_t config_class = { .id = "cookie_expires", .name = N_("Cookie expiration (days)"), .off = offsetof(config_t, cookie_expires), + .opts = PO_ADVANCED, .group = 1 }, { @@ -1987,6 +1988,7 @@ const idclass_t config_class = { .name = N_("HTTP CORS origin"), .set = config_class_cors_origin_set, .off = offsetof(config_t, cors_origin), + .opts = PO_EXPERT, .group = 1 }, { @@ -1995,6 +1997,7 @@ const idclass_t config_class = { .name = N_("DSCP/TOS for streaming"), .off = offsetof(config_t, dscp), .list = config_class_dscp_list, + .opts = PO_EXPERT, .group = 1 }, { @@ -2002,6 +2005,7 @@ const idclass_t config_class = { .id = "descrambler_buffer", .name = N_("Descrambler buffer (TS packets)"), .off = offsetof(config_t, descrambler_buffer), + .opts = PO_EXPERT, .group = 1 }, { @@ -2023,7 +2027,7 @@ const idclass_t config_class = { .set = config_class_info_area_set, .get = config_class_info_area_get, .list = config_class_info_area_list, - .opts = PO_LORDER, + .opts = PO_LORDER | PO_ADVANCED, .group = 3 }, { @@ -2039,6 +2043,7 @@ const idclass_t config_class = { .id = "muxconfpath", .name = N_("DVB scan files path"), .off = offsetof(config_t, muxconf_path), + .opts = PO_ADVANCED, .group = 4 }, { @@ -2046,6 +2051,7 @@ const idclass_t config_class = { .id = "tvhtime_update_enabled", .name = N_("Update time"), .off = offsetof(config_t, tvhtime_update_enabled), + .opts = PO_EXPERT, .group = 5, }, { @@ -2053,6 +2059,7 @@ const idclass_t config_class = { .id = "tvhtime_ntp_enabled", .name = N_("Enable NTP driver"), .off = offsetof(config_t, tvhtime_update_enabled), + .opts = PO_EXPERT, .group = 5, }, { @@ -2060,6 +2067,7 @@ const idclass_t config_class = { .id = "tvhtime_tolerance", .name = N_("Update tolerance (ms)"), .off = offsetof(config_t, tvhtime_tolerance), + .opts = PO_EXPERT, .group = 5, }, { @@ -2067,6 +2075,7 @@ const idclass_t config_class = { .id = "prefer_picon", .name = N_("Prefer picons over channel name"), .off = offsetof(config_t, prefer_picon), + .opts = PO_ADVANCED, .group = 6, }, { @@ -2074,6 +2083,7 @@ const idclass_t config_class = { .id = "chiconpath", .name = N_("Channel icon path (see Help)"), .off = offsetof(config_t, chicon_path), + .opts = PO_ADVANCED, .group = 6, }, { @@ -2081,6 +2091,7 @@ const idclass_t config_class = { .id = "chiconlowercase", .name = N_("Channel icon name lower-case"), .off = offsetof(config_t, chicon_lowercase), + .opts = PO_ADVANCED, .group = 6, }, { @@ -2088,6 +2099,7 @@ const idclass_t config_class = { .id = "piconpath", .name = N_("Picon path (see Help)"), .off = offsetof(config_t, picon_path), + .opts = PO_ADVANCED, .group = 6, }, {} diff --git a/src/dvr/dvr_config.c b/src/dvr/dvr_config.c index f23d47f99..988d3d1f4 100644 --- a/src/dvr/dvr_config.c +++ b/src/dvr/dvr_config.c @@ -807,6 +807,7 @@ const idclass_t dvr_config_class = { .off = offsetof(dvr_config_t, dvr_muxcnf.m_cache), .def.i = MC_CACHE_DONTKEEP, .list = dvr_config_class_cache_list, + .opts = PO_ADVANCED, .group = 1, }, { @@ -829,6 +830,7 @@ const idclass_t dvr_config_class = { .id = "clone", .name = N_("Clone scheduled entry on error"), .off = offsetof(dvr_config_t, dvr_clone), + .opts = PO_ADVANCED, .def.u32 = 1, .group = 1, }, @@ -837,6 +839,7 @@ const idclass_t dvr_config_class = { .id = "rerecord-errors", .name = N_("Schedule a re-recording if more errors than (0=off)"), .off = offsetof(dvr_config_t, dvr_rerecord_errors), + .opts = PO_ADVANCED, .group = 1, }, { @@ -844,6 +847,7 @@ const idclass_t dvr_config_class = { .id = "warm-time", .name = N_("Extra warming up time (seconds)"), .off = offsetof(dvr_config_t, dvr_warm_time), + .opts = PO_ADVANCED, .group = 1, .def.u32 = 30 }, @@ -853,6 +857,7 @@ const idclass_t dvr_config_class = { .name = N_("Extra padding before recordings (minutes)"), .off = offsetof(dvr_config_t, dvr_extra_time_pre), .list = dvr_config_class_extra_list, + .opts = PO_ADVANCED, .group = 1, }, { @@ -861,6 +866,7 @@ const idclass_t dvr_config_class = { .name = N_("Extra padding after recordings (minutes)"), .off = offsetof(dvr_config_t, dvr_extra_time_post), .list = dvr_config_class_extra_list, + .opts = PO_ADVANCED, .group = 1, }, { @@ -870,6 +876,7 @@ const idclass_t dvr_config_class = { .off = offsetof(dvr_config_t, dvr_update_window), .list = dvr_config_entry_class_update_window_list, .def.u32 = 24*3600, + .opts = PO_EXPERT, .group = 1, }, { @@ -877,6 +884,7 @@ const idclass_t dvr_config_class = { .id = "epg-running", .name = N_("Use EPG running state"), .off = offsetof(dvr_config_t, dvr_running), + .opts = PO_ADVANCED, .def.u32 = 1, .group = 1, }, @@ -885,6 +893,7 @@ const idclass_t dvr_config_class = { .id = "autorec-maxcount", .name = N_("Autorec maximum count (0=unlimited)"), .off = offsetof(dvr_config_t, dvr_autorec_max_count), + .opts = PO_ADVANCED, .group = 1, }, { @@ -892,6 +901,7 @@ const idclass_t dvr_config_class = { .id = "autorec-maxsched", .name = N_("Autorec maximum schedules limit (0=unlimited)"), .off = offsetof(dvr_config_t, dvr_autorec_max_sched_count), + .opts = PO_ADVANCED, .group = 1, }, { @@ -899,6 +909,7 @@ const idclass_t dvr_config_class = { .id = "postproc", .name = N_("Post-processor command"), .off = offsetof(dvr_config_t, dvr_postproc), + .opts = PO_ADVANCED, .group = 1, }, { @@ -906,6 +917,7 @@ const idclass_t dvr_config_class = { .id = "postremove", .name = N_("Post-remove command"), .off = offsetof(dvr_config_t, dvr_postremove), + .opts = PO_EXPERT, .group = 1, }, { @@ -920,6 +932,7 @@ const idclass_t dvr_config_class = { .id = "file-permissions", .name = N_("File permissions (octal, e.g. 0664)"), .off = offsetof(dvr_config_t, dvr_muxcnf.m_file_permissions), + .opts = PO_EXPERT, .def.u32 = 0664, .group = 2, }, @@ -930,6 +943,7 @@ const idclass_t dvr_config_class = { .off = offsetof(dvr_config_t, dvr_charset), .set = dvr_config_class_charset_set, .list = dvr_config_class_charset_list, + .opts = PO_ADVANCED, .def.s = "UTF-8", .group = 2, }, @@ -938,6 +952,7 @@ const idclass_t dvr_config_class = { .id = "tag-files", .name = N_("Tag files with metadata"), .off = offsetof(dvr_config_t, dvr_tag_files), + .opts = PO_ADVANCED, .def.i = 1, .group = 2, }, @@ -946,6 +961,7 @@ const idclass_t dvr_config_class = { .id = "skip-commercials", .name = N_("Skip commercials"), .off = offsetof(dvr_config_t, dvr_skip_commercials), + .opts = PO_ADVANCED, .def.i = 1, .group = 2, }, @@ -955,6 +971,7 @@ const idclass_t dvr_config_class = { .name = N_("Format String"), .set = dvr_config_class_pathname_set, .off = offsetof(dvr_config_t, dvr_pathname), + .opts = PO_EXPERT, .group = 3, }, { @@ -962,6 +979,7 @@ const idclass_t dvr_config_class = { .id = "directory-permissions", .name = N_("Directory permissions (octal, e.g. 0775)"), .off = offsetof(dvr_config_t, dvr_muxcnf.m_directory_permissions), + .opts = PO_EXPERT, .def.u32 = 0775, .group = 4, }, @@ -970,6 +988,7 @@ const idclass_t dvr_config_class = { .id = "day-dir", .name = N_("Make subdirectories per day"), .off = offsetof(dvr_config_t, dvr_dir_per_day), + .opts = PO_EXPERT, .group = 4, }, { @@ -977,6 +996,7 @@ const idclass_t dvr_config_class = { .id = "channel-dir", .name = N_("Make subdirectories per channel"), .off = offsetof(dvr_config_t, dvr_channel_dir), + .opts = PO_EXPERT, .group = 4, }, { @@ -984,6 +1004,7 @@ const idclass_t dvr_config_class = { .id = "title-dir", .name = N_("Make subdirectories per title"), .off = offsetof(dvr_config_t, dvr_title_dir), + .opts = PO_EXPERT, .group = 4, }, { @@ -991,6 +1012,7 @@ const idclass_t dvr_config_class = { .id = "channel-in-title", .name = N_("Include channel name in filename"), .off = offsetof(dvr_config_t, dvr_channel_in_title), + .opts = PO_EXPERT, .group = 5, }, { @@ -998,6 +1020,7 @@ const idclass_t dvr_config_class = { .id = "date-in-title", .name = N_("Include date In filename"), .off = offsetof(dvr_config_t, dvr_date_in_title), + .opts = PO_EXPERT, .group = 5, }, { @@ -1005,6 +1028,7 @@ const idclass_t dvr_config_class = { .id = "time-in-title", .name = N_("Include time In filename"), .off = offsetof(dvr_config_t, dvr_time_in_title), + .opts = PO_EXPERT, .group = 5, }, { @@ -1012,6 +1036,7 @@ const idclass_t dvr_config_class = { .id = "episode-in-title", .name = N_("Include episode in filename"), .off = offsetof(dvr_config_t, dvr_episode_in_title), + .opts = PO_EXPERT, .group = 5, }, { @@ -1019,6 +1044,7 @@ const idclass_t dvr_config_class = { .id = "subtitle-in-title", .name = N_("Include subtitle in filename"), .off = offsetof(dvr_config_t, dvr_subtitle_in_title), + .opts = PO_EXPERT, .group = 6, }, { @@ -1026,6 +1052,7 @@ const idclass_t dvr_config_class = { .id = "omit-title", .name = N_("Don't include title in filename"), .off = offsetof(dvr_config_t, dvr_omit_title), + .opts = PO_EXPERT, .group = 6, }, { @@ -1033,6 +1060,7 @@ const idclass_t dvr_config_class = { .id = "clean-title", .name = N_("Remove all unsafe characters from filename"), .off = offsetof(dvr_config_t, dvr_clean_title), + .opts = PO_EXPERT, .group = 6, }, { @@ -1040,6 +1068,7 @@ const idclass_t dvr_config_class = { .id = "whitespace-in-title", .name = N_("Replace whitespace in title with '-'"), .off = offsetof(dvr_config_t, dvr_whitespace_in_title), + .opts = PO_EXPERT, .group = 6, }, { @@ -1047,6 +1076,7 @@ const idclass_t dvr_config_class = { .id = "windows-compatible-filenames", .name = N_("Use Windows-compatible filenames"), .off = offsetof(dvr_config_t, dvr_windows_compatible_filenames), + .opts = PO_EXPERT, .group = 6, }, {} diff --git a/src/webui/static/app/ext.css b/src/webui/static/app/ext.css index 7b2193652..93152bfab 100644 --- a/src/webui/static/app/ext.css +++ b/src/webui/static/app/ext.css @@ -168,6 +168,10 @@ background-image: url(../icons/find.png) !important; } +.uilevel { + background-image: url(../icons/application_form.png) !important; +} + .imdb { background-image: url(../icons/imdb.png) !important; } diff --git a/src/webui/static/app/idnode.js b/src/webui/static/app/idnode.js index 1d1f44352..1de95c14d 100644 --- a/src/webui/static/app/idnode.js +++ b/src/webui/static/app/idnode.js @@ -240,7 +240,8 @@ tvheadend.IdNodeField = function(conf) this.rdonly = conf.rdonly; this.wronly = conf.wronly; this.wronce = conf.wronce; - this.hidden = conf.hidden || conf.advanced; + this.hidden = conf.hidden; + this.uilevel = conf.expert ? 'expert' : (conf.advanced ? 'advanced' : 'basic'); this.password = conf.showpwd ? false : conf.password; this.duration = conf.duration; this.date = conf.date; @@ -275,7 +276,19 @@ tvheadend.IdNodeField = function(conf) st.un('load', callback); } - this.column = function(conf) + this.get_hidden = function(uilevel) { + var hidden = this.hidden; + console.log('init hidden for', this.id, ' is ', hidden); + if (uilevel !== 'expert') { + if (uilevel === 'advanced' && this.uilevel === 'expert') + hidden = true; + else if (uilevel === 'basic' && this.uilevel !== 'basic') + hidden = true; + } + return hidden; + } + + this.column = function(uilevel, conf) { var cfg = conf && this.id in conf ? conf[this.id] : {}; var w = 300; @@ -309,7 +322,7 @@ tvheadend.IdNodeField = function(conf) editor: this.editor({create: false}), renderer: cfg.renderer ? cfg.renderer(this.store) : this.renderer(this.store), editable: !this.rdonly, - hidden: this.hidden, + hidden: this.get_hidden(uilevel), filter: { type: ftype, dataIndex: this.id, @@ -560,6 +573,42 @@ tvheadend.IdNode = function(conf) }; }; +/* + * + */ +tvheadend.idnode_uilevel_text = function(uilevel) +{ + if (uilevel === 'basic') + return _('Basic'); + if (uilevel === 'advanced') + return _('Advanced'); + return _('Expert'); +} + +tvheadend.idnode_uilevel_change = function(button, uilevel) +{ + if (uilevel == 'basic') + uilevel = 'advanced'; + else if (uilevel == 'advanced') + uilevel = 'expert'; + else + uilevel = 'basic'; + button.setText(tvheadend.idnode_uilevel_text(uilevel)); + return uilevel; +} + +tvheadend.idnode_uilevel_button = function(uilevel, handler) +{ + var b = new Ext.Toolbar.Button({ + tooltip: _('Change the user interface level (basic, advanced, expert)'), + iconCls: 'uilevel', + text: tvheadend.idnode_uilevel_text(uilevel), + disabled: true, + handler: handler + }); + b.setDisabled(false); + return b; +} /* * Field editor @@ -758,7 +807,7 @@ tvheadend.idnode_editor_field = function(f, conf) /* * ID node editor form fields */ -tvheadend.idnode_editor_form = function(d, meta, panel, conf) +tvheadend.idnode_editor_form = function(uilevel, d, meta, panel, conf) { var af = []; var ef = []; @@ -800,6 +849,7 @@ tvheadend.idnode_editor_form = function(d, meta, panel, conf) }); } if (p.group && meta.groups) { + f.tvh_uilevel = p.expert ? 'expert' : (p.advanced ? 'advanced' : 'basic'); if (!groups) groups = {}; if (!(p.group in groups)) @@ -807,14 +857,20 @@ tvheadend.idnode_editor_form = function(d, meta, panel, conf) else groups[p.group].push(f); } else { - if (p.rdonly) - rf.push(f); - else if (p.expert) - ef.push(f); - else if (p.advanced) - af.push(f); - else + if (p.rdonly) { + if (uilevel === 'expert' || (!p.advanced && !p.expert)) + rf.push(f); + else if (p.advanced && p.advanced) + rf.push(f); + } else if (p.expert) { + if (uilevel === 'expert') + ef.push(f); + } else if (p.advanced) { + if (uilevel !== 'basic') + af.push(f); + } else { df.push(f); + } } } @@ -880,10 +936,28 @@ tvheadend.idnode_editor_form = function(d, meta, panel, conf) } for (var number in groups) { var g = groups[number]; - for (var i = 0; i < g.length; i++) - cfs[number].add(g[i]); - if (number in mfs) + var cnt = 0; + for (var i = 0; i < g.length; i++) { + var f = g[i]; + var hide = false; + if (uilevel == 'basic') { + hide = f.tvh_uilevel !== 'basic'; + } else if (uilevel == 'advanced') { + hide = f.tvh_uilevel === 'expert'; + } + if (hide) + f.setVisible(false); + else + cnt++; + cfs[number].add(f); + } + if (!cnt) + cfs[number].setVisible(false); + if (number in mfs) { panel.add(mfs[number]); + if (!cnt) + mfs[number].setVisible(false); + } } } if (df.length && !af.length && !rf.length) { @@ -919,10 +993,25 @@ tvheadend.idnode_editor_form = function(d, meta, panel, conf) /* * ID node editor panel */ -tvheadend.idnode_editor = function(item, conf) +tvheadend.idnode_editor = function(_uilevel, item, conf) { var panel = null; var buttons = []; + var uilevel = _uilevel; + + function destroy() { + panel.removeAll(); + } + + function build() { + var c = { + showpwd: conf.showpwd, + uuids: conf.uuids, + labelWidth: conf.labelWidth || 200 + }; + + tvheadend.idnode_editor_form(uilevel, item.props || item.params, item.meta, panel, c); + } /* Buttons */ if (!conf.noButtons) { @@ -983,12 +1072,23 @@ tvheadend.idnode_editor = function(item, conf) buttons.push(applyBtn); } + var uilevelBtn = tvheadend.idnode_uilevel_button(uilevel, function() { + uilevel = tvheadend.idnode_uilevel_change(uilevelBtn, uilevel); + var values = panel.getForm().getFieldValues(); + destroy(); + build(); + panel.getForm().setValues(values); + }); + buttons.push('-'); + buttons.push(uilevelBtn); + if (conf.help) { var helpBtn = new Ext.Button({ text: _('Help'), iconCls: 'help', handler: conf.help }); + buttons.push('-'); buttons.push(helpBtn); } } @@ -1009,12 +1109,7 @@ tvheadend.idnode_editor = function(item, conf) buttons: buttons }); - var c = { - showpwd: conf.showpwd, - uuids: conf.uuids, - labelWidth: conf.labelWidth || 200 - }; - tvheadend.idnode_editor_form(item.props || item.params, item.meta, panel, c); + build(); return panel; }; @@ -1028,6 +1123,7 @@ tvheadend.idnode_create = function(conf, onlyDefault) var panel = null; var win = null; var pclass = null; + var uilevel = tvheadend.uilevel; /* Buttons */ var saveBtn = new Ext.Button({ @@ -1138,7 +1234,7 @@ tvheadend.idnode_create = function(conf, onlyDefault) pclass = r.get(conf.select.valueField); win.setTitle(String.format(_('Add {0}'), s.lastSelectionText)); panel.remove(s); - tvheadend.idnode_editor_form(d, null, panel, { create: true, showpwd: true }); + tvheadend.idnode_editor_form(uilevel, d, null, panel, { create: true, showpwd: true }); saveBtn.setVisible(true); applyBtn.setVisible(true); win.setOriginSize(true); @@ -1155,7 +1251,7 @@ tvheadend.idnode_create = function(conf, onlyDefault) success: function(d) { panel.remove(s); d = json_decode(d); - tvheadend.idnode_editor_form(d.props, d, panel, { create: true, showpwd: true }); + tvheadend.idnode_editor_form(uilevel, d.props, d, panel, { create: true, showpwd: true }); saveBtn.setVisible(true); applyBtn.setVisible(true); win.setOriginSize(true); @@ -1188,7 +1284,7 @@ tvheadend.idnode_create = function(conf, onlyDefault) params: conf.params, success: function(d) { d = json_decode(d); - tvheadend.idnode_editor_form(d.props, d, panel, { create: true, showpwd: true }); + tvheadend.idnode_editor_form(uilevel, d.props, d, panel, { create: true, showpwd: true }); if (onlyDefault) { saveBtn.handler(); panel.destroy(); @@ -1266,9 +1362,11 @@ tvheadend.idnode_grid = function(panel, conf) var columns = []; var filters = []; var fields = []; + var ifields = []; var buttons = []; var abuttons = {}; var plugins = conf.plugins ? conf.plugins.slice() : []; + var uilevel = tvheadend.uilevel; /* Some copies */ if (conf.add && !conf.add.titleS && conf.titleS) @@ -1283,8 +1381,9 @@ tvheadend.idnode_grid = function(panel, conf) idnode = new tvheadend.IdNode(d); for (var i = 0; i < idnode.length(); i++) { var f = idnode.field(i); - var c = f.column(conf.columns); + var c = f.column(uilevel, conf.columns); fields.push(f.id); + ifields.push(f); c['tooltip'] = f.text; columns.push(c); if (c.filter) @@ -1555,7 +1654,7 @@ tvheadend.idnode_grid = function(panel, conf) } else { var title = String.format(_('Edit {0}'), conf.titleS); } - var p = tvheadend.idnode_editor(d[0], c); + var p = tvheadend.idnode_editor(uilevel, d[0], c); var width = p.fixedWidth; w = new Ext.ux.Window({ title: title, @@ -1672,6 +1771,17 @@ tvheadend.idnode_grid = function(panel, conf) } } + abuttons.uilevel = tvheadend.idnode_uilevel_button(uilevel, function () { + uilevel = tvheadend.idnode_uilevel_change(abuttons.uilevel, uilevel); + for (var i = 0; i < ifields.length; i++) { + var h = ifields[i].get_hidden(uilevel); + console.log('idx', i, 'hidden', h); + model.setHidden(model.findColumnIndex(ifields[i].id), h); + } + }); + buttons.push('-'); + buttons.push(abuttons.uilevel); + /* Help */ if (conf.help) { buttons.push('->'); @@ -1808,6 +1918,7 @@ tvheadend.idnode_form_grid = function(panel, conf) var plugins = conf.plugins ? conf.plugins.slice() : []; var current = null; var selectuuid = null; + var uilevel = tvheadend.uilevel; /* Store */ var listurl = conf.list ? conf.list.url : null; @@ -2028,6 +2139,19 @@ tvheadend.idnode_form_grid = function(panel, conf) } } + abuttons.uilevel = tvheadend.idnode_uilevel_button(uilevel, function () { + uilevel = tvheadend.idnode_uilevel_change(abuttons.uilevel, uilevel); + var values = null; + if (current) + values = current.editor.getForm().getFieldValues(); + roweditor_destroy(); + roweditor(select.getSelected()); + if (values && current) + current.editor.getForm().setValues(values); + }); + buttons.push('-'); + buttons.push(abuttons.uilevel); + /* Help */ if (conf.help) { buttons.push('->'); @@ -2058,7 +2182,7 @@ tvheadend.idnode_form_grid = function(panel, conf) success: function(d) { d = json_decode(d); roweditor_destroy(); - var editor = new tvheadend.idnode_editor(d[0], { + var editor = new tvheadend.idnode_editor(uilevel, d[0], { title: _('Parameters'), labelWidth: 300, fixedHeight: true, @@ -2197,6 +2321,7 @@ tvheadend.idnode_tree = function(panel, conf) var current = null; var uuid = null; var params = conf.params || {}; + var uilevel = tvheadend.uilevel; var loader = new Ext.tree.TreeLoader({ dataUrl: conf.url, baseParams: params, @@ -2244,7 +2369,7 @@ tvheadend.idnode_tree = function(panel, conf) } if (!n.isRoot) { uuid = n.attributes.uuid; - current = new tvheadend.idnode_editor(n.attributes, { + current = new tvheadend.idnode_editor(uilevel, n.attributes, { title: _('Parameters'), width: 550, noautoWidth: true, @@ -2334,6 +2459,51 @@ tvheadend.idnode_simple = function(panel, conf) var buttons = []; var abuttons = {}; var current = null; + var uilevel = tvheadend.uilevel; + var lastdata = null; + + function fonchange(f, o, n) { + if (current) + conf.onchange(current, f, o, n); + } + + function form_build(d) { + + var fpanel = new Ext.form.FormPanel({ + frame: true, + border: true, + bodyStyle: 'padding: 5px', + labelAlign: 'left', + labelWidth: conf.labelWidth || 300, + autoWidth: false, + autoHeight: false, + width: conf.nowidth ? null : (conf.width || 730), + defaultType: 'textfield', + buttonAlign: 'left', + autoScroll: true + }); + + tvheadend.idnode_editor_form(uilevel, d.props || d.params, d.meta, + fpanel, { showpwd: conf.showpwd }); + + if (conf.onchange) { + var f = fpanel.getForm().items; + for (var i = 0; i < f.items.length; i++) { + var it = f.items[i]; + it.on('check', fonchange); + it.on('change', fonchange); + } + } + lastdata = d; + return fpanel; + + } + + function form_destroy() { + if (current) + mpanel.remove(current); + current = null; + } /* Top bar */ abuttons.save = new Ext.Toolbar.Button({ @@ -2367,6 +2537,25 @@ tvheadend.idnode_simple = function(panel, conf) }); buttons.push(abuttons.undo); + abuttons.uilevel = tvheadend.idnode_uilevel_button(uilevel, function () { + uilevel = tvheadend.idnode_uilevel_change(abuttons.uilevel, uilevel); + var values = null; + if (current) + values = current.getForm().getFieldValues(); + form_destroy(); + if (lastdata) { + current = form_build(lastdata); + if (values && current) + current.getForm().setValues(values); + if (current) { + mpanel.add(current); + mpanel.doLayout(); + } + } + }); + buttons.push('-'); + buttons.push(abuttons.uilevel); + /* Extra buttons */ if (conf.tbar) { buttons.push('-'); @@ -2397,48 +2586,6 @@ tvheadend.idnode_simple = function(panel, conf) }); } - function fonchange(f, o, n) { - if (current) - conf.onchange(current, f, o, n); - } - - function form_build(d) { - - var fpanel = new Ext.form.FormPanel({ - frame: true, - border: true, - bodyStyle: 'padding: 5px', - labelAlign: 'left', - labelWidth: conf.labelWidth || 300, - autoWidth: false, - autoHeight: false, - width: conf.nowidth ? null : (conf.width || 730), - defaultType: 'textfield', - buttonAlign: 'left', - autoScroll: true - }); - - tvheadend.idnode_editor_form(d.props || d.params, d.meta, - fpanel, { showpwd: conf.showpwd }); - - if (conf.onchange) { - var f = fpanel.getForm().items; - for (var i = 0; i < f.items.length; i++) { - var it = f.items[i]; - it.on('check', fonchange); - it.on('change', fonchange); - } - } - return fpanel; - - } - - function form_destroy() { - if (current) - mpanel.remove(current); - current = null; - } - function form_load(force) { if (!force && current) return; @@ -2453,8 +2600,6 @@ tvheadend.idnode_simple = function(panel, conf) current = new form_build(d[0]); abuttons.save.setDisabled(false); abuttons.undo.setDisabled(false); - if (abuttons.del) - abuttons.del.setDisabled(false); mpanel.add(current); mpanel.doLayout(); } diff --git a/src/webui/static/app/tvheadend.js b/src/webui/static/app/tvheadend.js index 304455b8f..707ac27fc 100644 --- a/src/webui/static/app/tvheadend.js +++ b/src/webui/static/app/tvheadend.js @@ -3,6 +3,7 @@ tvheadend.accessupdate = null; tvheadend.capabilities = null; tvheadend.admin = false; tvheadend.dialog = null; +tvheadend.uilevel = 'expert'; tvheadend.cookieProvider = new Ext.state.CookieProvider({ // 7 days from now @@ -405,6 +406,8 @@ function accessUpdate(o) { return; tvheadend.admin = o.admin == true; + if (o.uilevel) + tvheadend.uilevel = o.uilevel; if ('info_area' in o) tvheadend.rootTabPanel.setInfoArea(o.info_area); diff --git a/src/webui/static/icons/application_form.png b/src/webui/static/icons/application_form.png new file mode 120000 index 000000000..99dd638f0 --- /dev/null +++ b/src/webui/static/icons/application_form.png @@ -0,0 +1 @@ +../../../../vendor/famfamsilk/application_form.png \ No newline at end of file