diff --git a/src/api.php b/src/api.php index d803212..3bfac3a 100644 --- a/src/api.php +++ b/src/api.php @@ -20,6 +20,7 @@ require_once(MTTINC. 'api/ListsController.php'); require_once(MTTINC. 'api/TasksController.php'); require_once(MTTINC. 'api/TagsController.php'); require_once(MTTINC. 'api/AuthController.php'); +require_once(MTTINC. 'api/ExtSettingsController.php'); $endpoints = array( '/lists' => [ @@ -53,6 +54,10 @@ $endpoints = array( '/(login|logout|session)' => [ 'POST' => [ AuthController::class , 'postAction' ], ], + '/ext-settings/(.+)' => [ + 'GET' => [ ExtSettingsController::class , 'get' ], + 'PUT' => [ ExtSettingsController::class , 'put' ], + ] ); $req = new ApiRequest(); diff --git a/src/content/mytinytodo.js b/src/content/mytinytodo.js index ded7a0a..914a989 100644 --- a/src/content/mytinytodo.js +++ b/src/content/mytinytodo.js @@ -598,6 +598,9 @@ var mytinytodo = window.mytinytodo = _mtt = { else if (settingsPage == 'ext-activate' || settingsPage == 'ext-deactivate') { activateExtension(settingsPage == 'ext-activate' ? true : false, this.dataset.ext); } + else if (settingsPage == 'ext-index') { + showExtensionSettings(this.dataset.ext); + } return false; }); @@ -606,6 +609,11 @@ var mytinytodo = window.mytinytodo = _mtt = { return false; }); + $("#page_ajax").on('submit', '#ext_settings_form', function() { + saveExtensionSettings(this); + return false; + }); + $(document).on('click', '.mtt-back-button', function() { _mtt.pageBack(true); this.blur(); @@ -2518,16 +2526,10 @@ function flashInfo(str, details) $("#msg").addClass('mtt-info').effect("highlight", {color:_mtt.theme.msgFlashColor}, 700); } -function toggleMsgDetails() -{ - var el = $("#msg>.msg-details"); - if(!el) return; - if(el.css('display') == 'none') el.show(); - else el.hide() -} - function hideAlert() { + $("#msg>.msg-text").text(''); + $("#msg>.msg-details").text(''); $("#msg").hide().removeClass('mtt-error mtt-info').find('.msg-details').hide(); } @@ -2654,6 +2656,40 @@ function activateExtension(activate, ext) }, 'json'); } +function showExtensionSettings(ext, callback) +{ + if (_mtt.pages.current && _mtt.pages.current.page == 'ajax' && _mtt.pages.current.pageClass == 'settings') { + $('#page_ajax').load(_mtt.apiUrl + 'ext-settings/' + ext, null, function() { + if (callback !== undefined) callback(); + }); + } + +} + +function saveExtensionSettings(frm) +{ + if (!frm) return false; + var ext = frm.dataset.ext; + var params = {}; + $(frm).find("input:hidden,input:text,input:password,input:checked,select").filter(":enabled").each(function() { params[this.name || '__'] = this.value; }); + $.ajax({ + url: _mtt.apiUrl + 'ext-settings/' + ext, + method: 'PUT', + contentType : 'application/json', + data: JSON.stringify(params), + dataType: 'json', + success: function(json) { + if (json.saved) { + if (json.msg) showExtensionSettings(ext, function(){ + flashInfo(json.msg); + }); + else showExtensionSettings(ext); + + } + } + }); +} + /* * Dialogs */ diff --git a/src/content/theme/style.css b/src/content/theme/style.css index 306ec45..8d2982a 100644 --- a/src/content/theme/style.css +++ b/src/content/theme/style.css @@ -938,7 +938,9 @@ li.mtt-item-hidden { display:none; } border-color: var(--color-border-focus); box-shadow:0 0 0 2px var(--color-border-focus-shadow); } - +.mtt-settings-table a { + color: var(--color-text-default); +} #modal { position: absolute; diff --git a/src/includes/api/ExtSettingsController.php b/src/includes/api/ExtSettingsController.php new file mode 100644 index 0000000..64b6d7d --- /dev/null +++ b/src/includes/api/ExtSettingsController.php @@ -0,0 +1,78 @@ +extInstance($ext); + if (!$instance) { + return; + } + + $data = $instance->settingsPage(); + + $title = htmlspecialchars($instance::title); + $escapedExt = htmlspecialchars($ext); + $e = function($s) { return __($s, true); }; + $data = +<< $title + +
+
+ $data +
+ + +
+
+
+EOD; + + $this->response->htmlContent($data); + } + + /** + * Save extension settings + * @return void + * @throws Exception + */ + function put($ext) + { + /** @var MTTExtension|MTTExtensionSettingsInterface $instance */ + $instance = $this->extInstance($ext); + if (!$instance) { + return; + } + //$userError = ''; + $saved = $instance->saveSettings($this->req->jsonBody ?? [], $userError); + $a = [ 'saved' => (int)$saved ]; + if ($userError) { + $a['msg'] = $userError; + } + $this->response->data = $a; + } + + private function extInstance($ext): ?MTTExtensionSettingsInterface + { + $instance = MTTExtensionLoader::extensionInstance($ext); + if (!$instance) { + $this->response->data = [ 'msg' => "Unknown extension" ]; + $this->response->code = 404; + return null; + } + if (! ($instance instanceof MTTExtensionSettingsInterface) ) { + $this->response->data = [ 'msg' => "No settings page for extension" ]; + $this->response->code = 500; + return null; + } + return $instance; + } + +} diff --git a/src/includes/classes.php b/src/includes/classes.php index 7297d29..6b838a3 100644 --- a/src/includes/classes.php +++ b/src/includes/classes.php @@ -79,6 +79,11 @@ abstract class MTTExtension } +interface MTTExtensionSettingsInterface +{ + function settingsPage(): string; + function saveSettings(array $array, ?string &$userError): bool; +} class MTTExtensionLoader diff --git a/src/settings.php b/src/settings.php index f303ac9..d46eae8 100644 --- a/src/settings.php +++ b/src/settings.php @@ -189,6 +189,10 @@ function listExtensions() $out = "$ext "; if (in_array($ext, $activatedExts)) { $out .= "". __('set_deactivate', true). ''; + $instance = MTTExtensionLoader::extensionInstance($ext); + if ($instance instanceof MTTExtensionSettingsInterface) { + $out .= " ". __('a_settings', true). ""; + } } else { $out .= "". __('set_activate', true). '';