aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Manning <tamanning@zoho.com>2016-05-04 21:26:52 -0400
committerAndrew Manning <tamanning@zoho.com>2016-05-04 21:26:52 -0400
commit8cb06e7af8c3a14a6513d2aee2beba091f3ecfb5 (patch)
treeee9fc7e669c86c6c1ddf1ab9e5e0443d2b02a209
parente4a2aacd1d2f852264319aff848257349575131e (diff)
parent8c9a773a90fc331f0b4d6ce44119abe1278fd8ea (diff)
downloadvolse-hubzilla-8cb06e7af8c3a14a6513d2aee2beba091f3ecfb5.tar.gz
volse-hubzilla-8cb06e7af8c3a14a6513d2aee2beba091f3ecfb5.tar.bz2
volse-hubzilla-8cb06e7af8c3a14a6513d2aee2beba091f3ecfb5.zip
Merge remote-tracking branch 'upstream/dev' into plugin-repo
-rw-r--r--Zotlabs/Module/Appman.php6
-rw-r--r--Zotlabs/Module/Apps.php7
-rw-r--r--Zotlabs/Module/Channel.php10
-rw-r--r--Zotlabs/Module/Editblock.php74
-rw-r--r--Zotlabs/Module/Network.php12
-rw-r--r--app/bookmarks.apd2
-rw-r--r--app/chat.apd2
-rw-r--r--app/probe.apd2
-rw-r--r--app/profile.apd2
-rw-r--r--app/suggest.apd2
-rw-r--r--doc/acl_dialog_post.html13
-rw-r--r--include/acl_selectors.php27
-rw-r--r--include/apps.php84
-rw-r--r--include/widgets.php4
-rw-r--r--view/js/acl.js37
-rw-r--r--view/theme/redbasic/css/style.css67
-rwxr-xr-xview/tpl/acl_selector.tpl29
-rw-r--r--view/tpl/app_create.tpl4
-rw-r--r--view/tpl/app_select.tpl4
19 files changed, 296 insertions, 92 deletions
diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php
index 96e4cdd87..b0dd887f4 100644
--- a/Zotlabs/Module/Appman.php
+++ b/Zotlabs/Module/Appman.php
@@ -23,6 +23,8 @@ class Appman extends \Zotlabs\Web\Controller {
'photo' => escape_tags($_REQUEST['photo']),
'version' => escape_tags($_REQUEST['version']),
'price' => escape_tags($_REQUEST['price']),
+ 'requires' => escape_tags($_REQUEST['requires']),
+ 'system' => intval($_REQUEST['system']),
'sig' => escape_tags($_REQUEST['sig'])
);
@@ -64,7 +66,7 @@ class Appman extends \Zotlabs\Web\Controller {
}
- function get() {
+ function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
@@ -99,6 +101,8 @@ class Appman extends \Zotlabs\Web\Controller {
'$version' => array('version', t('Version ID'),(($app) ? $app['app_version'] : ''), ''),
'$price' => array('price', t('Price of app'),(($app) ? $app['app_price'] : ''), ''),
'$page' => array('page', t('Location (URL) to purchase app'),(($app) ? $app['app_page'] : ''), ''),
+ '$system' => (($app) ? intval($app['app_system']) : 0),
+ '$requires' => (($app) ? $app['app_requires'] : ''),
'$embed' => $embed,
'$submit' => t('Submit')
));
diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php
index 4066966ca..ea6ab1913 100644
--- a/Zotlabs/Module/Apps.php
+++ b/Zotlabs/Module/Apps.php
@@ -17,16 +17,21 @@ class Apps extends \Zotlabs\Web\Controller {
$apps = array();
- $syslist = get_system_apps();
if(local_channel()) {
+ import_system_apps();
+ $syslist = array();
$list = app_list(local_channel());
if($list) {
foreach($list as $x) {
$syslist[] = app_encode($x);
}
}
+ translate_system_apps($syslist);
}
+ else
+ $syslist = get_system_apps(true);
+
usort($syslist,'app_name_compare');
// logger('apps: ' . print_r($syslist,true));
diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php
index 36f13e775..d0c6d83d8 100644
--- a/Zotlabs/Module/Channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -126,13 +126,21 @@ function get($update = 0, $load = false) {
if($perms['post_wall']) {
+ // I'm trying to make two points in this description text - warn about finality of wall
+ // post permissions, and try to clear up confusion that these permissions set who is
+ // *shown* the post, istead of who is able to see the post, i.e. make it clear that clicking
+ // the "Show" button on a group does not post it to the feed of people in that group, it
+ // mearly allows those people to view the post if they are viewing/following this channel.
+ $aclDesc = t('Post permissions <b>cannot be changed</b> after a post is sent.</br />These permissions set who is allowed to view the post.');
+ $aclContextHelpCmd = 'acl_dialog_post';
+
$x = array(
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(\App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
'default_location' => (($is_owner) ? \App::$profile['channel_location'] : ''),
'nickname' => \App::$profile['channel_address'],
'lockstate' => (((strlen(\App::$profile['channel_allow_cid'])) || (strlen(\App::$profile['channel_allow_gid'])) || (strlen(\App::$profile['channel_deny_cid'])) || (strlen(\App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
- 'acl' => (($is_owner) ? populate_acl($channel_acl,true,((\App::$profile['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')) : ''),
+ 'acl' => (($is_owner) ? populate_acl($channel_acl,true,((\App::$profile['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : ''), $aclDesc, $aclContextHelpCmd) : ''),
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
diff --git a/Zotlabs/Module/Editblock.php b/Zotlabs/Module/Editblock.php
index 2821b3fe0..0204d0994 100644
--- a/Zotlabs/Module/Editblock.php
+++ b/Zotlabs/Module/Editblock.php
@@ -4,46 +4,43 @@ namespace Zotlabs\Module;
require_once('include/identity.php');
require_once('include/acl_selectors.php');
-
class Editblock extends \Zotlabs\Web\Controller {
function init() {
-
+
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
-
+
if(argc() > 1)
$which = argv(1);
else
return;
-
+
profile_load($a,$which);
-
+
}
-
-
-
- function get() {
-
+
+ function get() {
+
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
-
+
$which = argv(1);
-
+
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
-
+
$channel = \App::get_channel();
-
+
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
@@ -52,7 +49,7 @@ class Editblock extends \Zotlabs\Web\Controller {
$observer = $sys;
}
}
-
+
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
@@ -62,27 +59,26 @@ class Editblock extends \Zotlabs\Web\Controller {
$owner = intval($r[0]['channel_id']);
}
}
-
+
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
-
+
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
-
+
$is_owner = (($uid && $uid == $owner) ? true : false);
-
+
$o = '';
-
+
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
-
-
+
if(! ($post_id && $owner)) {
notice( t('Item not found') . EOL);
return;
}
-
+
$itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1",
intval($post_id),
intval($owner)
@@ -98,20 +94,20 @@ class Editblock extends \Zotlabs\Web\Controller {
notice( t('Item not found') . EOL);
return;
}
-
+
$plaintext = true;
-
+
$mimeselect = '';
$mimetype = $itm[0]['mimetype'];
-
+
if($mimetype != 'text/bbcode')
$plaintext = true;
-
+
if(get_config('system','page_mimetype'))
- $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
+ $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
else
$mimeselect = mimetype_select($itm[0]['uid'],$mimetype);
-
+
\App::$page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array(
'$baseurl' => z_root(),
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
@@ -122,17 +118,17 @@ class Editblock extends \Zotlabs\Web\Controller {
'$confirmdelete' => t('Delete block?'),
'$bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : 'comanche-block')
));
-
+
$tpl = get_markup_template("jot.tpl");
-
+
$jotplugins = '';
$jotnets = '';
-
+
call_hooks('jot_tool', $jotplugins);
call_hooks('jot_networks', $jotnets);
-
+
$rp = 'blocks/' . $channel['channel_address'];
-
+
$editor = replace_macros($tpl,array(
'$return_path' => $rp,
'$action' => 'item',
@@ -174,18 +170,16 @@ class Editblock extends \Zotlabs\Web\Controller {
'$defexpire' => '',
'$bbcode' => (($mimetype == 'text/bbcode') ? true : false)
));
-
+
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Block'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$editor' => $editor
));
-
+
return $o;
-
+
}
-
-
-
+
}
diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php
index 77353da05..e4b936dc2 100644
--- a/Zotlabs/Module/Network.php
+++ b/Zotlabs/Module/Network.php
@@ -154,6 +154,14 @@ class Network extends \Zotlabs\Web\Controller {
}
nav_set_selected('network');
+
+ // I'm trying to make two points in this description text - warn about finality of wall
+ // post permissions, and try to clear up confusion that these permissions set who is
+ // *shown* the post, istead of who is able to see the post, i.e. make it clear that clicking
+ // the "Show" button on a group does not post it to the feed of people in that group, it
+ // mearly allows those people to view the post if they are viewing/following this channel.
+ $aclDesc = t('Post permissions <b>cannot be changed</b> after a post is sent.</br />These permissions set who is allowed to view the post.');
+ $aclContextHelpCmd = 'acl_dialog_post';
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
@@ -161,7 +169,7 @@ class Network extends \Zotlabs\Web\Controller {
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
-
+
$private_editing = ((($group || $cid) && (! intval($_GET['pf']))) ? true : false);
$x = array(
@@ -170,7 +178,7 @@ class Network extends \Zotlabs\Web\Controller {
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
- 'acl' => populate_acl((($private_editing) ? $def_acl : $channel_acl), true, (($channel['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : '')),
+ 'acl' => populate_acl((($private_editing) ? $def_acl : $channel_acl), true, (($channel['channel_r_stream'] & PERMS_PUBLIC) ? t('Public') : ''), $aclDesc, $aclContextHelpCmd),
'bang' => (($private_editing) ? '!' : ''),
'visitor' => true,
'profile_uid' => local_channel(),
diff --git a/app/bookmarks.apd b/app/bookmarks.apd
index 9581a220c..2a04d9bf3 100644
--- a/app/bookmarks.apd
+++ b/app/bookmarks.apd
@@ -1,4 +1,4 @@
url: $baseurl/bookmarks
requires: local_channel
-name: View bookmarks
+name: View Bookmarks
photo: $baseurl/app/bookmarks.png
diff --git a/app/chat.apd b/app/chat.apd
index d4879c0b7..7ba1cd2c8 100644
--- a/app/chat.apd
+++ b/app/chat.apd
@@ -1,4 +1,4 @@
url: $baseurl/chat/$nick
requires: local_channel
-name: My chatrooms
+name: My Chatrooms
photo: $baseurl/app/chat.png
diff --git a/app/probe.apd b/app/probe.apd
index e1ab5fc43..910e628ba 100644
--- a/app/probe.apd
+++ b/app/probe.apd
@@ -1,4 +1,4 @@
url: $baseurl/probe
requires: local_channel
-name: Remote diagnostics
+name: Remote Diagnostics
photo: $baseurl/app/probe.png
diff --git a/app/profile.apd b/app/profile.apd
index d353d5742..48e5d5814 100644
--- a/app/profile.apd
+++ b/app/profile.apd
@@ -1,4 +1,4 @@
url: $baseurl/profile/$nick
requires: local_channel
-name: View profile
+name: View Profile
photo: $baseurl/app/profile.png
diff --git a/app/suggest.apd b/app/suggest.apd
index f3d17e0ea..cd94a6d1f 100644
--- a/app/suggest.apd
+++ b/app/suggest.apd
@@ -1,4 +1,4 @@
url: $baseurl/suggest
requires: local_channel
-name: Suggest channels
+name: Suggest Channels
photo: $baseurl/app/suggest.png
diff --git a/doc/acl_dialog_post.html b/doc/acl_dialog_post.html
new file mode 100644
index 000000000..19c366419
--- /dev/null
+++ b/doc/acl_dialog_post.html
@@ -0,0 +1,13 @@
+<!-- Network and channel posts cannot change their permissions after being sent, this help
+ file is for items of that nature. Files and photos etc should use a different help file. -->
+
+<h2>Post Permissions</h2>
+
+<p>Sometimes called Access Control List, or ACL, the permissions set who is able to see your new post.</p>
+
+<p>Pressing the ACL button (<i class="fa fa-lock"></i> or <i class="fa fa-unlock"></i>) beside the Submit button will display a dialog in which you can select what channels and/or privacy groups can see the post. You can also select who is explicitly denied access. For example, say you are planning a surprise party for a friend. You can send an invitation post to everyone in your <b>Friends</b> group <i>except</i> the friend you are surprising. In this case you "Show" the <b>Friends</b> group but "Don't show" that one person.
+
+<h3>Why can't I edit a post's permissions after I saved it?</h3>
+
+<p>You are able to change permissons to your files, photos and the likes, but not to posts after you have saved them. The main reason is: Once you have saved a post it is being distributed either to the public channel and from there to other Hubzilla servers or to those you intended it to go. Just like you cannot reclaim something you gave to another person, you cannot change permissions to Hubzilla posts. We would need to track everywhere your posting goes, keep track of everyone you allowed to see it and then keep track of from whom to delete it.</p>
+<p>If a posting is public this is even harder, as the Hubzilla is a global network and there is no way to follow a post, let alone reclaim it reliably. Other networks that may receive your post have no reliable way to delete or reclaim the post.</p> \ No newline at end of file
diff --git a/include/acl_selectors.php b/include/acl_selectors.php
index 92f9436a2..584a70142 100644
--- a/include/acl_selectors.php
+++ b/include/acl_selectors.php
@@ -210,12 +210,24 @@ function fixacl(&$item) {
$item = str_replace(array('<','>'),array('',''),$item);
}
-function populate_acl($defaults = null,$show_jotnets = true, $showall = '') {
+/**
+* Builds a modal dialog for editing permissions, using acl_selector.tpl as the template.
+*
+* @param array $default Optional access control list for the initial state of the dialog.
+* @param boolean $show_jotnets Whether plugins for federated networks should be included in the permissions dialog
+* @param string $showall_caption An optional caption to describe the scope of an unrestricted post. e.g. "Public"
+* @param string $dialog_description Optional message to include at the top of the dialog. E.g. "Warning: Post permissions cannot be changed once sent".
+* @param string $context_help Allows the dialog to present a help icon. E.g. "acl_dialog_post"
+* @param boolean $readonly Not implemented yet. When implemented, the dialog will use acl_readonly.tpl instead, so that permissions may be viewed for posts that can no longer have their permissions changed.
+*
+* @return string html modal dialog build from acl_selector.tpl
+*/
+function populate_acl($defaults = null,$show_jotnets = true, $showall_caption = '', $dialog_description = '', $context_help = '', $readonly = false) {
$allow_cid = $allow_gid = $deny_cid = $deny_gid = false;
- if(! $showall)
- $showall = t('Visible to your default audience');
+ if(! $showall_caption)
+ $showall_caption = t('Visible to your default audience');
if(is_array($defaults)) {
$allow_cid = ((strlen($defaults['allow_cid']))
@@ -239,9 +251,12 @@ function populate_acl($defaults = null,$show_jotnets = true, $showall = '') {
$tpl = get_markup_template("acl_selector.tpl");
$o = replace_macros($tpl, array(
- '$showall' => $showall,
+ '$showall' => $showall_caption,
+ '$showlimited' => t("Limit access:"),
+ '$showlimitedDesc' => t('Select "Show" to allow viewing. "Don\'t show" lets you override and limit the scope of "Show".'),
'$show' => t("Show"),
'$hide' => t("Don't show"),
+ '$search' => t("Search"),
'$allowcid' => json_encode($allow_cid),
'$allowgid' => json_encode($allow_gid),
'$denycid' => json_encode($deny_cid),
@@ -249,7 +264,9 @@ function populate_acl($defaults = null,$show_jotnets = true, $showall = '') {
'$jnetModalTitle' => t('Other networks and post services'),
'$jotnets' => $jotnets,
'$aclModalTitle' => t('Permissions'),
- '$aclModalDismiss' => t('Close')
+ '$aclModalDesc' => $dialog_description,
+ '$aclModalDismiss' => t('Close'),
+ '$helpUrl' => (($context_help == '') ? '' : (z_root() . '/help/' . $context_help))
));
return $o;
diff --git a/include/apps.php b/include/apps.php
index dca49a3c6..30fed361d 100644
--- a/include/apps.php
+++ b/include/apps.php
@@ -8,7 +8,7 @@
require_once('include/plugin.php');
require_once('include/identity.php');
-function get_system_apps() {
+function get_system_apps($translate = true) {
$ret = array();
if(is_dir('apps'))
@@ -17,7 +17,7 @@ function get_system_apps() {
$files = glob('app/*.apd');
if($files) {
foreach($files as $f) {
- $x = parse_app_description($f);
+ $x = parse_app_description($f,$translate);
if($x) {
$ret[] = $x;
}
@@ -28,7 +28,7 @@ function get_system_apps() {
foreach($files as $f) {
$n = basename($f,'.apd');
if(plugin_is_installed($n)) {
- $x = parse_app_description($f);
+ $x = parse_app_description($f,$translate);
if($x) {
$ret[] = $x;
}
@@ -40,11 +40,36 @@ function get_system_apps() {
}
+
+function import_system_apps() {
+ if(! local_channel())
+ return;
+
+ // Eventually we want to look at modification dates and update system apps.
+
+ $installed = get_pconfig(local_channel(),'system','apps_installed');
+ if($installed)
+ return;
+ $apps = get_system_apps(false);
+ if($apps) {
+ foreach($apps as $app) {
+ $app['uid'] = local_channel();
+ $app['guid'] = hash('whirlpool',$app['name']);
+ $app['system'] = 1;
+ app_install(local_channel(),$app);
+ }
+ }
+ set_pconfig(local_channel(),'system','apps_installed',1);
+}
+
+
+
+
function app_name_compare($a,$b) {
return strcmp($a['name'],$b['name']);
}
-function parse_app_description($f) {
+function parse_app_description($f,$translate = true) {
$ret = array();
$baseurl = z_root();
@@ -116,7 +141,8 @@ function parse_app_description($f) {
}
}
if($ret) {
- translate_system_apps($ret);
+ if($translate)
+ translate_system_apps($ret);
return $ret;
}
return false;
@@ -126,8 +152,13 @@ function parse_app_description($f) {
function translate_system_apps(&$arr) {
$apps = array(
'Site Admin' => t('Site Admin'),
- 'Bookmarks' => t('Bookmarks'),
- 'Address Book' => t('Address Book'),
+ 'Bug Report' => t('Bug Report'),
+ 'View Bookmarks' => t('View Bookmarks'),
+ 'My Chatrooms' => t('My Chatrooms'),
+ 'Connections' => t('Connections'),
+ 'Firefox Share' => t('Firefox Share'),
+ 'Remote Diagnostics' => t('Remote Diagnostics'),
+ 'Suggest Channels' => t('Suggest Channels'),
'Login' => t('Login'),
'Channel Manager' => t('Channel Manager'),
'Grid' => t('Grid'),
@@ -135,7 +166,7 @@ function translate_system_apps(&$arr) {
'Files' => t('Files'),
'Webpages' => t('Webpages'),
'Channel Home' => t('Channel Home'),
- 'Profile' => t('Profile'),
+ 'View Profile' => t('View Profile'),
'Photos' => t('Photos'),
'Events' => t('Events'),
'Directory' => t('Directory'),
@@ -293,11 +324,18 @@ function app_destroy($uid,$app) {
);
$x[0]['app_deleted'] = 1;
-
- $r = q("delete from app where app_id = '%s' and app_channel = %d",
- dbesc($app['guid']),
- intval($uid)
- );
+ if($x[0]['app_system']) {
+ $r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
+ dbesc($app['guid']),
+ intval($uid)
+ );
+ }
+ else {
+ $r = q("delete from app where app_id = '%s' and app_channel = %d",
+ dbesc($app['guid']),
+ intval($uid)
+ );
+ }
build_sync_packet($uid,array('app' => $x));
}
@@ -370,10 +408,12 @@ function app_store($arr) {
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
+ $darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
+ $darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
$created = datetime_convert();
- $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
+ $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited, app_system, app_deleted ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
dbesc($darray['app_id']),
dbesc($darray['app_sig']),
dbesc($darray['app_author']),
@@ -388,7 +428,9 @@ function app_store($arr) {
dbesc($darray['app_page']),
dbesc($darray['app_requires']),
dbesc($created),
- dbesc($created)
+ dbesc($created),
+ intval($darray['app_system']),
+ intval($darray['app_deleted'])
);
if($r) {
$ret['success'] = true;
@@ -425,10 +467,12 @@ function app_update($arr) {
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
+ $darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
+ $darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
$edited = datetime_convert();
- $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s' where app_id = '%s' and app_channel = %d",
+ $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s', app_system = %d, app_deleted = %d where app_id = '%s' and app_channel = %d",
dbesc($darray['app_sig']),
dbesc($darray['app_author']),
dbesc($darray['app_name']),
@@ -441,6 +485,8 @@ function app_update($arr) {
dbesc($darray['app_page']),
dbesc($darray['app_requires']),
dbesc($edited),
+ intval($darray['app_system']),
+ intval($darray['app_deleted']),
dbesc($darray['app_id']),
intval($darray['app_channel'])
);
@@ -499,6 +545,12 @@ function app_encode($app,$embed = false) {
if($app['app_requires'])
$ret['requires'] = $app['app_requires'];
+ if($app['app_system'])
+ $ret['system'] = $app['app_system'];
+
+ if($app['app_deleted'])
+ $ret['deleted'] = $app['app_deleted'];
+
if(! $embed)
return $ret;
diff --git a/include/widgets.php b/include/widgets.php
index fa92901ae..1b9d3c07a 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -103,8 +103,8 @@ function widget_appselect($arr) {
'$system' => t('System'),
'$authed' => ((local_channel()) ? true : false),
'$personal' => t('Personal'),
- '$new' => t('Create Personal App'),
- '$edit' => t('Edit Personal App')
+ '$new' => t('New App'),
+ '$edit' => t('Edit App')
));
}
diff --git a/view/js/acl.js b/view/js/acl.js
index be215fc91..162ada764 100644
--- a/view/js/acl.js
+++ b/view/js/acl.js
@@ -14,8 +14,9 @@ function ACL(backend_url, preset) {
that.nw = 4; //items per row. should be calulated from #acl-list.width
that.list_content = $("#acl-list-content");
- that.item_tpl = unescape($(".acl-list-item[rel=acl-template]").html());
- that.showall = $("#acl-showall");
+ that.item_tpl = unescape($(".acl-list-item[rel=acl-template]").html());
+ that.showall = $("#acl-showall");
+ that.showlimited = $("#acl-showlimited");
// set the initial ACL lists in case the enclosing form gets submitted before the ajax loader completes.
that.on_submit();
@@ -26,6 +27,7 @@ function ACL(backend_url, preset) {
$(document).ready(function() {
that.showall.click(that.on_showall);
+ that.showlimited.click(that.on_showlimited);
$(document).on('click','.acl-button-show',that.on_button_show);
$(document).on('click','.acl-button-hide',that.on_button_hide);
$("#acl-search").keypress(that.on_search);
@@ -71,7 +73,8 @@ ACL.prototype.on_search = function(event) {
};
ACL.prototype.on_showall = function(event) {
- event.preventDefault();
+
+ // preventDefault() isn't called here as we want state changes from update_view() to be applied to the radiobutton
event.stopPropagation();
if (that.showall.hasClass("btn-warning")) {
@@ -87,9 +90,17 @@ ACL.prototype.on_showall = function(event) {
that.update_view();
that.on_submit();
- return false;
+ return true; // return true so that state changes from update_view() will be applied
};
+ACL.prototype.on_showlimited = function(event) {
+ // Prevent the radiobutton from being selected, as the showlimited radiobutton
+ // option is selected only by selecting show or hide options on channels or groups.
+ event.preventDefault();
+ event.stopPropagation();
+ return false;
+}
+
ACL.prototype.on_selectall = function(event) {
event.preventDefault();
event.stopPropagation();
@@ -188,18 +199,32 @@ ACL.prototype.set_deny = function(itemid) {
that.update_view();
};
+ACL.prototype.update_radiobuttons = function(isPublic) {
+
+ that.showall.prop('checked', isPublic);
+ that.showlimited.prop('checked', !isPublic);
+ that.showlimited.prop('disabled', isPublic);
+};
+
ACL.prototype.update_view = function() {
if (that.allow_gid.length === 0 && that.allow_cid.length === 0 &&
that.deny_gid.length === 0 && that.deny_cid.length === 0) {
+ // btn-warning indicates that the permissions are public, it was chosen because
+ // that.showall used to be a normal button, which btn-warning is a bootstrap style for.
that.showall.removeClass("btn-default").addClass("btn-warning");
+ that.update_radiobuttons(true);
+
/* jot acl */
- $('#jot-perms-icon').removeClass('fa-lock').addClass('fa-unlock');
+ $('#jot-perms-icon, #dialog-perms-icon').removeClass('fa-lock').addClass('fa-unlock');
$('#jot-public').show();
$('.profile-jot-net input').attr('disabled', false);
+
} else {
that.showall.removeClass("btn-warning").addClass("btn-default");
+ that.update_radiobuttons(false);
+
/* jot acl */
- $('#jot-perms-icon').removeClass('fa-unlock').addClass('fa-lock');
+ $('#jot-perms-icon, #dialog-perms-icon').removeClass('fa-unlock').addClass('fa-lock');
$('#jot-public').hide();
$('.profile-jot-net input').attr('disabled', 'disabled');
diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css
index 58f216029..48d93025b 100644
--- a/view/theme/redbasic/css/style.css
+++ b/view/theme/redbasic/css/style.css
@@ -912,19 +912,52 @@ a.rconnect:hover, a.rateme:hover, div.rateme:hover {
clear: both;
}
+.modal-header .contextual-help-tool {
+ /* Mostly duplicating ".modal-header .close" and ".close" layout settings from bootstrap */
+ float: right;
+ font-size: 21px;
+ padding: 0;
+ margin-top: -4px;
+ margin-right: 15px;
+ line-height: 1;
+}
+
#acl-search {
- margin-top: 20px;
- padding: 8px;
+ padding: 4px;
border: 1px solid #ccc;
- width: 100%;
+ width: 90%; /* fallback if browser does not support calc() */
+ width: calc(100% - 10px);
+ margin: 0px 0px 10px 10px;
}
#acl-search::-webkit-input-placeholder {
- font-family: FontAwesome;
+ /* non-fontawesome fonts set a fallback for text parts of the placeholder*/
+ font-family: FontAwesome, sans-serif, arial, freesans;
}
#acl-search::-moz-placeholder {
- font-family: FontAwesome;
+ /* non-fontawesome fonts set a fallback for text parts of the placeholder*/
+ font-family: FontAwesome, sans-serif, arial, freesans;
+}
+
+#aclModal .modal-body {
+ padding-top: 10px;
+}
+
+#acl-dialog-description {
+ font-size: 90%;
+ color: #888;
+ padding-bottom: 4px;
+}
+#acl-dialog-description b {
+ color: black;
+}
+
+#acl-showlimited-description {
+ font-size: 90%;
+ color: #888;
+ margin-left: 10px;
+ margin-bottom: 4px;
}
#acl-list {
@@ -933,11 +966,11 @@ a.rconnect:hover, a.rateme:hover, div.rateme:hover {
overflow: auto;
clear: both;
min-height: 62px;
- margin-top: 20px;
padding: 10px 10px 0px 0px;
-webkit-border-radius: $radiuspx ;
-moz-border-radius: $radiuspx;
border-radius: $radiuspx;
+ background-color: rgb(238,238,238);
}
#jotnets-wrapper, #jotnets-collapse {
@@ -957,6 +990,7 @@ a.rconnect:hover, a.rateme:hover, div.rateme:hover {
-webkit-border-radius: $radiuspx ;
-moz-border-radius: $radiuspx;
border-radius: $radiuspx;
+ background-color: white;
}
.acl-list-item.grouphide {
@@ -995,6 +1029,27 @@ a.rconnect:hover, a.rateme:hover, div.rateme:hover {
margin-left: 5px;
}
+#acl-showlimited-caption,
+#acl-showall-caption {
+ font-size: 115%;
+}
+
+#acl-radiowrapper-showall {
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+#acl-radiowrapper-showlimited {
+ margin-bottom: 0;
+}
+
+#acl-showall + i {
+ font-size: 140%;
+}
+
+#acl-showall-caption {
+ margin-left: 0.35em;
+}
+
.contact-block-content {
margin-top: 10px;
}
diff --git a/view/tpl/acl_selector.tpl b/view/tpl/acl_selector.tpl
index e57fdba12..a3fe73d0c 100755
--- a/view/tpl/acl_selector.tpl
+++ b/view/tpl/acl_selector.tpl
@@ -3,9 +3,15 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
- <h4 class="modal-title">{{$aclModalTitle}}</h4>
+ {{if $helpUrl}}
+ <a type="button" target="hubzilla-help" href="{{$helpUrl}}" class="contextual-help-tool" title="Help and documentation"><i class="fa fa-question"></i></a>
+ {{/if}}
+ <h4 class="modal-title"><i id="dialog-perms-icon" class="fa fa-fw"></i> {{$aclModalTitle}}</h4>
</div>
<div class="modal-body">
+ {{if $aclModalDesc}}
+ <div id="acl-dialog-description">{{$aclModalDesc}}</div>
+ {{/if}}
{{if $jotnets}}
<div class="jotnets-wrapper" role="tab" id="jotnets-wrapper">
<a data-toggle="collapse" class="btn btn-block btn-default" href="#jotnets-collapse" aria-expanded="false" aria-controls="jotnets-collapse">{{$jnetModalTitle}} <span class="caret"></span></a>
@@ -16,11 +22,24 @@
</div>
{{/if}}
<div id="acl-wrapper">
- <button id="acl-showall" class="btn btn-block btn-default"><i class="fa fa-globe"></i> {{$showall}}</button>
- <input type="text" id="acl-search" placeholder="&#xf002;">
- <div id="acl-list">
- <div id="acl-list-content"></div>
+ <div id="acl-radiowrapper-showall" class="radio">
+ <label>
+ <input id="acl-showall" type="radio" name="optionsRadios" value="option1" checked>
+ <i class="fa fa-globe"></i><span id=acl-showall-caption>{{$showall}}</span>
+ </label>
</div>
+ <div id="acl-radiowrapper-showlimited" class="radio">
+ <label>
+ <input id="acl-showlimited" type="radio" name="optionsRadios" style="readonly" value="option2">
+ <span id=acl-showlimited-caption>{{$showlimited}}</span>
+ </label>
+ <div id="acl-list">
+ <input type="text" id="acl-search" placeholder="&#xf002; {{$search}}">
+ <div id=acl-showlimited-description>{{$showlimitedDesc}}</div>
+ <div id="acl-list-content"></div>
+ </div>
+ </div>
+
<span id="acl-fields"></span>
</div>
diff --git a/view/tpl/app_create.tpl b/view/tpl/app_create.tpl
index ff28e0598..0590e7031 100644
--- a/view/tpl/app_create.tpl
+++ b/view/tpl/app_create.tpl
@@ -12,6 +12,10 @@
<input type="hidden" name="addr" value="{{$addr}}" />
{{/if}}
+<input type="hidden" name="requires" value="{{$requires}}" />
+<input type="hidden" name="system" value="{{$system}}" />
+
+
{{include file="field_input.tpl" field=$name}}
{{include file="field_input.tpl" field=$url}}
{{include file="field_textarea.tpl" field=$desc}}
diff --git a/view/tpl/app_select.tpl b/view/tpl/app_select.tpl
index 527d01eae..93049d522 100644
--- a/view/tpl/app_select.tpl
+++ b/view/tpl/app_select.tpl
@@ -2,8 +2,8 @@
<div class="widget">
<h3>{{$title}}</h3>
<ul class="nav nav-pills nav-stacked">
-<li><a href="appman">{{$new}}</a></li>
-<li><a href="apps/edit">{{$edit}}</a></li>
+<li><a href="appman"><i class="fa fa-plus"></i>&nbsp;&nbsp;{{$new}}</a></li>
+<li><a href="apps/edit"><i class="fa fa-pencil"></i>&nbsp;&nbsp;{{$edit}}</a></li>
</ul>
</div>
{{/if}}