diff options
| -rw-r--r-- | lisp/service/menu-service.lisp | 1 | ||||
| -rw-r--r-- | lisp/service/resume-service.lisp | 149 | ||||
| -rw-r--r-- | lisp/sql/resume-pkg.lisp | 14 | ||||
| -rw-r--r-- | lisp/webapps/resume/clojurescript/resume/src/core.cljs | 209 | ||||
| -rw-r--r-- | lisp/webapps/resume/site.lisp | 28 | ||||
| -rw-r--r-- | sql/functions/resume.insert_language.sql | 45 |
6 files changed, 425 insertions, 21 deletions
diff --git a/lisp/service/menu-service.lisp b/lisp/service/menu-service.lisp index 00dff60..aaff72b 100644 --- a/lisp/service/menu-service.lisp +++ b/lisp/service/menu-service.lisp @@ -7,6 +7,7 @@ (:id "a_menu_resumes" :label "Resumes" :handler "/resumes" :permissions "resume-view") (:id "a_menu_resumes_contactinfo" :label "Contact Info" :handler "/resumes/contactinfo" :permissions "resume-view") (:id "a_menu_resumes_education" :label "Education" :handler "/resumes/education" :permissions "resume-view") + (:id "a_menu_resumes_language" :label "Language" :handler "/resumes/language" :permissions "resume-view") (:id "a_menu_contact_us" :label "Contact Me" :handler "/contact-us" :permissions "_Public") (:id "a_menu_messages" :label "Messages" :handler "/messages" :permissions "messages-view") (:id "a_menu_users" :label "Users" :handler "/users" :permissions "users-view"))) diff --git a/lisp/service/resume-service.lisp b/lisp/service/resume-service.lisp index 8994595..a1987d9 100644 --- a/lisp/service/resume-service.lisp +++ b/lisp/service/resume-service.lisp @@ -163,7 +163,6 @@ (with-auth (instance contactinfo/add-service "resume-modify") (with-resume-database (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) (states (get-records resume-pkg (make-instance 'states) "abbr asc")) (visastatuses (get-records resume-pkg (make-instance 'visastatus) "visastatus asc"))) (setf (title instance) "Contact Info - Add") @@ -287,21 +286,17 @@ (defun education-add-json () (with-auth (instance education/add-service "resume-modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user))) - (setf (title instance) "Education - Add") - (setf (form instance) (make-form "education-add-form" - nil - t - `((:name "school" :label "School" :field-type "text" :required "required") - (:name "major" :label "Major" :field-type "text" :required "required") - (:name "minor" :label "Minor" :field-type "text") - (:name "degree" :label "Degree" :field-type "text" :required "required") - (:name "progress" :label "Progress" :field-type "text" :required "required") - (:name "start_date" :label "Start Date" :field-type "text" :placeholder "MM/YYYY" :required "required") - (:name "end_date" :label "End Date" :field-type "text" :placeholder "MM/YYYY" :required "required") - (:label "Add Education" :field-type "button" :onclick "on_education_add_submit_clicked()")))))))) + (setf (form instance) (make-form "education-add-form" + nil + t + `((:name "school" :label "School" :field-type "text" :required "required") + (:name "major" :label "Major" :field-type "text" :required "required") + (:name "minor" :label "Minor" :field-type "text") + (:name "degree" :label "Degree" :field-type "text" :required "required") + (:name "progress" :label "Progress" :field-type "text" :required "required") + (:name "start_date" :label "Start Date" :field-type "text" :required "required") + (:name "end_date" :label "End Date" :field-type "text" :required "required") + (:label "Add Education" :field-type "button" :onclick "on_education_add_submit_clicked()")))))) (defun education-add-submit-json (school major minor degree progress start_date end_date) (declare (special school major minor degree progress start_date end_date)) @@ -341,8 +336,8 @@ (:name "minor" :label "Minor" :field-type "text" :value ,(minor education)) (:name "degree" :label "Degree" :field-type "text" :value ,(degree education) :required "required") (:name "progress" :label "Progress" :field-type "text" :value ,(progress education) :required "required") - (:name "start_date" :label "Start Date" :field-type "datetime-local" :value ,(start_date education) :required "required") - (:name "end_date" :label "End Date" :field-type "datetime-local" :value ,(end_date education) :required "required") + (:name "start_date" :label "Start Date" :field-type "text" :value ,(start_date education) :required "required") + (:name "end_date" :label "End Date" :field-type "text" :value ,(end_date education) :required "required") (:label "Modify Education" :field-type "button" :onclick "on_education_modify_submit_clicked()")))) (setf (session-value :errormsg) "Error: could not modify Education. Not found.")))))) @@ -382,12 +377,126 @@ ;; language +(defun language-json () + (with-auth (instance resumes-service "resume-view") + (setf (title instance) "Languages"))) + +(defclass language/view-service (resumes-service language) + ((languages :initarg :languages + :initform nil + :accessor languages) + (location-p :initform nil)) + (:documentation "")) + +(defun language-view-json () + (with-auth (instance language/view-service "resume-view") + (with-resume-database + (let ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user))) + (setf (languages instance) (get-all-languages resume-pkg user)))) + (sanitize-rest-json instance) + (loop for language in (languages instance) + do (sanitize-json language)))) +(defclass language/add-service (language/view-service) + ((form :initarg :form + :initform nil + :accessor form)) + (:documentation "")) -(defun language-options (level) +(defun language-options () (mapcar (lambda (level) - `(:label level :value level)) + `(:label ,level :value ,level)) '("A1" "A2" "B1" "B2" "C1" "C2"))) +(defun language-add-json () + (with-auth (instance language/add-service "resume-modify") + (setf (title instance) "Language - Add") + (setf (form instance) (make-form "language-add-form" + nil + t + `((:name "name" :label "Name" :field-type "text" :required "required") + (:name "understanding_listening" :label "Understanding Listening" :field-type "select" :options ,(language-options) :required "required") + (:name "understanding_reading" :label "Understanding Reading" :field-type "select" :options ,(language-options) :required "required") + (:name "speaking_interaction" :label "Speaking Interaction" :field-type "select" :options ,(language-options) :required "required") + (:name "speaking_production" :label "Speaking Production" :field-type "select" :options ,(language-options) :required "required") + (:name "writing" :label "Writing" :field-type "select" :options ,(language-options) :required "required") + (:label "Add Language" :field-type "button" :onclick "on_language_add_submit_clicked()")))))) + +(defun language-add-submit-json (name understanding_listening understanding_reading speaking_interaction speaking_production writing) + (declare (special name understanding_listening understanding_reading speaking_interaction speaking_production writing)) + (with-auth (instance language/add-service "resume-modify") + (with-resume-database + (handler-case + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (language (make-instance 'language :user_id (id user)))) + (loop for param in (remove-if (lambda (x) + (intersection `(,x) '(id))) + (sb-introspect:function-lambda-list #'language-add-submit-json)) + do (setf (slot-value language param) (symbol-value param))) + (insert-language resume-pkg language) + (setf (session-value :message) (format nil "Language \"~a\" created successfully." name))) + (error (e) + (setf (session-value :errormsg) (format nil "Error creating Language \"~a\". ~a" name e))))))) + +(defclass language/modify-service (language/add-service) + () + (:documentation "")) + +(defun language-modify-json (id) + (with-auth (instance language/modify-service "resume-modify") + (setf (title instance) "Language - Modify") + (with-resume-database + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (language (get-record resume-pkg (make-instance 'language :id id :user_id (id user))))) + (if language + (setf (form instance) (make-form "language-modify-form" + nil + t + `((:name "id" :field-type "hidden" :value ,(id language) :required "required") + (:name "name" :label "Name" :field-type "text" :value ,(name language) :required "required") + (:name "understanding_listening" :label "Understanding Listening" :field-type "select" :options ,(language-options) :value ,(understanding_listening language) :required "required") + (:name "understanding_reading" :label "Understanding Reading" :field-type "select" :options ,(language-options) :value ,(understanding_reading language) :required "required") + (:name "speaking_interaction" :label "Speaking Interaction" :field-type "select" :options ,(language-options) :value ,(speaking_interaction language) :required "required") + (:name "speaking_production" :label "Speaking Production" :field-type "select" :options ,(language-options) :value ,(speaking_production language) :required "required") + (:name "writing" :label "Writing" :field-type "text" :value ,(writing language) :required "required") + + (:label "Modify Language" :field-type "button" :onclick "on_language_modify_submit_clicked()")))) + (setf (session-value :errormsg) "Error: could not modify Language. Not found.")))))) + +(defun language-modify-submit-json (id name understanding_listening understanding_reading speaking_interaction speaking_production writing) + (declare (special id name understanding_listening understanding_reading speaking_interaction speaking_production writing)) + (with-auth (instance language/modify-service "resume-modify") + (setf (title instance) "Language - Modify") + (with-resume-database + (handler-case + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (language (get-record resume-pkg (make-instance 'language :id id :user_id (id user))))) + (loop for param in (remove-if (lambda (x) + (intersection `(,x) '(id))) + (sb-introspect:function-lambda-list #'language-modify-submit-json)) + do (setf (slot-value language param) (symbol-value param))) + (update-record resume-pkg language) + (setf (session-value :message) (format nil "Language \"~a\" modified successfully." name))) + (error (e) + (setf (session-value :errormsg) (format nil "Error modifying Language \"~a\". ~a" name e))))))) +(defclass language/delete-service (language/add-service) + () + (:documentation "")) + +(defun language-delete-json (id) + (with-auth (instance language/delete-service "resume-modify") + (with-resume-database + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (language (get-record resume-pkg (make-instance 'language :id id :user_id (id user))))) + (if language + (progn + (delete-record resume-pkg language) + (setf (session-value :message) (format nil "Language \"~a\" deleted successfully." (name language)))) + (setf (session-value :errormsg) "Error: could not delete Language: not found.")))))) diff --git a/lisp/sql/resume-pkg.lisp b/lisp/sql/resume-pkg.lisp index a43a07e..c45a6e1 100644 --- a/lisp/sql/resume-pkg.lisp +++ b/lisp/sql/resume-pkg.lisp @@ -65,7 +65,21 @@ ;; language +(defmethod get-all-languages ((resume-pkg resume-pkg) (user user)) + (let ((language (make-instance 'language :user_id (id user)))) + (get-records resume-pkg language "name asc"))) +(defmethod insert-language ((resume-pkg resume-pkg) (language language)) + (setf (*table language) (format nil + "resume.insert_language(~a, '~a', '~a', '~a', '~a', '~a', '~a')" + (user_id language) + (name language) + (understanding_listening language) + (understanding_reading language) + (speaking_interaction language) + (speaking_production language) + (writing language))) + (caar (call-pg-function resume-pkg language))) ;; job diff --git a/lisp/webapps/resume/clojurescript/resume/src/core.cljs b/lisp/webapps/resume/clojurescript/resume/src/core.cljs index d894e7f..532a52b 100644 --- a/lisp/webapps/resume/clojurescript/resume/src/core.cljs +++ b/lisp/webapps/resume/clojurescript/resume/src/core.cljs @@ -195,6 +195,29 @@ (declare on-education-delete-clicked) (declare handler-education-delete) (declare render-education-delete) +(declare template-language) +(declare handler-language) +(declare render-language) +(declare template-language-view) +(declare handler-language-view) +(declare render-language-view) +(declare on-language-add-clicked) +(declare template-language-add) +(declare handler-language-add) +(declare render-language-add) +(declare on-language-add-submit-clicked) +(declare handler-language-add-submit) +(declare render-language-add-submit) +(declare on-language-modify-clicked) +(declare template-language-modify) +(declare handler-language-modify) +(declare render-language-modify) +(declare on-language-modify-submit-clicked) +(declare handler-language-modify-submit) +(declare render-language-modify-submit) +(declare on-language-delete-clicked) +(declare handler-language-delete) +(declare render-language-delete) (declare on-menu-clicked) (declare handler-location) (declare goto-location) @@ -1606,6 +1629,189 @@ {:format :raw :handler handler-education-delete})) +;; language + +(hiccups/defhtml template-language [jsonobj] + [:h3 {:style "text-align: center"} (get jsonobj "title")] + [:div {:id "content"}] + [:div {:id "modify" + :class "modal fade" + :role "dialog" + :tabindex "-1"} + [:div {:class "modal-dialog modal-lg"} + [:div {:class "modal-content"} + [:div {:class "modal-header"} + [:h5 [:span {:id "modify-title"}]] + [:button {:type "button" + :class "close" + :data-dismiss "modal"} + "×"]] + [:div {:id "modify-body" + :class "modal-body" + :style "height: 450px;"}] + [:div {:class "modal-footer"} + [:button {:type "submit" + :class "btn btn-danger btn-default" + :data-dismiss "modal"} + [:span {:class "glyphicon glyphicon-remove"}] + "Cancel"]]]]]) + +(defn handler-language [response] + (let [jsonobj (js->clj (js/JSON.parse response))] + (notifications jsonobj) + (dommy/set-html! (dommy/sel1 :#body) (template-language jsonobj)) + (render-language-view))) + +(defn render-language [] + (GET "/resumes/language" {:handler handler-language})) + +;; language-view + +(hiccups/defhtml template-language-view [jsonobj] + [:div {:style "text-align: right"} + [:img {:src "/static/images/add.png" + :style "cursor:pointer; cursor:hand" + :onclick (str (namespace ::x) ".on_language_add_clicked()")}]] + [:table {:class "table table-striped table-hover table-sm"} + [:thead + [:tr + [:th {:scope "col"} "Name"] + [:th {:scope "col"} "Understanding Listening"] + [:th {:scope "col"} "Understanding Reading"] + [:th {:scope "col"} "Speaking Interaction"] + [:th {:scope "col"} "Speaking Production"] + [:th {:scope "col"} "Writing"] + [:th {:scope "col"} "Mod"] + [:th {:scope "col"} "Del"]]] + [:tbody + (for [language (get jsonobj "languages")] + [:tr + [:td (get language "name")] + [:td (get language "understanding_listening")] + [:td (get language "understanding_reading")] + [:td (get language "speaking_interaction")] + [:td (get language "speaking_production")] + [:td (get language "writing")] + [:td {:width "30"} + [:img {:src "/static/images/modify.png" + :onclick (str (namespace ::x) ".on_language_modify_clicked(" (get language "id") ")")}]] + [:td {:width "30"} + [:img {:src "/static/images/delete.png" + :onclick (str (namespace ::x) ".on_language_delete_clicked(" (get language "id") ", '" (get language "name") "')")}]]])]]) + +(defn handler-language-view [response] + (let [jsonobj (js->clj (js/JSON.parse response))] + (dommy/set-html! (dommy/sel1 :#content) (template-language-view jsonobj)))) + +(defn render-language-view [] + (GET "/resumes/language/view" {:handler handler-language-view})) + +;; language-add + +(defn on-language-add-clicked [] + (render-language-add)) + +(hiccups/defhtml template-language-add [jsonobj] + (ck-form/template-generic-form (get jsonobj "form") (namespace ::x))) + +(defn handler-language-add [response] + (let [jsonobj (js->clj (js/JSON.parse response))] + (auth-notifications jsonobj) + (dommy/set-html! (dommy/sel1 :#modify-title) (get jsonobj "title")) + (dommy/set-html! (dommy/sel1 :#modify-body) (template-language-add jsonobj)) + (.modal (jquery "#modify")))) + +(defn render-language-add [] + (POST "/resumes/language/add" {:handler handler-language-add})) + +;; language-add-submit + +(defn on-language-add-submit-clicked [] + (when (-> (jquery "#language-add-form") + (.get "0") + (.checkValidity)) + (.modal (jquery "#modify") "hide") + (render-language-add-submit))) + +(defn handler-language-add-submit [response] + (let [jsonobj (js->clj (js/JSON.parse response))] + (auth-notifications jsonobj) + (on-menu-clicked "/resumes/language"))) + +(defn render-language-add-submit [] + (POST "/resumes/language/add/submit" + {:format :raw + :params {:name (dommy/value (dommy/sel1 :#name)) + :understanding_listening (dommy/value (dommy/sel1 :#understanding_listening)) + :understanding_reading (dommy/value (dommy/sel1 :#understanding_reading)) + :speaking_interaction (dommy/value (dommy/sel1 :#speaking_interaction)) + :speaking_production (dommy/value (dommy/sel1 :#speaking_production)) + :writing (dommy/value (dommy/sel1 :#writing))} + :handler handler-language-add-submit})) + +;; language-modify + +(defn on-language-modify-clicked [id] + (render-language-modify id)) + +(hiccups/defhtml template-language-modify [jsonobj] + (ck-form/template-generic-form (get jsonobj "form") (namespace ::x))) + +(defn handler-language-modify [response] + (let [jsonobj (js->clj (js/JSON.parse response))] + (auth-notifications jsonobj) + (dommy/set-html! (dommy/sel1 :#modify-title) (get jsonobj "title")) + (dommy/set-html! (dommy/sel1 :#modify-body) (template-language-modify jsonobj)) + (.modal (jquery "#modify")))) + +(defn render-language-modify [id] + (POST "/resumes/language/modify" + {:format :raw + :params {:id id} + :handler handler-language-modify})) + +;; language-modify-submit + +(defn on-language-modify-submit-clicked [] + (when (-> (jquery "#language-modify-form") + (.get "0") + (.checkValidity)) + (.modal (jquery "#modify") "hide") + (render-language-modify-submit))) + +(defn handler-language-modify-submit [response] + (let [jsonobj (js->clj (js/JSON.parse response))] + (auth-notifications jsonobj) + (on-menu-clicked "/resumes/language"))) + +(defn render-language-modify-submit [] + (POST "/resumes/language/modify/submit" + {:format :raw + :params {:id (dommy/value (dommy/sel1 :#id)) + :name (dommy/value (dommy/sel1 :#name)) + :understanding_listening (dommy/value (dommy/sel1 :#understanding_listening)) + :understanding_reading (dommy/value (dommy/sel1 :#understanding_reading)) + :speaking_interaction (dommy/value (dommy/sel1 :#speaking_interaction)) + :speaking_production (dommy/value (dommy/sel1 :#speaking_production)) + :writing (dommy/value (dommy/sel1 :#writing))} + :handler handler-language-modify-submit})) + +;; language-delete + +(defn on-language-delete-clicked [id name] + (when (js/confirm (str "Are you sure you want to delete " name "? This action cannot be undone.")) + (render-language-delete id))) + +(defn handler-language-delete [response] + (let [jsonobj (js->clj (js/JSON.parse response))] + (auth-notifications jsonobj) + (on-menu-clicked "/resumes/language"))) + +(defn render-language-delete [id] + (DELETE (str "/resumes/language/delete/" id) + {:format :raw + :handler handler-language-delete})) + ;; location (defn on-menu-clicked [handler] @@ -1621,7 +1827,8 @@ (= handler "/users") (render-users) (= handler "/resumes") (render-resumes) (= handler "/resumes/contactinfo") (render-contactinfo) - (= handler "/resumes/education") (render-education))) + (= handler "/resumes/education") (render-education) + (= handler "/resumes/language") (render-language))) (defn handler-location [response] (let [jsonobj (js->clj (js/JSON.parse response))] diff --git a/lisp/webapps/resume/site.lisp b/lisp/webapps/resume/site.lisp index d8c1fb5..584c0b7 100644 --- a/lisp/webapps/resume/site.lisp +++ b/lisp/webapps/resume/site.lisp @@ -194,6 +194,27 @@ (defmacro .education-delete () `(education-delete-json id)) +(defmacro .language () + `(language-json)) + +(defmacro .language-view () + `(language-view-json)) + +(defmacro .language-add () + `(language-add-json)) + +(defmacro .language-add-submit () + `(language-add-submit-json name understanding_listening understanding_reading speaking_interaction speaking_production writing)) + +(defmacro .language-modify () + `(language-modify-json id)) + +(defmacro .language-modify-submit () + `(language-modify-submit-json id name understanding_listening understanding_reading speaking_interaction speaking_production writing)) + +(defmacro .language-delete () + `(language-delete-json id)) + (define-endpoint ("/" :method :get) () .base) (define-endpoint ("/location" :method :post) (&post (location :parameter-type 'string)) .location) (define-endpoint ("/home" :method :get) () .home-get) @@ -252,3 +273,10 @@ (define-endpoint ("/resumes/education/modify" :method :post) (&post (id :parameter-type 'integer)) .education-modify) (define-endpoint ("/resumes/education/modify/submit" :method :post) (&post (id :parameter-type 'integer) (school :parameter-type 'string) (major :parameter-type 'string) (minor :parameter-type 'string) (degree :parameter-type 'string) (progress :parameter-type 'string) (start_date :parameter-type 'string) (end_date :parameter-type 'string)) .education-modify-submit) (define-endpoint ("/resumes/education/delete/:id" :method :delete) (&path (id 'integer)) .education-delete) +(define-endpoint ("/resumes/language" :method :get) () .language) +(define-endpoint ("/resumes/language/view" :method :get) () .language-view) +(define-endpoint ("/resumes/language/add" :method :post) () .language-add) +(define-endpoint ("/resumes/language/add/submit" :method :post) (&post (name :parameter-type 'string) (understanding_listening :parameter-type 'string) (understanding_reading :parameter-type 'string) (speaking_interaction :parameter-type 'string) (speaking_production :parameter-type 'string) (writing :parameter-type 'string)) .language-add-submit) +(define-endpoint ("/resumes/language/modify" :method :post) (&post (id :parameter-type 'integer)) .language-modify) +(define-endpoint ("/resumes/language/modify/submit" :method :post) (&post (id :parameter-type 'integer) (name :parameter-type 'string) (understanding_listening :parameter-type 'string) (understanding_reading :parameter-type 'string) (speaking_interaction :parameter-type 'string) (speaking_production :parameter-type 'string) (writing :parameter-type 'string)) .language-modify-submit) +(define-endpoint ("/resumes/language/delete/:id" :method :delete) (&path (id 'integer)) .language-delete) diff --git a/sql/functions/resume.insert_language.sql b/sql/functions/resume.insert_language.sql new file mode 100644 index 0000000..92ce6b9 --- /dev/null +++ b/sql/functions/resume.insert_language.sql @@ -0,0 +1,45 @@ +drop function resume.insert_language ( + p_user_id int, + p_name character varying, + p_understanding_listening character varying, + p_understanding_reading character varying, + p_speaking_interaction character varying, + p_speaking_production character varying, + p_writing character varying +); + +create or replace function resume.insert_language ( + p_user_id int, + p_name character varying, + p_understanding_listening character varying, + p_understanding_reading character varying, + p_speaking_interaction character varying, + p_speaking_production character varying, + p_writing character varying +) +returns bigint +as $$ +declare + l_id bigint; +begin + insert into resume.language ( + user_id, + name, + understanding_listening, + understanding_reading, + speaking_interaction, + speaking_production, + writing + ) values ( + p_user_id, + p_name, + p_understanding_listening, + p_understanding_reading, + p_speaking_interaction, + p_speaking_production, + p_writing + ) returning id into l_id; + + return l_id; +end; +$$ language plpgsql; |
