Sfoglia il codice sorgente

Contacts: Update from main project.

Nate 5 anni fa
parent
commit
12fa754c2a

+ 99 - 0
contact_addresses_view.php

@@ -0,0 +1,99 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_address_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the address list
+	$sql = "select * from v_contact_addresses ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "and contact_uuid = :contact_uuid ";
+	$sql .= "order by address_primary desc, address_label asc ";
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_addresses = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_addresses) && @sizeof($contact_addresses) != 0) {
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px auto 30px;'>\n";
+			$x = 0;
+			foreach ($contact_addresses as $row) {
+				$map_query = $row['address_street']." ".$row['address_extended'].", ".$row['address_locality'].", ".$row['address_region'].", ".$row['address_region'].", ".$row['address_postal_code'];
+				echo "<div class='box contact-details-label'>".escape($row['address_label'])."</div>\n";
+// 				($row['address_primary'] ? "&nbsp;<i class='fas fa-star fa-xs' style='float: right; margin-top: 0.5em; margin-right: -0.5em;' title=\"".$text['label-primary']."\"></i>" : null)."</td>\n";
+				echo "<div class='box'>";
+				echo "<a href='http://maps.google.com/maps?q=".urlencode($map_query)."&hl=en' target='_blank' alt='".$text['label-google_map']."' title='".$text['label-google_map']."'>";
+				$previous_data = false;
+				if ($row['address_street']) {
+					echo escape($row['address_street']);
+					$previous_data = true;
+				}
+				if ($row['address_extended']) {
+					echo $previous_data ? ', ' : null;
+					echo escape($row['address_extended']);
+					$previous_data = true;
+				}
+				if ($row['address_locality']) {
+					echo $previous_data ? ', ' : null;
+					echo escape($row['address_locality']);
+					$previous_data = true;
+				}
+				if ($row['address_region']) {
+					echo $previous_data ? ', ' : null;
+					echo escape($row['address_region']);
+					$previous_data = true;
+				}
+				if ($row['address_country']) {
+					echo $previous_data ? ', ' : null;
+					echo escape($row['address_country']);
+					$previous_data = true;
+				}
+				echo "</a>";
+				echo "</div>\n";
+				echo "<div class='box' style='text-align: right;'><i class='fas fa-map-marked-alt fa-fw'></i></div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_addresses);
+
+	}
+
+?>

+ 103 - 0
contact_attachments_view.php

@@ -0,0 +1,103 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_attachment_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the contact attachment list
+	$sql = "select *, length(decode(attachment_content,'base64')) as attachment_size from v_contact_attachments ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "and contact_uuid = :contact_uuid ";
+	$sql .= "order by attachment_primary desc, attachment_filename asc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_attachments = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_attachments) && @sizeof($contact_attachments) != 0) {
+
+		//styles and attachment layer
+			echo "<style>\n";
+			echo "	#contact_attachment_layer {\n";
+			echo "		z-index: 999999;\n";
+			echo "		position: absolute;\n";
+			echo "		left: 0px;\n";
+			echo "		top: 0px;\n";
+			echo "		right: 0px;\n";
+			echo "		bottom: 0px;\n";
+			echo "		text-align: center;\n";
+			echo "		vertical-align: middle;\n";
+			echo "	}\n";
+			echo "</style>\n";
+			echo "<div id='contact_attachment_layer' style='display: none;'></div>\n";
+
+		//display script
+			echo "<script>\n";
+			echo "	function display_attachment(id) {\n";
+			echo "		$('#contact_attachment_layer').load('contact_attachment.php?id=' + id + '&action=display', function(){\n";
+			echo "			$('#contact_attachment_layer').fadeIn(200);\n";
+			echo "		});\n";
+			echo "	}\n";
+			echo "</script>\n";
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px auto 75px;'>\n";
+			$x = 0;
+			foreach ($contact_attachments as $row) {
+				$attachment_type = strtolower(pathinfo($row['attachment_filename'], PATHINFO_EXTENSION));
+				$attachment_type_label = $attachment_type == 'jpg' || $attachment_type == 'jpeg' || $attachment_type == 'gif' || $attachment_type == 'png' ? $text['label-image'] : $text['label-file'];
+				echo "<div class='box contact-details-label'>".$attachment_type_label."</div>\n";
+// 				($row['attachment_primary'] ? "&nbsp;<i class='fas fa-star fa-xs' style='float: right; margin-top: 0.5em; margin-right: -0.5em;' title=\"".$text['label-primary']."\"></i>" : null)."</td>\n";
+				echo "<div class='box'>";
+				if ($attachment_type == 'jpg' || $attachment_type == 'jpeg' || $attachment_type == 'gif' || $attachment_type == 'png') {
+					echo button::create(['type'=>'button','class'=>'link','label'=>escape($row['attachment_filename']),'onclick'=>"display_attachment('".escape($row['contact_attachment_uuid'])."');"]);
+				}
+				else {
+					echo button::create(['type'=>'button','class'=>'link','label'=>escape($row['attachment_filename']),'onclick'=>"window.location='contact_attachment.php?id=".urlencode($row['contact_attachment_uuid'])."&action=download';"]);
+				}
+				echo "</div>\n";
+				echo "<div class='box' style='text-align: right; font-size: 90%;'>".strtoupper(byte_convert($row['attachment_size']))."</div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_attachments);
+
+	}
+
+?>

+ 252 - 205
contact_edit.php

@@ -17,7 +17,7 @@
 
 	The Initial Developer of the Original Code is
 	Mark J Crane <[email protected]>
-	Portions created by the Initial Developer are Copyright (C) 2008-2019
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
 	the Initial Developer. All Rights Reserved.
 
 	Contributor(s):
@@ -30,7 +30,7 @@
 	require_once "resources/check_auth.php";
 
 //check permissions
-	if (permission_exists('contact_view')) {
+	if (permission_exists('contact_edit')) {
 		//access granted
 	}
 	else {
@@ -42,48 +42,6 @@
 	$language = new text;
 	$text = $language->get();
 
-
-//get the http post data from the contact property lists (numbers, addresses, etc) and process by action
-	if (is_array($_POST) && is_uuid($_POST['contact_uuid'])) {
-		$contact_uuid = $_POST['contact_uuid'];
-
-		switch ($_POST['action']) {
-			case 'delete_properties':
-				$array = array();
-				if (permission_exists('contact_phone_delete')) { $contact_properties['contact_phones'] = $_POST['contact_phones']; }
-				if (permission_exists('contact_address_delete')) { $contact_properties['contact_addresses'] = $_POST['contact_addresses']; }
-				if (permission_exists('contact_email_delete')) { $contact_properties['contact_emails'] = $_POST['contact_emails']; }
-				if (permission_exists('contact_url_delete')) { $contact_properties['contact_urls'] = $_POST['contact_urls']; }
-				//if (permission_exists('contact_extension_delete')) { $contact_properties['contact_extensions'] = $_POST['contact_extensions']; }
-				if (permission_exists('contact_relation_delete')) { $contact_properties['contact_relations'] = $_POST['contact_relations']; }
-				if (permission_exists('contact_note_delete')) { $contact_properties['contact_notes'] = $_POST['contact_notes']; }
-				if (permission_exists('contact_time_delete')) { $contact_properties['contact_times'] = $_POST['contact_times']; }
-				if (permission_exists('contact_setting_delete')) { $contact_properties['contact_settings'] = $_POST['contact_settings']; }
-				if (permission_exists('contact_attachment_delete')) { $contact_properties['contact_attachments'] = $_POST['contact_attachments']; }
-
-				if (@sizeof($contact_properties) != 0) {
-					$obj = new contacts;
-					$obj->contact_uuid = $contact_uuid;
-					$obj->delete_properties($contact_properties);
-				}
-
-				header('Location: contact_edit.php?id='.urlencode($contact_uuid));
-				exit;
-			case 'delete_contact':
-				if (permission_exists('contact_delete')) {
-					$array[0]['checked'] = 'true';
-					$array[0]['uuid'] = $contact_uuid;
-
-					$obj = new contacts;
-					$obj->delete($array);
-				}
-
-				header('Location: contacts.php');
-				exit;
-		}
-	}
-
-
 //action add or update
 	if (is_uuid($_REQUEST["id"])) {
 		$action = "update";
@@ -95,6 +53,24 @@
 
 //get http post variables and set them to php variables
 	if (count($_POST) > 0) {
+
+		//process the http post data by submitted action
+			if ($_POST['action'] != '' && is_uuid($_POST['contact_uuid'])) {
+				$array[0]['checked'] = 'true';
+				$array[0]['uuid'] = $_POST['contact_uuid'];
+
+				switch ($_POST['action']) {
+					case 'delete':
+						if (permission_exists('contact_delete')) {
+							$obj = new contacts;
+							$obj->delete($array);
+
+							header('Location: contacts.php');
+							exit;
+						}
+				}
+			}
+
 		$user_uuid = $_POST["user_uuid"];
 		$group_uuid = $_POST['group_uuid'];
 		$contact_type = $_POST["contact_type"];
@@ -110,6 +86,8 @@
 		$contact_role = $_POST["contact_role"];
 		$contact_time_zone = $_POST["contact_time_zone"];
 		$contact_note = $_POST["contact_note"];
+		$contact_users_delete = $_POST['contact_users_delete'];
+		$contact_groups_delete = $_POST['contact_groups_delete'];
 	}
 
 //process the form data
@@ -167,7 +145,7 @@
 					}
 
 				//update the contact
-					if ($action == "update" && permission_exists('contact_edit')) {
+					if ($action == "update") {
 						$array['contacts'][0]['contact_uuid'] = $contact_uuid;
 
 						message::add($text['message-update']);
@@ -234,6 +212,49 @@
 						$p->delete('contact_group_add', 'temp');
 					}
 
+				//delete checked contact properties
+					$array = array();
+					if (permission_exists('contact_phone_delete')) { $contact_properties['contact_phones'] = $_POST['contact_phones']; }
+					if (permission_exists('contact_address_delete')) { $contact_properties['contact_addresses'] = $_POST['contact_addresses']; }
+					if (permission_exists('contact_email_delete')) { $contact_properties['contact_emails'] = $_POST['contact_emails']; }
+					if (permission_exists('contact_url_delete')) { $contact_properties['contact_urls'] = $_POST['contact_urls']; }
+					//if (permission_exists('contact_extension_delete')) { $contact_properties['contact_extensions'] = $_POST['contact_extensions']; }
+					if (permission_exists('contact_relation_delete')) { $contact_properties['contact_relations'] = $_POST['contact_relations']; }
+					if (permission_exists('contact_note_delete')) { $contact_properties['contact_notes'] = $_POST['contact_notes']; }
+					if (permission_exists('contact_time_delete')) { $contact_properties['contact_times'] = $_POST['contact_times']; }
+					if (permission_exists('contact_setting_delete')) { $contact_properties['contact_settings'] = $_POST['contact_settings']; }
+					if (permission_exists('contact_attachment_delete')) { $contact_properties['contact_attachments'] = $_POST['contact_attachments']; }
+
+					if (@sizeof($contact_properties) != 0) {
+						$obj = new contacts;
+						$obj->contact_uuid = $contact_uuid;
+						$obj->delete_properties($contact_properties);
+					}
+
+				//remove checked users
+					if (
+						$action == 'update'
+						&& permission_exists('contact_user_delete')
+						&& is_array($contact_users_delete)
+						&& @sizeof($contact_users_delete) != 0
+						) {
+						$obj = new contacts;
+						$obj->contact_uuid = $contact_uuid;
+						$obj->delete_users($contact_users_delete);
+					}
+
+				//remove checked groups
+					if (
+						$action == 'update'
+						&& permission_exists('contact_group_delete')
+						&& is_array($contact_groups_delete)
+						&& @sizeof($contact_groups_delete) != 0
+						) {
+						$obj = new contacts;
+						$obj->contact_uuid = $contact_uuid;
+						$obj->delete_groups($contact_groups_delete);
+					}
+
 				//redirect the browser
 					header("Location: contact_edit.php?id=".urlencode($contact_uuid));
 					exit;
@@ -298,9 +319,41 @@
 	$parameters['contact_uuid'] = $contact_uuid;
 	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
 	$database = new database;
-	$contact_users = $database->select($sql, $parameters, 'all');
+	$contact_users_assigned = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//get the assigned groups of this contact
+	$sql = "select g.*, cg.contact_group_uuid ";
+	$sql .= "from v_groups as g, v_contact_groups as cg ";
+	$sql .= "where cg.group_uuid = g.group_uuid ";
+	$sql .= "and cg.domain_uuid = :domain_uuid ";
+	$sql .= "and cg.contact_uuid = :contact_uuid ";
+	$sql .= "and cg.group_uuid <> :group_uuid ";
+	$sql .= "order by g.group_name asc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$parameters['contact_uuid'] = $contact_uuid;
+	$parameters['group_uuid'] = $_SESSION["user_uuid"];
+	$database = new database;
+	$contact_groups_assigned = $database->select($sql, $parameters, 'all');
+	if (is_array($contact_groups_assigned) && @sizeof($contact_groups_assigned) != 0) {
+		foreach ($contact_groups_assigned as $field) {
+			$contact_groups[] = "'".$field['group_uuid']."'";
+		}
+	}
 	unset($sql, $parameters);
 
+//get the available groups to this contact
+	$sql = "select group_uuid, group_name from v_groups ";
+	$sql .= "where (domain_uuid = :domain_uuid or domain_uuid is null) ";
+	if (is_array($contact_groups) && @sizeof($contact_groups) != 0) {
+		$sql .= "and group_uuid not in (".implode(',', $contact_groups).") ";
+	}
+	$sql .= "order by group_name asc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$database = new database;
+	$contact_groups_available = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters, $contact_groups);
+
 //create token
 	$object = new token;
 	$token = $object->create($_SERVER['PHP_SELF']);
@@ -381,6 +434,8 @@
 	echo "</script>";
 
 //show the content
+	echo "<form name='frm' id='frm' method='post'>\n";
+
 	echo "<div class='action_bar' id='action_bar'>\n";
 	echo "	<div class='heading'>";
 	if ($action == "add") {
@@ -391,7 +446,7 @@
 	}
 	echo "	</div>\n";
 	echo "	<div class='actions'>\n";
-	echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'collapse'=>'hide-sm-dn','style'=>'margin-right: 15px;','link'=>'contacts.php']);
+	echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'id'=>'btn_back','collapse'=>'hide-sm-dn','style'=>'margin-right: 15px;','link'=>'contacts.php']);
 	if ($action == "update") {
 		if (permission_exists('contact_time_add')) {
 			//detect timer state (and start time)
@@ -436,8 +491,7 @@
 		permission_exists('contact_setting_add') ||
 		permission_exists('contact_attachment_add')
 		)) {
- 		echo button::create(['type'=>'button','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add'],'style'=>'margin-left: 15px;','collapse'=>'hide-sm-dn','onclick'=>"document.getElementById('select_add').style.display='inline'; this.style.display='none';"]);
-		echo 		"<select class='formfld' style='display: none; width: auto; margin-left: 15px;' id='select_add' onchange=\"document.location.href='contact_' + (this.options[this.selectedIndex].value) + '_edit.php?contact_uuid=".urlencode($contact_uuid)."';\">\n";
+		echo 		"<select class='formfld' style='width: auto; margin-left: 15px;' id='select_add' onchange=\"document.location.href='contact_' + (this.options[this.selectedIndex].value) + '_edit.php?contact_uuid=".urlencode($contact_uuid)."';\">\n";
 		echo "			<option value=''>".$text['button-add']."...</option>\n";
 		if (permission_exists('contact_phone_add')) { echo "<option value='phone'>".$text['label-phone_number']."</option>\n"; }
 		if (permission_exists('contact_address_add')) { echo "<option value='address'>".$text['label-address_address']."</option>\n"; }
@@ -450,56 +504,48 @@
 		if (permission_exists('contact_attachment_add')) { echo "<option value='attachment'>".$text['label-attachment']."</option>\n"; }
 		echo "		</select>";
 	}
-	if ($action == "update") {
-		if (
-			permission_exists('contact_delete') && (
-			permission_exists('contact_phone_delete') ||
-			permission_exists('contact_address_delete') ||
-			permission_exists('contact_email_delete') ||
-			permission_exists('contact_url_delete') ||
-			permission_exists('contact_relation_delete') ||
-			permission_exists('contact_note_delete') ||
-			permission_exists('contact_time_delete') ||
-			permission_exists('contact_setting_delete') ||
-			permission_exists('contact_attachment_delete')
-			)) {
-			echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'collapse'=>'hide-sm-dn','link'=>'#modal-delete']);
-			echo modal::create([
-				'id'=>'modal-delete',
-				'title'=>$text['modal_title-confirmation'],
-				'message'=>$text['message-delete_selection'],
-				'actions'=>
-					button::create(['type'=>'button','label'=>$text['button-cancel'],'icon'=>'times','collapse'=>'hide-xs','onclick'=>'modal_close();']).
-					button::create(['type'=>'button','label'=>$text['label-contact'],'icon'=>$_SESSION['theme']['button_icon_user'],'style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); if (confirm('".$text['confirm-delete']."')) { document.getElementById('contact_action').value='delete_contact'; document.getElementById('frm').submit(); } else { this.blur(); return false; }"]).
-					button::create(['type'=>'button','label'=>$text['label-properties'],'icon'=>'check-square','collapse'=>'never','style'=>'float: right;','onclick'=>"modal_close(); list_action_set('delete_properties'); list_form_submit('form_list');"])
-				]);
-		}
-		else {
-			if (permission_exists('contact_delete')) {
-				echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'collapse'=>'hide-sm-dn','link'=>'#modal-delete']);
-				echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); document.getElementById('contact_action').value='delete_contact'; document.getElementById('frm').submit();"])]);
-			}
-			else if (
-				permission_exists('contact_phone_delete') ||
-				permission_exists('contact_address_delete') ||
-				permission_exists('contact_email_delete') ||
-				permission_exists('contact_url_delete') ||
-				permission_exists('contact_relation_delete') ||
-				permission_exists('contact_note_delete') ||
-				permission_exists('contact_time_delete') ||
-				permission_exists('contact_setting_delete') ||
-				permission_exists('contact_attachment_delete')
-				) {
-				echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'collapse'=>'hide-sm-dn','link'=>'#modal-delete']);
-				echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('delete_properties'); list_form_submit('form_list');"])]);
-			}
-		}
+	if (
+		$action == "update" && (
+		permission_exists('contact_delete') ||
+		permission_exists('contact_user_delete') ||
+		permission_exists('contact_group_delete') ||
+		permission_exists('contact_phone_delete') ||
+		permission_exists('contact_address_delete') ||
+		permission_exists('contact_email_delete') ||
+		permission_exists('contact_url_delete') ||
+		permission_exists('contact_relation_delete') ||
+		permission_exists('contact_note_delete') ||
+		permission_exists('contact_time_delete') ||
+		permission_exists('contact_setting_delete') ||
+		permission_exists('contact_attachment_delete')
+		)) {
+		echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'name'=>'btn_delete','collapse'=>'hide-sm-dn','onclick'=>"modal_open('modal-delete','btn_delete');"]);
+	}
+	if (permission_exists('contact_add')) {
+		echo button::create(['type'=>'button','label'=>$text['button-save'],'icon'=>$_SESSION['theme']['button_icon_save'],'id'=>'btn_save','style'=>($action != 'update' ?: 'margin-left: 15px;'),'collapse'=>'hide-sm-dn','onclick'=>"document.getElementById('frm').submit();"]);
 	}
-	echo button::create(['type'=>'button','label'=>$text['button-save'],'icon'=>$_SESSION['theme']['button_icon_save'],'style'=>($action != 'update' ?: 'margin-left: 15px;'),'collapse'=>'hide-sm-dn','onclick'=>"document.getElementById('frm').submit();"]);
 	echo "	</div>\n";
 	echo "	<div style='clear: both;'></div>\n";
 	echo "</div>\n";
 
+	if (
+		$action == "update" && (
+		permission_exists('contact_delete') ||
+		permission_exists('contact_user_delete') ||
+		permission_exists('contact_group_delete') ||
+		permission_exists('contact_phone_delete') ||
+		permission_exists('contact_address_delete') ||
+		permission_exists('contact_email_delete') ||
+		permission_exists('contact_url_delete') ||
+		permission_exists('contact_relation_delete') ||
+		permission_exists('contact_note_delete') ||
+		permission_exists('contact_time_delete') ||
+		permission_exists('contact_setting_delete') ||
+		permission_exists('contact_attachment_delete')
+		)) {
+		echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'submit','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_delete','style'=>'float: right; margin-left: 15px;','collapse'=>'never','name'=>'action','value'=>'delete','onclick'=>"modal_close();"])]);
+	}
+
 	if ($action == "add") {
 		echo $text['description-contact-add']."\n";
 	}
@@ -512,8 +558,6 @@
 	echo "<tr>\n";
 	echo "<td valign='top' align='left' nowrap='nowrap'>\n";
 
-		echo "<form id='frm' method='post'>\n";
-
 		echo "<table border='0' cellpadding='0' cellspacing='0' width='100%'>\n";
 		echo "<tr>\n";
 		echo "<td width='30%' class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
@@ -684,118 +728,113 @@
 			echo "	<tr>";
 			echo "		<td class='vncell' valign='top'>".$text['label-users']."</td>";
 			echo "		<td class='vtable' align='left'>";
-			if ($action == "update" && is_array($contact_users) && @sizeof($contact_users) != 0) {
-				echo "			<table border='0' style='width: 100%;'>\n";
-				foreach ($contact_users as $field) {
+			echo "			<table border='0' cellpadding='0' cellspacing='0' style='width: 100%;'>\n";
+			if ($action == "update" && is_array($contact_users_assigned) && @sizeof($contact_users_assigned) != 0) {
+				echo "				<tr>\n";
+				echo "					<td class='vtable'>".$text['label-username']."</td>\n";
+				if ($contact_users_assigned && permission_exists('contact_user_delete')) {
+					echo "					<td class='vtable edit_delete_checkbox_all' onmouseover=\"swap_display('delete_label_users', 'delete_toggle_users');\" onmouseout=\"swap_display('delete_label_users', 'delete_toggle_users');\">\n";
+					echo "						<span id='delete_label_users'>".$text['label-delete']."</span>\n";
+					echo "						<span id='delete_toggle_users'><input type='checkbox' id='checkbox_all_users' name='checkbox_all' onclick=\"edit_all_toggle('users');\"></span>\n";
+					echo "					</td>\n";
+				}
+				echo "				</tr>\n";
+				foreach ($contact_users_assigned as $x => $field) {
 					echo "			<tr>\n";
-					echo "				<td class='vtable' style='width: 100%;'>".escape($field['username'])."</td>\n";
-					echo "				<td>\n";
-					if (permission_exists('contact_user_delete')) {
-						echo "					<a href='contact_user_delete.php?id=".urlencode($field['contact_user_uuid'])."&contact_uuid=".urlencode($contact_uuid)."' alt='delete' onclick=\"return confirm('".$text['confirm-delete']."');\">$v_link_label_delete</a>\n";
+					echo "				<td class='vtable'>".escape($field['username'])."</td>\n";
+					if ($contact_users_assigned && permission_exists('contact_user_delete')) {
+						if (is_uuid($field['contact_user_uuid'])) {
+							echo "			<td class='vtable' style='text-align: center; padding-bottom: 3px;'>";
+							echo "				<input type='checkbox' name='contact_users_delete[".$x."][checked]' value='true' class='chk_delete checkbox_users' onclick=\"edit_delete_action('users');\">\n";
+							echo "				<input type='hidden' name='contact_users_delete[".$x."][uuid]' value='".escape($field['contact_user_uuid'])."' />\n";
+						}
+						else {
+							echo "			<td>";
+						}
+						echo "			</td>\n";
 					}
-					echo "				</td>\n";
 					echo "			</tr>\n";
 				}
-				echo "			</table>\n";
-				echo "			<br />\n";
 			}
 			if (permission_exists('contact_user_add')) {
-				echo "			<select name=\"user_uuid\" class='formfld' style='width: auto;'>\n";
-				echo "			<option value=\"\"></option>\n";
+				echo "			<tr>\n";
+				echo "				<td class='vtable' style='border-bottom: none;' colspan='2'>\n";
+				echo "					<select name='user_uuid' class='formfld' style='width: auto;'>\n";
+				echo "						<option value=''></option>\n";
 				foreach ($users as $field) {
-					if (in_array($field['user_uuid'], array_column($contact_users, 'user_uuid'))) { continue; } //skip users already assigned
-					echo "			<option value='".escape($field['user_uuid'])."'>".escape($field['username'])."</option>\n";
+					if (in_array($field['user_uuid'], array_column($contact_users_assigned, 'user_uuid'))) { continue; } //skip users already assigned
+					echo "						<option value='".escape($field['user_uuid'])."'>".escape($field['username'])."</option>\n";
 				}
-				echo "			</select>";
+				echo "					</select>";
 				if ($action == "update") {
 					echo button::create(['type'=>'submit','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add']]);
 				}
 				unset($users);
-				echo "			<br>\n";
-				echo "			".$text['description-users']."\n";
+				echo "				</td>\n";
+				echo "			<tr>\n";
 			}
+			echo "			</table>\n";
+			echo "			".$text['description-users']."\n";
 			echo "		</td>";
 			echo "	</tr>";
 		}
 
 		if (permission_exists('contact_group_view')) {
 			echo "<tr>";
-			echo "	<td width='30%' class='vncell' valign='top'>".$text['label-groups']."</td>";
-			echo "	<td width='70%' class='vtable'>";
-			$sql = "select ";
-			$sql .= "g.*, ";
-			$sql .= "cg.contact_group_uuid ";
-			$sql .= "from ";
-			$sql .= "v_groups as g, ";
-			$sql .= "v_contact_groups as cg ";
-			$sql .= "where ";
-			$sql .= "cg.group_uuid = g.group_uuid ";
-			$sql .= "and cg.domain_uuid = :domain_uuid ";
-			$sql .= "and cg.contact_uuid = :contact_uuid ";
-			$sql .= "and cg.group_uuid <> :group_uuid ";
-			$sql .= "order by g.group_name asc ";
-			$parameters['domain_uuid'] = $domain_uuid;
-			$parameters['contact_uuid'] = $contact_uuid;
-			$parameters['group_uuid'] = $_SESSION["user_uuid"];
-			$database = new database;
-			$result = $database->select($sql, $parameters, 'all');
-			if (is_array($result) && @sizeof($result) != 0) {
-				echo "	<table style='width: 100%;'>\n";
-				foreach ($result as $field) {
+			echo "	<td class='vncell' valign='top'>".$text['label-groups']."</td>";
+			echo "	<td class='vtable'>";
+			echo "		<table border='0' cellpadding='0' cellspacing='0' style='width: 100%;'>\n";
+			if (is_array($contact_groups_assigned) && @sizeof($contact_groups_assigned) != 0) {
+				echo "			<tr>\n";
+				echo "				<td class='vtable'>".$text['label-group']."</td>\n";
+				if ($contact_groups_assigned && permission_exists('contact_group_delete')) {
+					echo "				<td class='vtable edit_delete_checkbox_all' onmouseover=\"swap_display('delete_label_groups', 'delete_toggle_groups');\" onmouseout=\"swap_display('delete_label_groups', 'delete_toggle_groups');\">\n";
+					echo "					<span id='delete_label_groups'>".$text['label-delete']."</span>\n";
+					echo "					<span id='delete_toggle_groups'><input type='checkbox' id='checkbox_all_groups' name='checkbox_all' onclick=\"edit_all_toggle('groups');\"></span>\n";
+					echo "				</td>\n";
+				}
+				echo "			</tr>\n";
+				foreach ($contact_groups_assigned as $x => $field) {
 					if (strlen($field['group_name']) > 0) {
-						echo "<tr>\n";
-						echo "	<td class='vtable' style='width: 100%;'>".escape($field['group_name'])."</td>\n";
-						echo "	<td>\n";
-						if (permission_exists('contact_group_delete') || if_group("superadmin")) {
-							echo "	<a href='contact_group_delete.php?id=".urlencode($field['contact_group_uuid'])."&contact_uuid=".urlencode($contact_uuid)."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."');\">$v_link_label_delete</a>\n";
+						echo "			<tr>\n";
+						echo "				<td class='vtable'>".escape($field['group_name'])."</td>\n";
+						if (permission_exists('contact_group_delete')) {
+							if (is_uuid($field['contact_group_uuid'])) {
+								echo "				<td class='vtable' style='text-align: center; padding-bottom: 3px;'>";
+								echo "					<input type='checkbox' name='contact_groups_delete[".$x."][checked]' value='true' class='chk_delete checkbox_groups' onclick=\"edit_delete_action('groups');\">\n";
+								echo "					<input type='hidden' name='contact_groups_delete[".$x."][uuid]' value='".escape($field['contact_group_uuid'])."' />\n";
+							}
+							else {
+								echo "				<td>";
+							}
+							echo "				</td>\n";
 						}
-						echo "	</td>\n";
-						echo "</tr>\n";
-						$assigned_groups[] = $field['group_uuid'];
+						echo "			</tr>\n";
 					}
 				}
-				echo "	</table>\n";
-				echo "	<br />\n";
 			}
-			unset($sql, $parameters, $result, $field);
-
-			if (permission_exists('contact_group_add') || if_group("superadmin")) {
-				$sql = "select * from v_groups ";
-				$sql .= "where domain_uuid = :domain_uuid ";
-				$sql .= "or domain_uuid is null ";
-				if (is_array($assigned_groups) && @sizeof($assigned_groups) != 0) {
-					foreach ($assigned_groups as $index => $assigned_group) {
-						$sql_where_and[] = "group_uuid <> :group_uuid_".$index." ";
-						$parameters['group_uuid_'.$index] = $assigned_group;
-					}
-					if (is_array($sql_where_and) && @sizeof($sql_where_and) != 0) {
-						$sql .= "and ".implode(' and ', $sql_where_and)." ";
-					}
-				}
-				$sql .= "order by group_name asc ";
-				$parameters['domain_uuid'] = $domain_uuid;
-				$database = new database;
-				$result = $database->select($sql, $parameters, 'all');
-				unset($sql, $sql_where_and, $index, $parameters, $assigned_groups, $assigned_group);
-
-				if (is_array($result) && @sizeof($result) != 0) {
-					echo "	<select name='group_uuid' class='formfld' style='width: auto; margin-right: 3px;'>\n";
-					echo "		<option value=''></option>\n";
-					foreach ($result as $field) {
+
+			if (permission_exists('contact_group_add')) {
+				if (is_array($contact_groups_available) && @sizeof($contact_groups_available) != 0) {
+					echo "			<tr>\n";
+					echo "				<td class='vtable' style='border-bottom: none;' colspan='2'>\n";
+					echo "					<select name='group_uuid' class='formfld' style='width: auto; margin-right: 3px;'>\n";
+					echo "						<option value=''></option>\n";
+					foreach ($contact_groups_available as $field) {
 						if ($field['group_name'] == "superadmin" && !if_group("superadmin")) { continue; }	//only show superadmin group to superadmins
 						if ($field['group_name'] == "admin" && (!if_group("superadmin") && !if_group("admin"))) { continue; }	//only show admin group to admins
-						echo "<option value='".escape($field['group_uuid'])."'>".escape($field['group_name'])."</option>\n";
+						echo "						<option value='".escape($field['group_uuid'])."'>".escape($field['group_name'])."</option>\n";
 					}
-					echo "	</select>";
-
+					echo "					</select>";
 					if ($action == "update") {
 						echo button::create(['type'=>'submit','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add']]);
 					}
-					echo "<br>";
+					echo "				</td>\n";
+					echo "			</tr>\n";
 				}
-				unset($result, $field);
 			}
 
+			echo "		</table>\n";
 			echo "		".$text['description-groups']."\n";
 
 			echo "	</td>";
@@ -803,50 +842,32 @@
 		}
 
 		echo "<tr>\n";
-		echo "	<td width='30%' class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+		echo "	<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
 		echo "		".$text['label-contact_note']."\n";
 		echo "	</td>\n";
-		echo "	<td width='70%' class='vtable' align='left'>\n";
+		echo "	<td class='vtable' align='left'>\n";
 		echo "		<textarea class='formfld' style='width: 100%; height: 160px;' name='contact_note'>".$contact_note."</textarea>\n";
 		echo "	</td>\n";
 		echo "</tr>\n";
 
 		echo "</table>";
 
-		if ($action == "update") {
-			echo "<input type='hidden' id='contact_action' name='action' value=''>\n";
-			echo "<input type='hidden' name='contact_uuid' value='".escape($contact_uuid)."'>\n";
-		}
-		echo "<input type='hidden' name='".$token['name']."' value='".$token['hash']."'>\n";
-
-		echo "</form>";
-
 	echo "</td>\n";
 
 	if ($action == "update") {
 		echo "<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>";
 		echo "<td width='100%' valign='top'>\n";
 
-			echo "<form id='form_list' method='post'>\n";
-			echo "<input type='hidden' id='action' name='action' value=''>\n";
-
-			if (permission_exists('contact_phone_view')) { require "contact_phones.php"; }
-			if (permission_exists('contact_address_view')) { require "contact_addresses.php"; }
-			if (permission_exists('contact_email_view')) { require "contact_emails.php"; }
-			if (permission_exists('contact_url_view')) { require "contact_urls.php"; }
-			if (permission_exists('contact_extension_view')) { require "contact_extensions.php"; }
-			if (permission_exists('contact_relation_view')) { require "contact_relations.php"; }
-			if (permission_exists('contact_note_view')) { require "contact_notes.php"; }
-			if (permission_exists('contact_time_view')) { require "contact_times.php"; }
-			if (permission_exists('contact_setting_view')) { require "contact_settings.php"; }
-			if (permission_exists('contact_attachment_view')) { require "contact_attachments.php"; }
-
-			if ($action == "update") {
-				echo "<input type='hidden' name='contact_uuid' value='".escape($contact_uuid)."'>\n";
-			}
-			echo "<input type='hidden' name='".$token['name']."' value='".$token['hash']."'>\n";
-
-			echo "</form>";
+		if (permission_exists('contact_phone_view')) { require "contact_phones.php"; }
+		if (permission_exists('contact_address_view')) { require "contact_addresses.php"; }
+		if (permission_exists('contact_email_view')) { require "contact_emails.php"; }
+		if (permission_exists('contact_url_view')) { require "contact_urls.php"; }
+		if (permission_exists('contact_extension_view')) { require "contact_extensions.php"; }
+		if (permission_exists('contact_relation_view')) { require "contact_relations.php"; }
+		if (permission_exists('contact_note_view')) { require "contact_notes.php"; }
+		if (permission_exists('contact_time_view')) { require "contact_times.php"; }
+		if (permission_exists('contact_setting_view')) { require "contact_settings.php"; }
+		if (permission_exists('contact_attachment_view')) { require "contact_attachments.php"; }
 
 		echo "</td>\n";
 	}
@@ -855,6 +876,32 @@
 	echo "</table>\n";
 	echo "<br><br>";
 
+	if ($action == "update") {
+		echo "<input type='hidden' name='contact_uuid' value='".escape($contact_uuid)."'>\n";
+	}
+	echo "<input type='hidden' name='".$token['name']."' value='".$token['hash']."'>\n";
+	echo "</form>";
+
+//hide the delete button when nothing to delete
+	if (
+		$action == 'update' &&
+		!permission_exists('contact_delete') && (
+		(!is_array($contact_users_assigned) || @sizeof($contact_users_assigned) == 0) &&
+		(!is_array($contact_groups_assigned) || @sizeof($contact_groups_assigned) == 0) &&
+		(!is_array($contact_phones) || @sizeof($contact_phones) == 0) &&
+		(!is_array($contact_addresses) || @sizeof($contact_addresses) == 0) &&
+		(!is_array($contact_emails) || @sizeof($contact_emails) == 0) &&
+		(!is_array($contact_urls) || @sizeof($contact_urls) == 0) &&
+		(!is_array($contact_extensions) || @sizeof($contact_extensions) == 0) &&
+		(!is_array($contact_relations) || @sizeof($contact_relations) == 0) &&
+		(!is_array($contact_notes) || @sizeof($contact_notes) == 0) &&
+		(!is_array($contact_times) || @sizeof($contact_times) == 0) &&
+		(!is_array($contact_settings) || @sizeof($contact_settings) == 0) &&
+		(!is_array($contact_attachments) || @sizeof($contact_attachments) == 0)
+		)) {
+		echo "<script>document.getElementsByName('btn_delete')[0].style.display='none';</script>\n";
+	}
+
 //include the footer
 	require_once "resources/footer.php";
 

+ 69 - 0
contact_emails_view.php

@@ -0,0 +1,69 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_email_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the contact list
+	$sql = "select * from v_contact_emails ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "and contact_uuid = :contact_uuid ";
+	$sql .= "order by email_primary desc, email_label asc ";
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_emails = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_emails) && @sizeof($contact_emails) != 0) {
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px auto;'>\n";
+			$x = 0;
+			foreach ($contact_emails as $row) {
+				echo "<div class='box contact-details-label'>".($row['email_label'] == strtolower($row['email_label']) ? ucwords($row['email_label']) : $row['email_label'])."</div>\n";
+// 				($row['email_primary'] ? "&nbsp;<i class='fas fa-star fa-xs' style='float: right; margin-top: 0.5em; margin-right: -0.5em;' title=\"".$text['label-primary']."\"></i>" : null)."</td>\n";
+				echo "<div class='box'><a href='mailto:".escape($row['email_address'])."'>".escape($row['email_address'])."</a></div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_emails);
+
+	}
+
+?>

+ 91 - 0
contact_extensions_view.php

@@ -0,0 +1,91 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_extension_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the extension list
+	$sql = "select e.extension_uuid, e.extension, e.enabled, e.description ";
+	$sql .= "from v_extensions e, v_extension_users eu, v_users u ";
+	$sql .= "where e.extension_uuid = eu.extension_uuid ";
+	$sql .= "and u.user_uuid = eu.user_uuid ";
+	$sql .= "and e.domain_uuid = :domain_uuid ";
+	$sql .= "and u.contact_uuid = :contact_uuid ";
+	$sql .= "order by e.extension asc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_extensions = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_extensions) && @sizeof($contact_extensions) != 0) {
+
+		//javascript function: send_cmd
+			echo "<script type='text/javascript'>\n";
+			echo "function send_cmd(url) {\n";
+			echo "	if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari\n";
+			echo "		xmlhttp=new XMLHttpRequest();\n";
+			echo "	}\n";
+			echo "	else {// code for IE6, IE5\n";
+			echo "		xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');\n";
+			echo "	}\n";
+			echo "	xmlhttp.open('GET',url,true);\n";
+			echo "	xmlhttp.send(null);\n";
+			echo "	document.getElementById('cmd_reponse').innerHTML=xmlhttp.responseText;\n";
+			echo "}\n";
+			echo "</script>\n";
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px 100px auto;'>\n";
+			$x = 0;
+			foreach ($contact_extensions as $row) {
+				if ($row['enabled'] != 'true') { continue; } //skip disabled extensions
+				echo "<div class='box contact-details-label'>".$text['label-extension']."</div>\n";
+// 				($row['url_primary'] ? "style='font-weight: bold;'" : null).">\n";
+				echo "<div class='box'>";
+				echo button::create(['type'=>'button','class'=>'link','label'=>escape($row['extension']),'title'=>$text['label-click_to_call'],'onclick'=>"send_cmd('".PROJECT_PATH."/app/click_to_call/click_to_call.php?src_cid_name=".urlencode($row['extension'])."&src_cid_number=".urlencode($row['extension'])."&dest_cid_name=".urlencode($_SESSION['user']['extension'][0]['outbound_caller_id_name'])."&dest_cid_number=".urlencode($_SESSION['user']['extension'][0]['outbound_caller_id_number'])."&src=".urlencode($_SESSION['user']['extension'][0]['user'])."&dest=".urlencode($row['extension'])."&rec=false&ringback=us-ring&auto_answer=true');"]);
+				echo "</div>\n";
+				echo "<div class='box'>".$row['description']."</div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_extensions);
+
+	}
+
+?>

+ 69 - 0
contact_notes_view.php

@@ -0,0 +1,69 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_note_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the contact list
+	$sql = "select * from v_contact_notes ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "and contact_uuid = :contact_uuid ";
+	$sql .= "order by last_mod_date desc ";
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_notes = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_notes) && @sizeof($contact_notes) != 0) {
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: auto 190px;'>\n";
+			$x = 0;
+			foreach ($contact_notes as $row) {
+				$contact_note = str_replace("\n","<br />",escape($row['contact_note']));
+				echo "<div class='box' style='padding-bottom: 15px;'>".$contact_note."</div>\n";
+				echo "<div class='box contact-details-label' style='padding-bottom: 15px; text-align: right;'><strong>".escape($row['last_mod_user'])."</strong>: ".date("j M Y @ H:i:s", strtotime($row['last_mod_date']))."</div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_notes);
+
+	}
+
+?>

+ 96 - 0
contact_phones_view.php

@@ -0,0 +1,96 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_phone_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the contact list
+	$sql = "select * from v_contact_phones ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "and contact_uuid = :contact_uuid ";
+	$sql .= "order by phone_primary desc, phone_label asc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_phones = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_phones) && @sizeof($contact_phones) != 0) {
+
+		//javascript function: send_cmd
+			echo "<script type='text/javascript'>\n";
+			echo "function send_cmd(url) {\n";
+			echo "	if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari\n";
+			echo "		xmlhttp=new XMLHttpRequest();\n";
+			echo "	}\n";
+			echo "	else {// code for IE6, IE5\n";
+			echo "		xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');\n";
+			echo "	}\n";
+			echo "	xmlhttp.open('GET',url,true);\n";
+			echo "	xmlhttp.send(null);\n";
+			echo "	document.getElementById('cmd_reponse').innerHTML=xmlhttp.responseText;\n";
+			echo "}\n";
+			echo "</script>\n";
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px 120px auto;'>\n";
+			$x = 0;
+			foreach ($contact_phones as $row) {
+				echo "<div class='box contact-details-label'>".($row['phone_label'] == strtolower($row['phone_label']) ? ucwords($row['phone_label']) : $row['phone_label'])."</div>\n";
+// 				($row['phone_primary'] ? "&nbsp;<i class='fas fa-star fa-xs' style='float: right; margin-top: 0.5em; margin-right: -0.5em;' title=\"".$text['label-primary']."\"></i>" : null)."</td>\n";
+				echo "<div class='box'>";
+				echo button::create(['type'=>'button','class'=>'link','label'=>escape(format_phone($row['phone_number'])),'title'=>$text['label-click_to_call'],'onclick'=>"send_cmd('".PROJECT_PATH."/app/click_to_call/click_to_call.php?src_cid_name=".urlencode($row['phone_number'])."&src_cid_number=".urlencode($row['phone_number'])."&dest_cid_name=".urlencode($_SESSION['user']['extension'][0]['outbound_caller_id_name'])."&dest_cid_number=".urlencode($_SESSION['user']['extension'][0]['outbound_caller_id_number'])."&src=".urlencode($_SESSION['user']['extension'][0]['user'])."&dest=".urlencode($row['phone_number'])."&rec=false&ringback=us-ring&auto_answer=true');"]);
+				echo "</div>\n";
+				echo "<div class='box no-wrap'>";
+				if ($row['phone_type_voice']) { $phone_types[] = "<i class='fas fa-phone fa-fw' style='margin-right: 3px;' title=\"".$text['label-voice']."\"></i>"; }
+				if ($row['phone_type_fax']) { $phone_types[] = "<i class='fas fa-fax fa-fw' style='margin-right: 3px;' title=\"".$text['label-fax']."\"></i>"; }
+				if ($row['phone_type_video']) { $phone_types[] = "<i class='fas fa-video fa-fw' style='margin-right: 3px;' title=\"".$text['label-video']."\"></i>"; }
+				if ($row['phone_type_text']) { $phone_types[] = "<i class='fas fa-sms fa-fw' style='margin-right: 3px;' title=\"".$text['label-text']."\"></i>"; }
+				if (is_array($phone_types)) {
+					echo "	".implode(" ", $phone_types)."\n";
+				}
+				unset($phone_types);
+				echo "</div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_phones);
+
+	}
+
+?>

+ 83 - 0
contact_relations_view.php

@@ -0,0 +1,83 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_relation_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the related contacts
+	$sql = "select ";
+	$sql .= "cr.contact_relation_uuid, ";
+	$sql .= "cr.relation_label, ";
+	$sql .= "c.contact_uuid, ";
+	$sql .= "c.contact_organization, ";
+	$sql .= "c.contact_name_given, ";
+	$sql .= "c.contact_name_family ";
+	$sql .= "from ";
+	$sql .= "v_contact_relations as cr, ";
+	$sql .= "v_contacts as c ";
+	$sql .= "where ";
+	$sql .= "cr.relation_contact_uuid = c.contact_uuid ";
+	$sql .= "and cr.domain_uuid = :domain_uuid ";
+	$sql .= "and cr.contact_uuid = :contact_uuid ";
+	$sql .= "order by ";
+	$sql .= "c.contact_organization desc, ";
+	$sql .= "c.contact_name_given asc, ";
+	$sql .= "c.contact_name_family asc ";
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_relations = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_relations) && @sizeof($contact_relations) != 0) {
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px auto auto;'>\n";
+			$x = 0;
+			foreach ($contact_relations as $row) {
+				echo "<div class='box contact-details-label'>".escape($row['relation_label'])."</div>\n";
+				echo "<div class='box'><a href='contact_view.php?id=".urlencode($row['contact_uuid'])."'>".escape($row['contact_organization'])."</a></div>\n";
+				echo "<div class='box'><a href='contact_view.php?id=".urlencode($row['contact_uuid'])."'>".escape($row['contact_name_given']).(($row['contact_name_given'] && $row['contact_name_family']) ? ' ' : null).escape($row['contact_name_family'])."</a></div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_relations);
+
+	}
+
+?>

+ 81 - 0
contact_times_view.php

@@ -0,0 +1,81 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_time_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the contact list
+	$sql = "select ct.*, u.username, u.domain_uuid as user_domain_uuid ";
+	$sql .= "from v_contact_times as ct, v_users as u ";
+	$sql .= "where ct.user_uuid = u.user_uuid ";
+	$sql .= "and ct.domain_uuid = :domain_uuid ";
+	$sql .= "and ct.contact_uuid = :contact_uuid ";
+	$sql .= "order by ct.time_start desc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_times = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_times) && @sizeof($contact_times) != 0) {
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px auto auto;'>\n";
+			$x = 0;
+			foreach ($contact_times as $row) {
+				if ($row["time_start"] != '' && $row['time_stop'] != '') {
+					$time_start = strtotime($row["time_start"]);
+					$time_stop = strtotime($row['time_stop']);
+					$time = gmdate("H:i:s", ($time_stop - $time_start));
+				}
+				else {
+					unset($time);
+				}
+				$tmp = explode(' ', $row['time_start']);
+				$time_start = $tmp[0];
+				echo "<div class='box contact-details-label'><span ".($row['user_domain_uuid'] != $domain_uuid ? "title='".$_SESSION['domains'][escape($row['user_domain_uuid'])]['domain_name']."' style='cursor: help;'" : null).">".escape($row["username"])."</span></div>\n";
+				echo "<div class='box'>".$time_start."</div>\n";
+				echo "<div class='box'>".$time."</div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_times);
+
+	}
+
+?>

+ 69 - 0
contact_urls_view.php

@@ -0,0 +1,69 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_url_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//get the contact list
+	$sql = "select * from v_contact_urls ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "and contact_uuid = :contact_uuid ";
+	$sql .= "order by url_primary desc, url_label asc ";
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$contact_urls = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//show if exists
+	if (is_array($contact_urls) && @sizeof($contact_urls) != 0) {
+
+		//show the content
+			echo "<div class='grid' style='grid-template-columns: 70px auto;'>\n";
+			$x = 0;
+			foreach ($contact_urls as $row) {
+				echo "<div class='box contact-details-label'>".escape($row['url_label'])."</div>\n";
+// 				($row['url_primary'] ? "&nbsp;<i class='fas fa-star fa-xs' style='float: right; margin-top: 0.5em; margin-right: -0.5em;' title=\"".$text['label-primary']."\"></i>" : null)."</td>\n";
+				echo "<div class='box'><a href='".escape($row['url_address'])."' target='_blank'>".escape(str_replace(['http://','https://'], '', $row['url_address']))."</a></div>\n";
+				$x++;
+			}
+			echo "</div>\n";
+			unset($contact_urls);
+
+	}
+
+?>

+ 533 - 0
contact_view.php

@@ -0,0 +1,533 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2020
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	require_once "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('contact_view')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//add multi-lingual support
+	$language = new text;
+	$text = $language->get();
+
+
+//action add or update
+	if (is_uuid($_REQUEST["id"])) {
+		$contact_uuid = $_REQUEST["id"];
+	}
+	else {
+		header("Location: contacts.php");
+	}
+
+//main contact details
+	$sql = "select * from v_contacts ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "and contact_uuid = :contact_uuid ";
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$parameters['contact_uuid'] = $contact_uuid;
+	$database = new database;
+	$row = $database->select($sql, $parameters, 'row');
+	if (is_array($row) && @sizeof($row) != 0) {
+		$contact_type = $row["contact_type"];
+		$contact_organization = $row["contact_organization"];
+		$contact_name_prefix = $row["contact_name_prefix"];
+		$contact_name_given = $row["contact_name_given"];
+		$contact_name_middle = $row["contact_name_middle"];
+		$contact_name_family = $row["contact_name_family"];
+		$contact_name_suffix = $row["contact_name_suffix"];
+		$contact_nickname = $row["contact_nickname"];
+		$contact_title = $row["contact_title"];
+		$contact_category = $row["contact_category"];
+		$contact_role = $row["contact_role"];
+		$contact_time_zone = $row["contact_time_zone"];
+		$contact_note = $row["contact_note"];
+	}
+	unset($sql, $parameters, $row);
+
+//get the available users for this contact
+	$sql = "select * from v_users ";
+	$sql .= "where domain_uuid = :domain_uuid ";
+	$sql .= "order by username asc ";
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$database = new database;
+	$users = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//determine if contact assigned to a user
+	if (is_array($users) && sizeof($users) != 0) {
+		foreach ($users as $user) {
+			if ($user['contact_uuid'] == $contact_uuid) {
+				$contact_user_uuid = $user['user_uuid'];
+				break;
+			}
+		}
+	}
+
+//get the assigned users that can view this contact
+	$sql = "select u.username, u.user_uuid, a.contact_user_uuid from v_contacts as c, v_users as u, v_contact_users as a ";
+	$sql .= "where c.contact_uuid = :contact_uuid ";
+	$sql .= "and c.domain_uuid = :domain_uuid ";
+	$sql .= "and u.user_uuid = a.user_uuid ";
+	$sql .= "and c.contact_uuid = a.contact_uuid ";
+	$sql .= "order by u.username asc ";
+	$parameters['contact_uuid'] = $contact_uuid;
+	$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+	$database = new database;
+	$contact_users_assigned = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters);
+
+//get the assigned groups that can view this contact
+	$sql = "select g.*, cg.contact_group_uuid ";
+	$sql .= "from v_groups as g, v_contact_groups as cg ";
+	$sql .= "where cg.group_uuid = g.group_uuid ";
+	$sql .= "and cg.domain_uuid = :domain_uuid ";
+	$sql .= "and cg.contact_uuid = :contact_uuid ";
+	$sql .= "and cg.group_uuid <> :group_uuid ";
+	$sql .= "order by g.group_name asc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$parameters['contact_uuid'] = $contact_uuid;
+	$parameters['group_uuid'] = $_SESSION["user_uuid"];
+	$database = new database;
+	$contact_groups_assigned = $database->select($sql, $parameters, 'all');
+	if (is_array($contact_groups_assigned) && @sizeof($contact_groups_assigned) != 0) {
+		foreach ($contact_groups_assigned as $field) {
+			$contact_groups[] = "'".$field['group_uuid']."'";
+		}
+	}
+	unset($sql, $parameters);
+
+//get the available groups for this contact
+	$sql = "select group_uuid, group_name from v_groups ";
+	$sql .= "where (domain_uuid = :domain_uuid or domain_uuid is null) ";
+	if (is_array($contact_groups) && @sizeof($contact_groups) != 0) {
+		$sql .= "and group_uuid not in (".implode(',', $contact_groups).") ";
+	}
+	$sql .= "order by group_name asc ";
+	$parameters['domain_uuid'] = $domain_uuid;
+	$database = new database;
+	$contact_groups_available = $database->select($sql, $parameters, 'all');
+	unset($sql, $parameters, $contact_groups);
+
+//determine title name
+	if ($contact_name_given || $contact_name_family) {
+		$contact_name = $contact_name_prefix ? escape($contact_name_prefix).' ' : null;
+		$contact_name .= $contact_name_given ? escape($contact_name_given).' ' : null;
+		$contact_name .= $contact_name_middle ? escape($contact_name_middle).' ' : null;
+		$contact_name .= $contact_name_family ? escape($contact_name_family).' ' : null;
+		$contact_name .= $contact_name_suffix ? escape($contact_name_suffix).' ' : null;
+	}
+	else {
+		$contact_name = $contact_organization;
+	}
+
+//show the header
+	$document['title'] = $text['title-contact-edit'].($contact_name ? ': '.$contact_name : null);
+	require_once "resources/header.php";
+
+//determine qr branding
+	if ($_SESSION['theme']['qr_brand_type']['text'] == 'image' && $_SESSION['theme']['qr_brand_image']['text'] != '') {
+		echo "<img id='img-buffer' style='display: none;' src='".$_SESSION["theme"]["qr_brand_image"]["text"]."'>";
+		$qr_option = "image: $('#img-buffer')[0],";
+		$qr_mode = '4';
+		$qr_size = '0.2';
+	}
+	else if ($_SESSION['theme']['qr_brand_type']['text'] == 'text' && $_SESSION['theme']['qr_brand_text']['text'] != '') {
+		$qr_option = 'label: "'.$_SESSION['theme']['qr_brand_text']['text'].'"';
+		$qr_mode = '2';
+		$qr_size = '0.05';
+	}
+	else {
+		echo "<img id='img-buffer' style='display: none;' src='".PROJECT_PATH."/themes/".$_SESSION["domain"]["template"]["name"]."/images/qr_code.png'>";
+		$qr_option = "image: $('#img-buffer')[0],";
+		$qr_mode = '4';
+		$qr_size = '0.2';
+	}
+
+//qr code generation
+	$_GET['type'] = "text";
+	$qr_vcard = true;
+	include "contacts_vcard.php";
+	echo "<input type='hidden' id='qr_vcard' value=\"".$qr_vcard."\">";
+	echo "<style>";
+	echo "	#qr_code_container {";
+	echo "		z-index: 999999; ";
+	echo "		position: absolute; ";
+	echo "		left: 0; ";
+	echo "		top: 0; ";
+	echo "		right: 0; ";
+	echo "		bottom: 0; ";
+	echo "		text-align: center; ";
+	echo "		vertical-align: middle;";
+	echo "	}";
+	echo "	#qr_code {";
+	echo "		display: block; ";
+	echo "		width: 650px; ";
+	echo "		height: 650px; ";
+	echo "		-webkit-box-shadow: 0px 1px 20px #888; ";
+	echo "		-moz-box-shadow: 0px 1px 20px #888; ";
+	echo "		box-shadow: 0px 1px 20px #888;";
+	echo "	}";
+	echo "</style>";
+	echo "<script src='".PROJECT_PATH."/resources/jquery/jquery-qrcode.min.js'></script>";
+	echo "<script language='JavaScript' type='text/javascript'>";
+	echo "	$(document).ready(function() {";
+	echo "		$('#qr_code').qrcode({ ";
+	echo "			render: 'canvas', ";
+	echo "			minVersion: 6, ";
+	echo "			maxVersion: 40, ";
+	echo "			ecLevel: 'H', ";
+	echo "			size: 650, ";
+	echo "			radius: 0.2, ";
+	echo "			quiet: 6, ";
+	echo "			background: '#fff', ";
+	echo "			mode: ".$qr_mode.", ";
+	echo "			mSize: ".$qr_size.", ";
+	echo "			mPosX: 0.5, ";
+	echo "			mPosY: 0.5, ";
+	echo "			text: document.getElementById('qr_vcard').value, ";
+	echo "			".$qr_option;
+	echo "		});";
+	echo "	});";
+	echo "</script>";
+
+//show the content
+	echo "<div class='action_bar' id='action_bar'>\n";
+	echo "	<div class='heading'><b>".($contact_name ? $contact_name : $text['header-contact-edit'])."</b></div>\n";
+	echo "	<div class='actions'>\n";
+	echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'id'=>'btn_back','collapse'=>'hide-sm-dn','style'=>'margin-right: 15px;','link'=>'contacts.php']);
+	if (permission_exists('contact_time_add')) {
+		//detect timer state (and start time)
+		$sql = "select ";
+		$sql .= "time_start ";
+		$sql .= "from v_contact_times ";
+		$sql .= "where domain_uuid = :domain_uuid ";
+		$sql .= "and user_uuid = :user_uuid ";
+		$sql .= "and contact_uuid = :contact_uuid ";
+		$sql .= "and time_start is not null ";
+		$sql .= "and time_stop is null ";
+		$parameters['domain_uuid'] = $_SESSION['domain_uuid'];
+		$parameters['user_uuid'] = $_SESSION['user']['user_uuid'];
+		$parameters['contact_uuid'] = $contact_uuid;
+		$database = new database;
+		$time_start = $database->select($sql, $parameters, 'column');
+		$btn_style = $time_start ? 'color: #fff; background-color: #3693df; background-image: none;' : null;
+		unset($sql, $parameters);
+		echo button::create(['type'=>'button','label'=>$text['button-timer'],'icon'=>'clock','style'=>$btn_style,'title'=>$time_start,'collapse'=>'hide-sm-dn','onclick'=>"window.open('contact_timer.php?domain_uuid=".urlencode($domain_uuid)."&contact_uuid=".urlencode($contact_uuid)."','contact_time_".escape($contact_uuid)."','width=300, height=375, top=30, left='+(screen.width - 350)+', menubar=no, scrollbars=no, status=no, toolbar=no, resizable=no');"]);
+	}
+	echo button::create(['type'=>'button','label'=>$text['button-qr_code'],'icon'=>'qrcode','collapse'=>'hide-sm-dn','onclick'=>"$('#qr_code_container').fadeIn(400);"]);
+	echo button::create(['type'=>'button','label'=>$text['button-vcard'],'icon'=>'address-card','collapse'=>'hide-sm-dn','link'=>'contacts_vcard.php?id='.urlencode($contact_uuid).'&type=download']);
+	if (is_dir($_SERVER["DOCUMENT_ROOT"].PROJECT_PATH.'/app/invoices')) {
+		echo button::create(['type'=>'button','label'=>$text['button-invoices'],'icon'=>'file-invoice-dollar','collapse'=>'hide-sm-dn','link'=>'../invoices/invoices.php?id='.urlencode($contact_uuid)]);
+	}
+	if (is_dir($_SERVER["DOCUMENT_ROOT"].PROJECT_PATH.'/app/certificates')) {
+		echo button::create(['type'=>'button','label'=>$text['button-certificate'],'icon'=>'certificate','collapse'=>'hide-sm-dn','link'=>'../certificates/index.php?name='.urlencode($contact_name_given." ".$contact_name_family)]);
+	}
+	if (permission_exists('user_edit') && is_uuid($contact_user_uuid)) {
+		echo button::create(['type'=>'button','label'=>$text['button-user'],'icon'=>'user','collapse'=>'hide-sm-dn','link'=>'../../core/users/user_edit.php?id='.urlencode($contact_user_uuid)]);
+	}
+	if (
+		permission_exists('contact_phone_add') ||
+		permission_exists('contact_address_add') ||
+		permission_exists('contact_email_add') ||
+		permission_exists('contact_url_add') ||
+		permission_exists('contact_relation_add') ||
+		permission_exists('contact_note_add') ||
+		permission_exists('contact_time_add') ||
+		permission_exists('contact_setting_add') ||
+		permission_exists('contact_attachment_add')
+		) {
+		echo 		"<select class='formfld' style='width: auto; margin-left: 15px;' id='select_add' onchange=\"document.location.href='contact_' + (this.options[this.selectedIndex].value) + '_edit.php?contact_uuid=".urlencode($contact_uuid)."';\">\n";
+		echo "			<option value=''>".$text['button-add']."...</option>\n";
+		if (permission_exists('contact_phone_add')) { echo "<option value='phone'>".$text['label-phone_number']."</option>\n"; }
+		if (permission_exists('contact_address_add')) { echo "<option value='address'>".$text['label-address_address']."</option>\n"; }
+		if (permission_exists('contact_email_add')) { echo "<option value='email'>".$text['label-email']."</option>\n"; }
+		if (permission_exists('contact_url_add')) { echo "<option value='url'>".$text['label-url']."</option>\n"; }
+		if (permission_exists('contact_relation_add')) { echo "<option value='relation'>".$text['label-contact_relation_label']."</option>\n"; }
+		if (permission_exists('contact_note_add')) { echo "<option value='note'>".$text['label-contact_note']."</option>\n"; }
+		if (permission_exists('contact_time_add')) { echo "<option value='time'>".$text['label-time_time']."</option>\n"; }
+		if (permission_exists('contact_setting_add')) { echo "<option value='setting'>".$text['label-setting']."</option>\n"; }
+		if (permission_exists('contact_attachment_add')) { echo "<option value='attachment'>".$text['label-attachment']."</option>\n"; }
+		echo "		</select>";
+	}
+	if (permission_exists('contact_edit')) {
+		echo button::create(['type'=>'button','label'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'id'=>'btn_edit','style'=>'margin-left: 15px;','collapse'=>'hide-sm-dn','link'=>'contact_edit.php?id='.urlencode($contact_uuid)]);
+	}
+	echo "	</div>\n";
+	echo "	<div style='clear: both;'></div>\n";
+	echo "</div>\n";
+
+	if (
+		$action == "update" && (
+		permission_exists('contact_delete') ||
+		permission_exists('contact_user_delete') ||
+		permission_exists('contact_group_delete') ||
+		permission_exists('contact_phone_delete') ||
+		permission_exists('contact_address_delete') ||
+		permission_exists('contact_email_delete') ||
+		permission_exists('contact_url_delete') ||
+		permission_exists('contact_relation_delete') ||
+		permission_exists('contact_note_delete') ||
+		permission_exists('contact_time_delete') ||
+		permission_exists('contact_setting_delete') ||
+		permission_exists('contact_attachment_delete')
+		)) {
+		echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'submit','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_delete','style'=>'float: right; margin-left: 15px;','collapse'=>'never','name'=>'action','value'=>'delete','onclick'=>"modal_close();"])]);
+	}
+
+	if ($contact_title || $contact_organization) {
+		echo ($contact_title ? '<i>'.$contact_title.'</i>' : null).($contact_title && $contact_organization ? ', ' : null).($contact_organization ? '<strong>'.$contact_organization.'</strong>' : null)."\n";
+	}
+	else {
+		echo $contact_note."\n";
+	}
+	echo "<br /><br />\n";
+
+	echo "<div class='grid' style='grid-gap: 15px; grid-template-columns: repeat(auto-fill, minmax(375px, 1fr));'>\n";
+
+//general info
+	echo "	<div class='box contact-details'>\n";
+	echo "		<div class='grid contact-details'>\n";
+	echo "			<div class='box'><b class='fas fa-user fa-fw fa-lg'></b></div>\n";
+	echo "			<div class='box'>\n";
+	echo "				<div class='grid' style='grid-template-columns: 70px auto;'>\n";
+		//nickname
+			if ($contact_nickname) {
+				echo "<div class='box contact-details-label'>".$text['label-contact_nickname']."</div>\n";
+				echo "<div class='box'>\"".escape($contact_nickname)."\"</div>\n";
+			}
+		//contact type
+			if ($contact_type) {
+				echo "<div class='box contact-details-label'>".$text['label-contact_type']."</div>\n";
+				echo "<div class='box'>";
+				if (is_array($_SESSION["contact"]["type"])) {
+					sort($_SESSION["contact"]["type"]);
+					foreach ($_SESSION["contact"]["type"] as $type) {
+						if ($contact_type == $type) {
+							echo escape($type);
+						}
+					}
+				}
+				else if ($text['option-contact_type_'.$contact_type]) {
+					echo $text['option-contact_type_'.$contact_type];
+				}
+				else {
+					echo escape($contact_type);
+				}
+				echo "</div>\n";
+			}
+		//category
+			if ($contact_category) {
+				echo "<div class='box contact-details-label'>".$text['label-contact_category']."</div>\n";
+				echo "<div class='box'>";
+				if (is_array($_SESSION["contact"]["category"])) {
+					sort($_SESSION["contact"]["category"]);
+					foreach ($_SESSION["contact"]["category"] as $category) {
+						if ($contact_category == $category) {
+							echo escape($category);
+							break;
+						}
+					}
+				}
+				else {
+					echo escape($contact_category);
+				}
+				echo "</div>\n";
+			}
+		//role
+			if ($contact_role) {
+				echo "<div class='box contact-details-label'>".$text['label-contact_role']."</div>\n";
+				echo "<div class='box'>";
+				if (is_array($_SESSION["contact"]["role"])) {
+					sort($_SESSION["contact"]["role"]);
+					foreach ($_SESSION["contact"]["role"] as $role) {
+						if ($contact_role == $role) {
+							echo escape($role);
+							break;
+						}
+					}
+				}
+				else {
+					echo escape($contact_role);
+				}
+				echo "</div>\n";
+			}
+		//time_zone
+			if ($contact_time_zone) {
+				echo "<div class='box contact-details-label'>".$text['label-contact_time_zone']."</div>\n";
+				echo "<div class='box'>";
+				echo $contact_time_zone."<br>\n";
+				echo "</div>\n";
+			}
+		//users (viewing contact)
+			if (permission_exists('contact_user_view') && is_array($contact_users_assigned) && @sizeof($contact_users_assigned) != 0) {
+				echo "<div class='box contact-details-label'>".$text['label-users']."</div>\n";
+				echo "<div class='box'>";
+				foreach ($contact_users_assigned as $field) {
+					echo escape($field['username'])."<br>\n";
+				}
+				echo "</div>\n";
+			}
+		//groups (viewing contact)
+			if (permission_exists('contact_group_view') && is_array($contact_groups_assigned) && @sizeof($contact_groups_assigned) != 0) {
+				echo "<div class='box contact-details-label'>".$text['label-groups']."</div>\n";
+				echo "<div class='box'>";
+				foreach ($contact_groups_assigned as $field) {
+					echo escape($field['group_name'])."<br>\n";
+				}
+				echo "</div>\n";
+			}
+	echo "				</div>\n";
+	echo "			</div>\n";
+	echo "		</div>\n";
+	echo "	</div>\n";
+
+//numbers
+	if (permission_exists('contact_phone_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['label-phone_numbers']."\"><b class='fas fa-hashtag fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require 'contact_phones_view.php';
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+//emails
+	if (permission_exists('contact_email_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['label-emails']."\"><b class='fas fa-envelope fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require 'contact_emails_view.php';
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+//addresses
+	if (permission_exists('contact_address_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['label-addresses']."\"><b class='fas fa-map-marker-alt fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require 'contact_addresses_view.php';
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+//urls
+	if (permission_exists('contact_url_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['label-urls']."\"><b class='fas fa-link fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require "contact_urls_view.php";
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+//relations
+	if (permission_exists('contact_relation_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['header-contact_relations']."\"><b class='fas fa-project-diagram fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require "contact_relations_view.php";
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+//attachments
+	if (permission_exists('contact_attachment_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['label-attachments']."\"><b class='fas fa-paperclip fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require "contact_attachments_view.php";
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+//times
+	if (permission_exists('contact_time_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['header_contact_times']."\"><b class='fas fa-clock fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require "contact_times_view.php";
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+//extensions
+	if (permission_exists('contact_extension_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['label-contact_extensions']."\"><b class='fas fa-fax fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require "contact_extensions_view.php";
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+	echo "</div>\n";
+	echo "<div class='grid' style='margin-top: 15px; grid-template-columns: auto;'>\n";
+
+//notes
+	if (permission_exists('contact_note_view')) {
+		echo "	<div class='box contact-details'>\n";
+		echo "		<div class='grid contact-details'>\n";
+		echo "			<div class='box' title=\"".$text['label-contact_notes']."\"><b class='fas fa-sticky-note fa-fw fa-lg'></b></div>\n";
+		echo "			<div class='box'>\n";
+		require "contact_notes_view.php";
+		echo "			</div>\n";
+		echo "		</div>\n";
+		echo "	</div>\n";
+	}
+
+	echo "</div>\n";
+	echo "<br><br>\n";
+
+//include the footer
+	require_once "resources/footer.php";
+
+?>

+ 10 - 9
contacts.php

@@ -256,11 +256,10 @@
 		echo button::create(['type'=>'button','label'=>$text['button-import'],'icon'=>$_SESSION['theme']['button_icon_import'],'collapse'=>'hide-sm-dn','style'=>'margin-right: 15px;','link'=>'contact_import.php']);
 	}
 	if (permission_exists('contact_add')) {
-		echo button::create(['type'=>'button','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add'],'collapse'=>'hide-sm-dn','link'=>'contact_edit.php']);
+		echo button::create(['type'=>'button','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add'],'id'=>'btn_add','collapse'=>'hide-sm-dn','link'=>'contact_edit.php']);
 	}
 	if (permission_exists('contact_delete') && $contacts) {
-		echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'collapse'=>'hide-sm-dn','link'=>'#modal-delete']);
-		echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('delete'); list_form_submit('form_list');"])]);
+		echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'name'=>'btn_delete','collapse'=>'hide-sm-dn','onclick'=>"modal_open('modal-delete','btn_delete');"]);
 	}
 	echo 		"<form id='form_search' class='inline' method='get'>\n";
 	echo 		"<input type='text' class='txt list-search' name='search' id='search' value=\"".escape($search)."\" placeholder=\"".$text['label-search']."\" onkeydown='list_search_reset();'>";
@@ -274,6 +273,10 @@
 	echo "	<div style='clear: both;'></div>\n";
 	echo "</div>\n";
 
+	if (permission_exists('contact_delete') && $contacts) {
+		echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_delete','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('delete'); list_form_submit('form_list');"])]);
+	}
+
 	echo $text['description-contacts']."\n";
 	echo "<br /><br />\n";
 
@@ -297,7 +300,7 @@
 	echo th_order_by('contact_title', $text['label-contact_title'], $order_by, $order, null, "class='hide-sm-dn'");
 	echo th_order_by('contact_role', $text['label-contact_role'], $order_by, $order, null, "class='hide-sm-dn'");
 	echo "<th class='shrink hide-sm-dn'>&nbsp;</th>\n";
-	if (permission_exists('contact_edit') && $_SESSION['theme']['list_row_edit_button']['boolean'] == 'true') {
+	if ($_SESSION['theme']['list_row_edit_button']['boolean'] == 'true') {
 		echo "	<td class='action-button'>&nbsp;</td>\n";
 	}
 	echo "</tr>\n";
@@ -305,9 +308,7 @@
 	if (is_array($contacts) && @sizeof($contacts) != 0) {
 		$x = 0;
 		foreach($contacts as $row) {
-			if (permission_exists('contact_edit')) {
-				$list_row_url = "contact_edit.php?id=".urlencode($row['contact_uuid'])."&query_string=".urlencode($_SERVER["QUERY_STRING"]);
-			}
+			$list_row_url = "contact_view.php?id=".urlencode($row['contact_uuid'])."&query_string=".urlencode($_SERVER["QUERY_STRING"]);
 			echo "<tr class='list-row' href='".$list_row_url."'>\n";
 			if (permission_exists('contact_delete')) {
 				echo "	<td class='checkbox'>\n";
@@ -339,9 +340,9 @@
 				echo "&nbsp;";
 			}
 			echo "	</td>\n";
-			if (permission_exists('contact_edit') && $_SESSION['theme']['list_row_edit_button']['boolean'] == 'true') {
+			if ($_SESSION['theme']['list_row_edit_button']['boolean'] == 'true') {
 				echo "	<td class='action-button'>";
-				echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]);
+				echo button::create(['type'=>'button','title'=>$text['button-view'],'icon'=>$_SESSION['theme']['button_icon_view'],'link'=>$list_row_url]);
 				echo "	</td>\n";
 			}
 			echo "</tr>\n";

BIN
resources/images/icon_gmaps.png