diff --git a/agent/document_details.php b/agent/document_details.php
index f0456a7c..ad86884d 100644
--- a/agent/document_details.php
+++ b/agent/document_details.php
@@ -163,17 +163,19 @@ $page_title = $row['document_name'];
-
-
-
-
+
+
+
+
diff --git a/agent/post/document.php b/agent/post/document.php
index 35681336..30ce36b3 100644
--- a/agent/post/document.php
+++ b/agent/post/document.php
@@ -633,7 +633,15 @@ if (isset($_GET['delete_document'])) {
flash_alert("Document $document_name deleted and all versions", 'error');
- redirect();
+ // Determine redirect behavior
+ // If there's a "from" parameter, we can use it to decide where to go
+ if (isset($_GET['from']) && $_GET['from'] === 'document_details') {
+ // User deleted from document_details.php
+ redirect("documents.php?client_id=$client_id");
+ } else {
+ // Default behavior — redirect back to previous page
+ redirect();
+ }
}
diff --git a/js/app.js b/js/app.js
index e8e6b0fe..b73b5616 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,380 +1,403 @@
$(document).ready(function() {
- //Prevents resubmit on forms
- if(window.history.replaceState){
- window.history.replaceState(null, null, window.location.href);
- }
+ // Prevents resubmit on forms
+ if (window.history.replaceState) {
+ window.history.replaceState(null, null, window.location.href);
+ }
- // Slide alert up after 4 secs
- $("#alert").fadeTo(5000, 500).slideUp(500, function(){
- $("#alert").slideUp(500);
- });
+ // Slide alert up after 4 secs
+ $("#alert").fadeTo(5000, 500).slideUp(500, function() {
+ $("#alert").slideUp(500);
+ });
- // Initialize Select2 Elements
- $('.select2').select2({
- theme: 'bootstrap4',
- });
+ // Initialize Select2 Elements
+ $('.select2').select2({
+ theme: 'bootstrap4',
+ });
- // Initialize TinyMCE
- tinymce.init({
- selector: '.tinymce-simple',
- browser_spellcheck: true,
- contextmenu: false,
- resize: true,
- min_height: 300,
- max_height: 600,
- promotion: false,
- branding: false,
- menubar: false,
- statusbar: false,
- toolbar: [
- { name: 'styles', items: [ 'styles' ] },
- { name: 'formatting', items: [ 'bold', 'italic', 'forecolor' ] },
- { name: 'link', items: [ 'link'] },
- { name: 'lists', items: [ 'bullist', 'numlist' ] },
- { name: 'alignment', items: [ 'alignleft', 'aligncenter', 'alignright', 'alignjustify' ] },
- { name: 'indentation', items: [ 'outdent', 'indent' ] },
- { name: 'table', items: [ 'table' ] },
- { name: 'extra', items: [ 'code', 'fullscreen' ] }
- ],
- mobile: {
- menubar: false,
- plugins: 'autosave lists autolink',
- toolbar: 'bold italic styles'
- },
- convert_urls: false,
- plugins: 'link image lists table code codesample fullscreen autoresize',
- license_key: 'gpl'
- });
-
- // Initialize TinyMCE with AI
- tinymce.init({
- selector: '.tinymce',
- browser_spellcheck: true,
- contextmenu: false,
- resize: true,
- min_height: 300,
- max_height: 600,
- promotion: false,
- branding: false,
- menubar: false,
- statusbar: false,
- toolbar: [
- { name: 'styles', items: [ 'styles' ] },
- { name: 'formatting', items: [ 'bold', 'italic', 'forecolor' ] },
- { name: 'link', items: [ 'link'] },
- { name: 'lists', items: [ 'bullist', 'numlist' ] },
- { name: 'alignment', items: [ 'alignleft', 'aligncenter', 'alignright', 'alignjustify' ] },
- { name: 'indentation', items: [ 'outdent', 'indent' ] },
- { name: 'table', items: [ 'table' ] },
- { name: 'extra', items: [ 'code', 'fullscreen' ] },
- { name: 'ai', items: [ 'reword', 'undo', 'redo' ] }
- ],
- mobile: {
- menubar: false,
- plugins: 'autosave lists autolink',
- toolbar: 'bold italic styles'
- },
- convert_urls: false,
- plugins: 'link image lists table code codesample fullscreen autoresize',
- license_key: 'gpl',
- setup: function(editor) {
- var rewordButtonApi;
-
- editor.ui.registry.addButton('reword', {
- icon: 'ai',
- tooltip: 'Reword Text',
- onAction: function() {
- var content = editor.getContent();
-
- // Disable the Reword button
- rewordButtonApi.setEnabled(false);
-
- // Show the progress indicator
- editor.setProgressState(true);
-
- fetch('post.php?ai_reword', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ text: content }),
- })
- .then(response => {
- if (!response.ok) {
- throw new Error('Network response was not ok');
- }
- return response.json();
- })
- .then(data => {
- editor.undoManager.transact(function() {
- editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
- });
-
- // Hide the progress indicator
- editor.setProgressState(false);
-
- // Re-enable the Reword button
- rewordButtonApi.setEnabled(true);
-
- // Optional: Show a success notification
- editor.notificationManager.open({
- text: 'Text reworded successfully!',
- type: 'success',
- timeout: 3000
- });
- })
- .catch(error => {
- console.error('Error:', error);
-
- // Hide the progress indicator
- editor.setProgressState(false);
-
- // Re-enable the Reword button
- rewordButtonApi.setEnabled(true);
-
- // Show an error notification
- editor.notificationManager.open({
- text: 'An error occurred while rewording the text.',
- type: 'error',
- timeout: 5000
- });
- });
- },
- onSetup: function(buttonApi) {
- rewordButtonApi = buttonApi;
- return function() {
- // Cleanup when the editor is destroyed (if necessary)
- };
- }
- });
- }
- });
-
- // Initialize TinyMCE AI
- tinymce.init({
- selector: '.tinymceTicket',
- browser_spellcheck: true,
- contextmenu: false,
- resize: true,
- min_height: 300,
- max_height: 600,
- promotion: false,
- branding: false,
- menubar: false,
- statusbar: false,
- toolbar: [
- { name: 'styles', items: ['styles'] },
- { name: 'formatting', items: ['bold', 'italic', 'forecolor'] },
- { name: 'link', items: ['link'] },
- { name: 'lists', items: ['bullist', 'numlist'] },
- { name: 'indentation', items: ['outdent', 'indent'] },
- { name: 'ai', items: ['reword', 'undo', 'redo'] },
- { name: 'custom', items: ['redactButton'] }, // Add custom redact button to toolbar
- { name: 'code', items: ['code'] },
- ],
- mobile: {
- menubar: false,
- toolbar: 'bold italic styles'
- },
- convert_urls: false,
- plugins: 'link image lists table code codesample fullscreen autoresize code',
- license_key: 'gpl',
- setup: function(editor) {
- var rewordButtonApi;
-
- // Define the Reword button (AI-related button)
- editor.ui.registry.addButton('reword', {
- icon: 'ai', // Example icon for AI rewording
- tooltip: 'Reword Text',
- onAction: function() {
- var content = editor.getContent();
-
- // Disable the Reword button
- rewordButtonApi.setEnabled(false);
-
- // Show the progress indicator
- editor.setProgressState(true);
-
- fetch('post.php?ai_reword', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ text: content }),
- })
- .then(response => {
- if (!response.ok) {
- throw new Error('Network response was not ok');
- }
- return response.json();
- })
- .then(data => {
- editor.undoManager.transact(function() {
- editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
- });
-
- // Hide the progress indicator
- editor.setProgressState(false);
-
- // Re-enable the Reword button
- rewordButtonApi.setEnabled(true);
-
- // Optional: Show a success notification
- editor.notificationManager.open({
- text: 'Text reworded successfully!',
- type: 'success',
- timeout: 3000
- });
- })
- .catch(error => {
- console.error('Error:', error);
-
- // Hide the progress indicator
- editor.setProgressState(false);
-
- // Re-enable the Reword button
- rewordButtonApi.setEnabled(true);
-
- // Show an error notification
- editor.notificationManager.open({
- text: 'An error occurred while rewording the text.',
- type: 'error',
- timeout: 5000
- });
- });
+ // Initialize TinyMCE
+ tinymce.init({
+ selector: '.tinymce-simple',
+ browser_spellcheck: true,
+ contextmenu: false,
+ resize: true,
+ min_height: 300,
+ max_height: 600,
+ promotion: false,
+ branding: false,
+ menubar: false,
+ statusbar: false,
+ toolbar: [
+ { name: 'styles', items: ['styles'] },
+ { name: 'formatting', items: ['bold', 'italic', 'forecolor'] },
+ { name: 'link', items: ['link'] },
+ { name: 'lists', items: ['bullist', 'numlist'] },
+ { name: 'alignment', items: ['alignleft', 'aligncenter', 'alignright', 'alignjustify'] },
+ { name: 'indentation', items: ['outdent', 'indent'] },
+ { name: 'table', items: ['table'] },
+ { name: 'extra', items: ['code', 'fullscreen'] }
+ ],
+ mobile: {
+ menubar: false,
+ plugins: 'autosave lists autolink',
+ toolbar: 'bold italic styles'
},
- onSetup: function(buttonApi) {
- rewordButtonApi = buttonApi;
- return function() {
- // Cleanup when the editor is destroyed (if necessary)
- };
+ convert_urls: false,
+ plugins: 'link image lists table code codesample fullscreen autoresize',
+ setup: function (editor) {
+ editor.on('init', function() {
+ window.onbeforeunload = function() {
+ // If editor is dirty AND not inside a visible modal → warn
+ const inVisibleModal = editor.getContainer()?.closest('.modal.show');
+ if (!inVisibleModal && editor.isDirty()) {
+ return "You have unsaved changes. Are you sure you want to leave?";
+ }
+ };
+
+ // When the modal closes, mark editor clean
+ const modal = editor.getContainer()?.closest('.modal');
+ if (modal) {
+ modal.addEventListener('hidden.bs.modal', () => {
+ editor.undoManager.clear();
+ editor.setDirty(false);
+ });
+ }
+ });
+ },
+ license_key: 'gpl'
+ });
+
+ // Initialize TinyMCE with AI
+ tinymce.init({
+ selector: '.tinymce',
+ browser_spellcheck: true,
+ contextmenu: false,
+ resize: true,
+ min_height: 300,
+ max_height: 600,
+ promotion: false,
+ branding: false,
+ menubar: false,
+ statusbar: false,
+ toolbar: [
+ { name: 'styles', items: ['styles'] },
+ { name: 'formatting', items: ['bold', 'italic', 'forecolor'] },
+ { name: 'link', items: ['link'] },
+ { name: 'lists', items: ['bullist', 'numlist'] },
+ { name: 'alignment', items: ['alignleft', 'aligncenter', 'alignright', 'alignjustify'] },
+ { name: 'indentation', items: ['outdent', 'indent'] },
+ { name: 'table', items: ['table'] },
+ { name: 'extra', items: ['code', 'fullscreen'] },
+ { name: 'ai', items: ['reword', 'undo', 'redo'] }
+ ],
+ mobile: {
+ menubar: false,
+ plugins: 'autosave lists autolink',
+ toolbar: 'bold italic styles'
+ },
+ convert_urls: false,
+ plugins: 'link image lists table code codesample fullscreen autoresize',
+ license_key: 'gpl',
+ setup: function(editor) {
+ editor.on('init', function() {
+ window.onbeforeunload = function() {
+ // If editor is dirty AND not inside a visible modal → warn
+ const inVisibleModal = editor.getContainer()?.closest('.modal.show');
+ if (!inVisibleModal && editor.isDirty()) {
+ return "You have unsaved changes. Are you sure you want to leave?";
+ }
+ };
+
+ // When the modal closes, mark editor clean
+ const modal = editor.getContainer()?.closest('.modal');
+ if (modal) {
+ modal.addEventListener('hidden.bs.modal', () => {
+ editor.undoManager.clear();
+ editor.setDirty(false);
+ });
+ }
+ });
+
+ var rewordButtonApi;
+
+ editor.ui.registry.addButton('reword', {
+ icon: 'ai',
+ tooltip: 'Reword Text',
+ onAction: function() {
+ var content = editor.getContent();
+
+ // Disable the Reword button
+ rewordButtonApi.setEnabled(false);
+
+ // Show the progress indicator
+ editor.setProgressState(true);
+
+ fetch('post.php?ai_reword', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ text: content }),
+ })
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ editor.undoManager.transact(function() {
+ editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
+ });
+
+ editor.setProgressState(false);
+ rewordButtonApi.setEnabled(true);
+
+ editor.notificationManager.open({
+ text: 'Text reworded successfully!',
+ type: 'success',
+ timeout: 3000
+ });
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ editor.setProgressState(false);
+ rewordButtonApi.setEnabled(true);
+ editor.notificationManager.open({
+ text: 'An error occurred while rewording the text.',
+ type: 'error',
+ timeout: 5000
+ });
+ });
+ },
+ onSetup: function(buttonApi) {
+ rewordButtonApi = buttonApi;
+ return function() {};
+ }
+ });
}
- });
+ });
- // Add the Redact button
- editor.ui.registry.addButton('redactButton', {
- icon: 'permanent-pen',
- tooltip: 'Redact Text', // Tooltip text for the button
- onAction: function() {
- var selectedText = editor.selection.getContent({ format: 'text' });
+ // Initialize TinyMCE AI for Tickets
+ tinymce.init({
+ selector: '.tinymceTicket',
+ browser_spellcheck: true,
+ contextmenu: false,
+ resize: true,
+ min_height: 300,
+ max_height: 600,
+ promotion: false,
+ branding: false,
+ menubar: false,
+ statusbar: false,
+ toolbar: [
+ { name: 'styles', items: ['styles'] },
+ { name: 'formatting', items: ['bold', 'italic', 'forecolor'] },
+ { name: 'link', items: ['link'] },
+ { name: 'lists', items: ['bullist', 'numlist'] },
+ { name: 'indentation', items: ['outdent', 'indent'] },
+ { name: 'ai', items: ['reword', 'undo', 'redo'] },
+ { name: 'custom', items: ['redactButton'] },
+ { name: 'code', items: ['code'] },
+ ],
+ mobile: {
+ menubar: false,
+ toolbar: 'bold italic styles'
+ },
+ convert_urls: false,
+ plugins: 'link image lists table code codesample fullscreen autoresize code',
+ license_key: 'gpl',
+ setup: function(editor) {
+ editor.on('init', function() {
+ window.onbeforeunload = function() {
+ // If editor is dirty AND not inside a visible modal → warn
+ const inVisibleModal = editor.getContainer()?.closest('.modal.show');
+ if (!inVisibleModal && editor.isDirty()) {
+ return "You have unsaved changes. Are you sure you want to leave?";
+ }
+ };
- if (selectedText) {
- // Replace the selected text with [REDACTED] in bold red
- var newContent = '[REDACTED]';
+ // When the modal closes, mark editor clean
+ const modal = editor.getContainer()?.closest('.modal');
+ if (modal) {
+ modal.addEventListener('hidden.bs.modal', () => {
+ editor.undoManager.clear();
+ editor.setDirty(false);
+ });
+ }
+ });
+
+ var rewordButtonApi;
+
+ editor.ui.registry.addButton('reword', {
+ icon: 'ai',
+ tooltip: 'Reword Text',
+ onAction: function() {
+ var content = editor.getContent();
+ rewordButtonApi.setEnabled(false);
+ editor.setProgressState(true);
+
+ fetch('post.php?ai_reword', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ text: content }),
+ })
+ .then(response => {
+ if (!response.ok) throw new Error('Network response was not ok');
+ return response.json();
+ })
+ .then(data => {
+ editor.undoManager.transact(function() {
+ editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
+ });
+ editor.setProgressState(false);
+ rewordButtonApi.setEnabled(true);
+ editor.notificationManager.open({
+ text: 'Text reworded successfully!',
+ type: 'success',
+ timeout: 3000
+ });
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ editor.setProgressState(false);
+ rewordButtonApi.setEnabled(true);
+ editor.notificationManager.open({
+ text: 'An error occurred while rewording the text.',
+ type: 'error',
+ timeout: 5000
+ });
+ });
+ },
+ onSetup: function(buttonApi) {
+ rewordButtonApi = buttonApi;
+ return function() {};
+ }
+ });
+
+ editor.ui.registry.addButton('redactButton', {
+ icon: 'permanent-pen',
+ tooltip: 'Redact Text',
+ onAction: function() {
+ var selectedText = editor.selection.getContent({ format: 'text' });
+ if (selectedText) {
+ var newContent = '[REDACTED]';
+ editor.selection.setContent(newContent);
+ } else {
+ alert('Please select a word to redact');
+ }
+ }
+ });
+ }
+ });
+
+ // Initialize TinyMCE Redact-only
+ tinymce.init({
+ selector: '.tinymceRedact',
+ browser_spellcheck: true,
+ contextmenu: false,
+ resize: true,
+ min_height: 300,
+ max_height: 600,
+ promotion: false,
+ branding: false,
+ menubar: false,
+ statusbar: false,
+ toolbar: 'redactButton',
+ mobile: {
+ menubar: false,
+ plugins: 'autosave lists autolink',
+ toolbar: 'redactButton'
+ },
+ convert_urls: false,
+ plugins: 'link image lists table code fullscreen autoresize',
+ license_key: 'gpl',
+ setup: function(editor) {
- // Replace selected content with the new content
- editor.selection.setContent(newContent);
- } else {
- alert('Please select a word to redact');
- }
+ editor.on('init', function() {
+ window.onbeforeunload = function() {
+ // If editor is dirty AND not inside a visible modal → warn
+ const inVisibleModal = editor.getContainer()?.closest('.modal.show');
+ if (!inVisibleModal && editor.isDirty()) {
+ return "You have unsaved changes. Are you sure you want to leave?";
+ }
+ };
+
+ // When the modal closes, mark editor clean
+ const modal = editor.getContainer()?.closest('.modal');
+ if (modal) {
+ modal.addEventListener('hidden.bs.modal', () => {
+ editor.undoManager.clear();
+ editor.setDirty(false);
+ });
+ }
+ });
+
+ editor.on('keydown', function(e) {
+ e.preventDefault();
+ });
+
+ editor.ui.registry.addButton('redactButton', {
+ icon: 'permanent-pen',
+ tooltip: 'Redact',
+ text: 'REDACT',
+ onAction: function() {
+ var selectedText = editor.selection.getContent({ format: 'text' });
+ if (selectedText) {
+ var newContent = '[REDACTED]';
+ editor.selection.setContent(newContent);
+ } else {
+ alert('Please select a word to redact');
+ }
+ }
+ });
}
- });
+ });
+
+ // DateTime
+ $('.datetimepicker').datetimepicker();
+
+ // Data Input Mask
+ $('[data-mask]').inputmask();
+
+ // ClipboardJS fix for Bootstrap modals
+ $.fn.modal.Constructor.prototype._enforceFocus = function() {};
+
+ // Tooltip
+ $('button').tooltip({
+ trigger: 'click',
+ placement: 'bottom'
+ });
+
+ function setTooltip(btn, message) {
+ $(btn).tooltip('hide')
+ .attr('data-original-title', message)
+ .tooltip('show');
}
- });
- tinymce.init({
- selector: '.tinymceRedact', // Your selector
- browser_spellcheck: true,
- contextmenu: false,
- resize: true,
- min_height: 300,
- max_height: 600,
- promotion: false,
- branding: false,
- menubar: false,
- statusbar: false,
- toolbar: 'redactButton', // Only the redact button in the toolbar
- mobile: {
- menubar: false,
- plugins: 'autosave lists autolink',
- toolbar: 'redactButton' // Only the redact button on mobile
- },
- convert_urls: false,
- plugins: 'link image lists table code fullscreen autoresize',
- license_key: 'gpl',
- setup: function(editor) {
- // Disable all text input and backspace/delete actions
- editor.on('keydown', function(e) {
- // Prevent all key events (including backspace and delete)
- e.preventDefault();
- });
-
- // Add custom toolbar button with Font Awesome icon and label
- editor.ui.registry.addButton('redactButton', {
- icon: 'permanent-pen',
- tooltip: 'Redact', // Tooltip text for the button
- text: 'REDACT', // Add the text next to the icon
- onAction: function() {
- var selectedText = editor.selection.getContent({ format: 'text' });
-
- if (selectedText) {
- // Replace the selected text with [REDACTED] in bold red
- var newContent = '[REDACTED]';
-
- // Replace selected content with the new content
- editor.selection.setContent(newContent);
- } else {
- alert('Please select a word to redact');
- }
- }
- });
+ function hideTooltip(btn) {
+ setTimeout(function() {
+ $(btn).tooltip('hide');
+ }, 1000);
}
- });
+ // Clipboard
+ var clipboard = new ClipboardJS('.clipboardjs');
+ clipboard.on('success', function(e) {
+ setTooltip(e.trigger, 'Copied!');
+ hideTooltip(e.trigger);
+ });
- // DateTime
- $('.datetimepicker').datetimepicker({
- });
+ clipboard.on('error', function(e) {
+ setTooltip(e.trigger, 'Failed!');
+ hideTooltip(e.trigger);
+ });
- // Data Input Mask
- $('[data-mask]').inputmask();
+ // Enable Popovers
+ $(function() {
+ $('[data-toggle="popover"]').popover();
+ });
- // ClipboardJS
-
- //Fix to allow Clipboard Copying within Bootstrap Modals
- //For use in Bootstrap Modals or with any other library that changes the focus you'll want to set the focused element as the container value.
- $.fn.modal.Constructor.prototype._enforceFocus = function() {};
-
- // Tooltip
-
- $('button').tooltip({
- trigger: 'click',
- placement: 'bottom'
- });
-
- function setTooltip(btn, message) {
- $(btn).tooltip('hide')
- .attr('data-original-title', message)
- .tooltip('show');
- }
-
- function hideTooltip(btn) {
- setTimeout(function() {
- $(btn).tooltip('hide');
- }, 1000);
- }
-
- // Clipboard
-
- var clipboard = new ClipboardJS('.clipboardjs');
-
- clipboard.on('success', function(e) {
- setTooltip(e.trigger, 'Copied!');
- hideTooltip(e.trigger);
- });
-
- clipboard.on('error', function(e) {
- setTooltip(e.trigger, 'Failed!');
- hideTooltip(e.trigger);
- });
-
- // Enable Popovers
- $(function () {
- $('[data-toggle="popover"]').popover()
- });
-
- // Data Tables
- new DataTable('.dataTables');
-
-});
\ No newline at end of file
+ // Data Tables
+ new DataTable('.dataTables');
+});