From 9900603d3763cb5d16564d3019074b2bf499506a Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Fri, 19 Jul 2024 16:25:42 +0100
Subject: [PATCH 1/8] Add button - doesn't do anything yet
---
web/js/search.js.php | 16 ++++++++++++++++
web/lang/lang.en | 1 +
2 files changed, 17 insertions(+)
diff --git a/web/js/search.js.php b/web/js/search.js.php
index 10ed37628e..28baff5370 100644
--- a/web/js/search.js.php
+++ b/web/js/search.js.php
@@ -51,6 +51,22 @@
tableOptions.columnDefs = getTypes(table);
+ tableOptions.buttons = [
+ {
+
+ extend: 'colvis'
+ },
+ {
+
+ text: '',
+ action: function (e, dt, node, config) {
+ alert('Button activated');
+ }
+ }
+ ]
+
makeDataTable('#search_results', tableOptions, {"leftColumns": 1});
}
diff --git a/web/lang/lang.en b/web/lang/lang.en
index d766b2a585..ac648de589 100644
--- a/web/lang/lang.en
+++ b/web/lang/lang.en
@@ -403,6 +403,7 @@ $vocab["entry"] = "Entry";
$vocab["search_button"] = "Search";
$vocab["search_for"] = "Search for";
$vocab["from"] = "From";
+$vocab["export_as_ics"] = ".ics";
// Used in report.php
$vocab["report_on"] = "Report on Meetings";
From 05790822ebfaedaff927fc2170f9ce9a2f0d1c5d Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Sat, 20 Jul 2024 06:34:28 +0100
Subject: [PATCH 2/8] Add button - doesn't do anything yet
---
web/js/search.js.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/web/js/search.js.php b/web/js/search.js.php
index 28baff5370..3cc8645b1d 100644
--- a/web/js/search.js.php
+++ b/web/js/search.js.php
@@ -62,7 +62,8 @@
?>
text: '',
action: function (e, dt, node, config) {
- alert('Button activated');
+ var data = $('#search_form').serializeArray();
+ $.post(window.location.href, data);
}
}
]
From 5b7db5873489c783f4cd36878cd54236991d54d7 Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Sat, 20 Jul 2024 10:12:26 +0100
Subject: [PATCH 3/8] Add an ics parameter to post request
---
web/js/search.js.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/web/js/search.js.php b/web/js/search.js.php
index c3afd5d8d9..9027a98faa 100644
--- a/web/js/search.js.php
+++ b/web/js/search.js.php
@@ -53,6 +53,7 @@
text: '',
action: function (e, dt, node, config) {
var data = $('#search_form').serializeArray();
+ data.push({name: 'ics', value: 1});
$.post(window.location.href, data);
}
}
From 998742a4d1c6a770a5af68cd1e667c127d87c2e7 Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Sat, 20 Jul 2024 10:22:57 +0100
Subject: [PATCH 4/8] Add comments
---
web/js/search.js.php | 2 ++
1 file changed, 2 insertions(+)
diff --git a/web/js/search.js.php b/web/js/search.js.php
index 9027a98faa..f87fed7271 100644
--- a/web/js/search.js.php
+++ b/web/js/search.js.php
@@ -52,7 +52,9 @@
?>
text: '',
action: function (e, dt, node, config) {
+
var data = $('#search_form').serializeArray();
+
data.push({name: 'ics', value: 1});
$.post(window.location.href, data);
}
From 69bfab2a70da4d1a74608fee13b5cb76817ae99a Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Sat, 20 Jul 2024 11:10:47 +0100
Subject: [PATCH 5/8] Interim commit
---
web/search.php | 31 ++++++++++++++++++++-----------
1 file changed, 20 insertions(+), 11 deletions(-)
diff --git a/web/search.php b/web/search.php
index 06225e91e6..31d1a232f6 100644
--- a/web/search.php
+++ b/web/search.php
@@ -66,7 +66,7 @@ function output_row($row, $returl)
{
global $is_ajax, $json_data, $view;
- $vars = array('id' => $row['entry_id'],
+ $vars = array('id' => $row['id'],
'returl' => $returl);
$query = http_build_query($vars, '', '&');
@@ -125,7 +125,7 @@ function output_row($row, $returl)
$search_pos = get_form_var('search_pos', 'int');
$total = get_form_var('total', 'int');
$datatable = get_form_var('datatable', 'int'); // Will only be set if we're using DataTables
-// Get the start day/month/year and make them the current day/month/year
+$ics = get_form_var('ics', 'bool', false);
$from_date = get_form_var('from_date', 'string');
// If we're going to be doing something then check the CSRF token
@@ -166,7 +166,7 @@ function output_row($row, $returl)
}
}
-if (!$is_ajax) {
+if (!($is_ajax || $ics)) {
$context = array(
'view' => $view,
'view_all' => $view_all,
@@ -336,7 +336,7 @@ function output_row($row, $returl)
$total = db()->query1($sql, $sql_params);
}
-if (($total <= 0) && !$is_ajax)
+if (($total <= 0) && !($is_ajax || $ics))
{
echo "
" . get_vocab("nothing_found") . "
\n";
print_footer();
@@ -355,11 +355,12 @@ function output_row($row, $returl)
// If we're Ajax capable and this is not an Ajax request then don't output
// the table body, because that's going to be sent later in response to
// an Ajax request - so we don't need to do the query
-if (!$ajax_capable || $is_ajax)
+if (!$ajax_capable || $is_ajax || $ics)
{
// Now we set up the "real" query
- $sql = "SELECT E.id AS entry_id, E.create_by, E.name, E.description, E.start_time,
- E.room_id, R.area_id, A.enable_periods
+ $sql = "SELECT E.*, " .
+ db()->syntax_timestamp_to_unix("E.timestamp") . " AS last_updated, " .
+ "A.area_name, R.room_name, R.area_id, A.enable_periods
FROM " . _tbl('entry') . " E
LEFT JOIN " . _tbl('room') . " R
ON E.room_id = R.id
@@ -367,9 +368,9 @@ function output_row($row, $returl)
ON R.area_id = A.id
WHERE $sql_pred
ORDER BY E.start_time asc";
- // If it's an Ajax query we want everything. Otherwise we use LIMIT to just get
+ // If it's an Ajax query or an ics export we want everything. Otherwise we use LIMIT to just get
// the stuff we want.
- if (!$is_ajax)
+ if (!($is_ajax || $ics))
{
$sql .= " " . db()->syntax_limit($search["count"], $search_pos);
}
@@ -379,12 +380,12 @@ function output_row($row, $returl)
$num_records = $result->count();
}
-if (!$ajax_capable)
+if (!($ajax_capable || $ics))
{
echo generate_search_nav_html($search_pos, $total, $num_records, $search_str);
}
-if (!$is_ajax)
+if (!($is_ajax || $ics))
{
echo "\n";
echo "
\n";
}
+if ($ics)
+{
+ // We set $keep_private to FALSE here because we excluded all private
+ // events in the SQL query
+ export_icalendar($result, false);
+ exit;
+}
+
// If we're Ajax capable and this is not an Ajax request then don't output
// the table body, because that's going to be sent later in response to
// an Ajax request
From 84ef22ebf5d974546ce0cd464455461598ec3fff Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Sat, 20 Jul 2024 15:15:29 +0100
Subject: [PATCH 6/8] First working version
---
web/js/search.js.php | 41 ++++++++++++++++++++++++++++++++++++++++-
web/search.php | 6 ++++++
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/web/js/search.js.php b/web/js/search.js.php
index f87fed7271..0d5e61275f 100644
--- a/web/js/search.js.php
+++ b/web/js/search.js.php
@@ -56,7 +56,46 @@
var data = $('#search_form').serializeArray();
data.push({name: 'ics', value: 1});
- $.post(window.location.href, data);
+ $.post({
+ url: window.location.href,
+ data: data,
+ success: function(blob, status, xhr) {
+ // check for a filename
+ var filename = "";
+ var disposition = xhr.getResponseHeader('Content-Disposition');
+ if (disposition && disposition.indexOf('attachment') !== -1) {
+ var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
+ var matches = filenameRegex.exec(disposition);
+ if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
+ }
+
+ if (typeof window.navigator.msSaveBlob !== 'undefined') {
+ // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
+ window.navigator.msSaveBlob(blob, filename);
+ } else {
+ var URL = window.URL || window.webkitURL;
+ var downloadUrl = URL.createObjectURL(new Blob([blob], {type: 'application/ics'}));
+
+ if (filename) {
+ // use HTML5 a[download] attribute to specify filename
+ var a = document.createElement("a");
+ // safari doesn't support this yet
+ if (typeof a.download === 'undefined') {
+ window.location.href = downloadUrl;
+ } else {
+ a.href = downloadUrl;
+ a.download = filename;
+ document.body.appendChild(a);
+ a.click();
+ }
+ } else {
+ window.location.href = downloadUrl;
+ }
+
+ setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
+ }
+ }
+ });
}
}
]
diff --git a/web/search.php b/web/search.php
index 31d1a232f6..0e92ce2312 100644
--- a/web/search.php
+++ b/web/search.php
@@ -412,6 +412,12 @@ function output_row($row, $returl)
if ($ics)
{
+ $filename = 'search.ics';
+ $content_type = "application/ics; charset=" . get_charset() . "; name=\"$filename\"";
+ http_headers(array(
+ "Content-Type: $content_type",
+ "Content-Disposition: attachment; filename=\"$filename\"")
+ );
// We set $keep_private to FALSE here because we excluded all private
// events in the SQL query
export_icalendar($result, false);
From 8675c8fa6ade5db0d8a0292d91415f14d66ca2f3 Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Sat, 20 Jul 2024 15:58:54 +0100
Subject: [PATCH 7/8] Take content type from server
---
web/js/search.js.php | 64 ++++++++++++++++++++++++--------------------
1 file changed, 35 insertions(+), 29 deletions(-)
diff --git a/web/js/search.js.php b/web/js/search.js.php
index 0d5e61275f..b87e58e7cd 100644
--- a/web/js/search.js.php
+++ b/web/js/search.js.php
@@ -60,41 +60,47 @@
url: window.location.href,
data: data,
success: function(blob, status, xhr) {
- // check for a filename
- var filename = "";
- var disposition = xhr.getResponseHeader('Content-Disposition');
- if (disposition && disposition.indexOf('attachment') !== -1) {
- var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
- var matches = filenameRegex.exec(disposition);
- if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
- }
+
+ var contentType = xhr.getResponseHeader('Content-Type');
+ var contentTypeRegex = /^[^;]*/;
+ var matches = contentType.match(contentTypeRegex);
+ var type = (matches === null) ? '' : matches[0];
+ var filename = "";
+ var disposition = xhr.getResponseHeader('Content-Disposition');
+ if (disposition && disposition.indexOf('attachment') !== -1) {
+ var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
+ matches = filenameRegex.exec(disposition);
+ if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
+ }
- if (typeof window.navigator.msSaveBlob !== 'undefined') {
- // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
- window.navigator.msSaveBlob(blob, filename);
- } else {
- var URL = window.URL || window.webkitURL;
- var downloadUrl = URL.createObjectURL(new Blob([blob], {type: 'application/ics'}));
+ if (typeof window.navigator.msSaveBlob !== 'undefined') {
+ // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
+ window.navigator.msSaveBlob(blob, filename);
+ } else {
+ var URL = window.URL || window.webkitURL;
+ var downloadUrl = URL.createObjectURL(new Blob([blob], {type: type}));
- if (filename) {
- // use HTML5 a[download] attribute to specify filename
- var a = document.createElement("a");
- // safari doesn't support this yet
- if (typeof a.download === 'undefined') {
- window.location.href = downloadUrl;
+ if (filename) {
+ // use HTML5 a[download] attribute to specify filename
+ var a = document.createElement("a");
+ // safari doesn't support this yet
+ if (typeof a.download === 'undefined') {
+ window.location.href = downloadUrl;
+ } else {
+ a.href = downloadUrl;
+ a.download = filename;
+ document.body.appendChild(a);
+ a.click();
+ }
} else {
- a.href = downloadUrl;
- a.download = filename;
- document.body.appendChild(a);
- a.click();
+ window.location.href = downloadUrl;
}
- } else {
- window.location.href = downloadUrl;
- }
- setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
+ setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
+ }
}
- }
});
}
}
From 8a89a82187ee3d0b41b497be840c207fd3670ce0 Mon Sep 17 00:00:00 2001
From: campbell-m <87438215+campbell-m@users.noreply.github.com>
Date: Sat, 20 Jul 2024 16:09:00 +0100
Subject: [PATCH 8/8] Make file name a config setting
---
web/search.php | 2 +-
web/systemdefaults.inc.php | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/web/search.php b/web/search.php
index 0e92ce2312..49e886b3e4 100644
--- a/web/search.php
+++ b/web/search.php
@@ -412,7 +412,7 @@ function output_row($row, $returl)
if ($ics)
{
- $filename = 'search.ics';
+ $filename = "$search_filename.ics";
$content_type = "application/ics; charset=" . get_charset() . "; name=\"$filename\"";
http_headers(array(
"Content-Type: $content_type",
diff --git a/web/systemdefaults.inc.php b/web/systemdefaults.inc.php
index e860d47d51..aeca4eb288 100644
--- a/web/systemdefaults.inc.php
+++ b/web/systemdefaults.inc.php
@@ -1860,6 +1860,7 @@
// Default file names
$report_filename = "report";
+$search_filename = "search";
$summary_filename = "summary";
// CSV format