diff options
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el')
-rw-r--r-- | configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el new file mode 100644 index 000000000000..e62f2a46ec13 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el @@ -0,0 +1,343 @@ +;;; slack-dialog.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 + +;; Author: <yuya373@yuya373> +;; Keywords: + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-selectable) + +(defclass slack-dialog () + ((title :initarg :title :type string) + (callback-id :initarg :callback_id :type string) + (elements :initarg :elements :type list) + (state :initarg :state :type (or null string) :initform nil) + (submit-label :initarg :submit_label :type string :initform "Submit") + (notify-on-cancel :initarg :notify_on_cancel :type boolean :initform nil) + (error-message :initarg :error-message :type (or null string) :initform nil) + )) + +(defclass slack-dialog-element () + ((name :initarg :name :type string) + (label :initarg :label :type string) + (type :initarg :type :type string) + (optional :initarg :optional :type boolean :initform nil) + (placeholder :initarg :placeholder :type (or null string) :initform nil) + (value :initarg :value :type (or null string) :initform nil) + (errors :initarg :errors :type list :initform '()))) + +(defclass slack-dialog-element-error () + ((name :initarg :name :type string) + (error-message :initarg :error-message :type string))) + +(defclass slack-dialog-text-element (slack-dialog-element) + ((max-length :initarg :max_length :type number :initform 150) + (min-length :initarg :min_length :type number :initform 0) + (hint :initarg :hint :type (or null string) :initform nil) + ;; one of email, number, tel or url + (subtype :initarg :subtype :type (or null string) :initform nil))) + +(defclass slack-dialog-textarea-element (slack-dialog-text-element) + ((max-length :initarg :max_length :type number :initform 3000))) + +(defclass slack-dialog-select-element (slack-dialog-element slack-selectable) + ((min-query-length :initarg :min_query_length :type (or null number) :initform nil))) + +(defclass slack-dialog-select-option (slack-selectable-option) + ((label :initarg :label :type string))) + +(defclass slack-dialog-select-option-group (slack-selectable-option-group) + ((label :initarg :label :type string))) + +(defmethod slack-dialog-element-value ((this slack-dialog-element)) + (or (oref this value) "")) + +(defmethod slack-dialog-element-value ((this slack-dialog-select-element)) + (with-slots (data-source selected-options) this + (or (cond + ((string= data-source "external") + (and selected-options + (car selected-options) + (oref (car selected-options) value))) + (t (oref this value))) + ""))) + +(defmethod slack-equalp ((this slack-dialog-element) other) + (string= (oref this name) + (oref other name))) + +(defmethod slack-dialog-selected-option ((this slack-dialog-select-element)) + (with-slots (data-source value options selected-options) this + (if (string= data-source "static") + (cl-find-if #'(lambda (op) (string= (oref op value) + value)) + options) + (and selected-options (car selected-options))))) + +(defmethod slack-selectable-text ((this slack-dialog-select-option)) + (oref this label)) + +(defmethod slack-selectable-text ((this slack-dialog-select-option-group)) + (oref this label)) + +(defmethod slack-selectable-prompt ((this slack-dialog-select-element)) + (format "%s :" + (oref this label))) + +(defun slack-dialog-text-element-create (payload) + (apply #'make-instance 'slack-dialog-text-element + (slack-collect-slots 'slack-dialog-text-element payload))) + +(defun slack-dialog-textarea-element-create (payload) + (apply #'make-instance 'slack-dialog-textarea-element + (slack-collect-slots 'slack-dialog-textarea-element payload))) + +(defun slack-dialog-select-element-create (payload) + (let ((options + (mapcar #'(lambda (e) + (apply #'make-instance 'slack-dialog-select-option + (slack-collect-slots 'slack-dialog-select-option + e))) + (plist-get payload :options))) + (option-groups + (mapcar #'(lambda (e) + (apply #'make-instance + 'slack-dialog-select-option-group + (slack-collect-slots 'slack-dialog-select-option-group + e))) + (plist-get payload :option_groups)))) + (setq payload (plist-put payload :options options)) + (setq payload (plist-put payload :option_groups option-groups)) + (apply #'make-instance 'slack-dialog-select-element + (slack-collect-slots 'slack-dialog-select-element + payload)))) + +(defun slack-dialog-element-create (payload) + (let ((type (plist-get payload :type))) + (cond + ((string= type "select") + (slack-dialog-select-element-create payload)) + ((string= type "text") + (slack-dialog-text-element-create payload)) + ((string= type "textarea") + (slack-dialog-textarea-element-create payload)) + (t (error "Unknown dialog element type: %s" type))))) + +(defun slack-dialog-create (payload) + (let ((elements (mapcar #'slack-dialog-element-create + (plist-get payload :elements)))) + (setq payload (plist-put payload :elements elements)) + (apply #'make-instance 'slack-dialog + (slack-collect-slots 'slack-dialog payload)))) + +(defmethod slack-dialog-element-validate ((this slack-dialog-element) value) + (with-slots (optional label) this + (when (and (not optional) + (or (null value) + (< (length value) 1))) + (error "%s must not be empty" label)))) + +(defmethod slack-dialog-element-validate ((_this slack-dialog-select-element) _value) + (call-next-method)) + +(defmethod slack-dialog-element-validate ((this slack-dialog-text-element) value) + (call-next-method) + (with-slots (min-length max-length label) this + (when (< max-length (length value)) + (error "%s must be less than %s" label max-length)) + (when (< (length value) min-length) + (error "%s must be greater than %s" label min-length)))) + +(defmethod slack-dialog-execute ((this slack-dialog-text-element) _dialog-id team) + (with-slots (hint value placeholder label optional) this + (let* ((prompt (format "%s%s%s : " + label + (if hint (format " (%s)" hint) "") + (if optional " (optional)" ""))) + (value (read-from-minibuffer prompt value))) + (slack-dialog-element-validate this value) + value))) + +(defmethod slack-dialog-execute ((this slack-dialog-textarea-element) _dialog-id team) + (call-next-method)) + +(defmethod slack-dialog-select-element-get-suggestions ((this slack-dialog-select-element) + dialog-id team after-success) + (let* ((url "https://slack.com/api/dialog.selectSuggestion") + (min-query-length (oref this min-query-length)) + (prompt (format "Type hints to see options (minimum: %s) : " min-query-length)) + (params (list (cons "dialog_id" dialog-id) + (cons "name" (oref this name)) + (cons "value" (read-from-minibuffer prompt))))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-dialog-select-fetch-suggestion") + (funcall after-success data)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :sync t + :success #'on-success))))) + +(defmethod slack-dialog-execute ((this slack-dialog-select-element) dialog-id team) + (slack-if-let* ((selected (slack-dialog--execute this dialog-id team))) + (cdr selected))) + +(defmethod slack-dialog--execute ((this slack-dialog-select-element) dialog-id team) + (with-slots (data-source) this + (cond + ((string= data-source "external") + (let ((result-option nil)) + (cl-labels + ((log-error (err) + (slack-log (format "Error: %s" err) team :level 'error)) + (select (options) + (slack-if-let* + ((selected (completing-read "Choose an Option..." + (mapcar #'(lambda (option) + (plist-get option :label)) + options) + nil t))) + (cl-find-if #'(lambda (option) (string= selected + (plist-get option :label))) + options))) + (after-success (data) + (slack-request-handle-error + (data "slack-dialog-execute" + #'log-error) + (let ((option-groups (plist-get data :option_groups)) + (options (plist-get data :options))) + (when option-groups + (slack-if-let* ((selected-option-group (select option-groups))) + (setq options (plist-get selected-option-group :options)))) + (when options + (slack-if-let* ((selected (select options))) + (setq result-option selected))))))) + (slack-dialog-select-element-get-suggestions this + dialog-id + team + #'after-success) + (if result-option + (cons (plist-get result-option :label) + (plist-get result-option :value)))))) + ((string= data-source "conversations") + (slack-if-let* ((rooms (append (oref team channels) + (oref team groups) + (oref team ims))) + (room (slack-room-select rooms team))) + (cons (slack-room-name room team) + (oref room id)))) + ((string= data-source "channels") + (slack-if-let* ((channels (oref team channels)) + (channel (slack-room-select channels team))) + (cons (slack-room-name channel team) + (oref channel id)))) + ((string= data-source "users") + (slack-if-let* ((id (plist-get (slack--user-select team) :id))) + (cons (slack-user-name id team) + id))) + ((string= "static" data-source) + (slack-if-let* ((selected (slack-selectable-select-from-static-data-source this))) + (cons (oref selected label) + (oref selected value)))) + (t (error "Unknown element's data-source: %s" data-source)) + ))) + +(defmethod slack-dialog--submit ((_this slack-dialog) + dialog-id team submission + &optional after-success) + (let ((url "https://slack.com/api/dialog.submit") + (params (list (cons "submission" (json-encode-alist submission)) + (cons "dialog_id" dialog-id)))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (when (functionp after-success) + (funcall after-success data)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(defmethod slack-dialog-submit ((this slack-dialog) dialog-id team) + (with-slots (elements) this + (let ((submission (mapcar #'(lambda (element) + (let ((value (slack-dialog-execute element dialog-id team))) + (cons (oref element name) value))) + elements))) + (slack-dialog--submit this dialog-id team submission)))) + +(defun slack-dialog-get (id team) + (let ((url "https://slack.com/api/dialog.get") + (params (list (cons "dialog_id" id)))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-dialog-get") + (slack-if-let* + ((payload (plist-get data :dialog)) + (dialog (slack-dialog-create payload))) + ;; (slack-dialog-submit dialog id team) + (slack-buffer-display + (slack-create-dialog-buffer id + dialog + team)) + )))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(defmethod slack-dialog-notify-cancel ((this slack-dialog) dialog-id team) + (slack-if-let* ((url "https://slack.com/api/dialog.notifyCancel") + (params (list (cons "dialog_id" dialog-id))) + (notify-cancelp (oref this notify-on-cancel))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-dialog-notify-cancel")))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(defmethod slack-dialog-clear-errors ((this slack-dialog)) + (oset this error-message nil) + (dolist (element (oref this elements)) + (oset element errors nil))) + +(provide 'slack-dialog) +;;; slack-dialog.el ends here |