From 85fdf5db522a3e3e841fef4c3dd5ff3a570739ca Mon Sep 17 00:00:00 2001 From: ckonstanski Date: Mon, 27 Jul 2026 20:27:17 -0600 Subject: stuff --- lisp/service/base-service.lisp | 210 ++- lisp/service/menu-service.lisp | 10 +- lisp/service/resume-service.lisp | 1489 ++++++++++---------- lisp/sql/contactinfo.lisp | 14 +- .../resume/clojurescript/resume/src/core.cljs | 2 +- lisp/webapps/resume/site.lisp | 194 ++- lisp/webapps/webapp-loader.lisp | 172 --- sql/tables/resume.contactinfo.sql | 1 + sql/views/resume.contactinfo_v.sql | 1 + 9 files changed, 1066 insertions(+), 1027 deletions(-) diff --git a/lisp/service/base-service.lisp b/lisp/service/base-service.lisp index bd38c5a..8853639 100644 --- a/lisp/service/base-service.lisp +++ b/lisp/service/base-service.lisp @@ -3,19 +3,221 @@ (in-package :resume) -(defclass base-service () - () +;; webapp + +(defvar *acceptor* nil) +(defvar *dispatch-table* '(#'dispatch-easy-handlers #'default-dispatcher)) +(defvar *webapps* (make-hash-table :test 'equal)) +(defvar *webapp* nil) +(defvar *uri* nil) +(defvar *header-register* nil) +(defvar *sessionid* nil) +(defparameter *port* 3014) +(defparameter *server-root* (namestring (asdf:system-relative-pathname (intern (package-name #.*package*)) "./")) + "The location of the web server root on the filesystem.") + +(defclass webapp () + ((name :initarg :name + :initform nil + :accessor name + :documentation "The name of the webapp as used in the code. A +string used as the key to any webapp config lookup.") + (scheme :initarg :scheme + :initform nil + :accessor scheme) + (url :initarg :url + :initform nil + :accessor url + :documentation "The domain portion of the URL to the +root of the webapp.") + (document-root :initarg :document-root + :initform nil + :accessor document-root + :documentation "The absolute filesystem path to the +webapp's top-level directory which is inside the webapps folder.") + (title :initarg :title + :initform nil + :accessor title + :documentation "The default title that shows up in +the browser title bar.") + (meta-description :initarg :meta-description + :initform nil + :accessor meta-description + :documentation "The text that goes into the META DESCRIPTION +tag, and anywhere else we want to put this text so that it will show +up in Google.") + (databases :initarg :databases + :initform nil + :accessor databases) + (mail-mx :initarg :mail-mx + :initform nil + :accessor mail-mx) + (mail-from :initarg :mail-from + :initform nil + :accessor mail-from) + (mail-postmaster :initarg :mail-postmaster + :initform nil + :accessor mail-postmaster) + (mail-webmaster :initarg :mail-webmaster + :initform nil + :accessor mail-webmaster) + (mail-info :initarg :mail-info + :initform nil + :accessor mail-info) + (mail-login-notify :initarg :mail-login-notify + :initform nil + :accessor mail-login-notify) + (mail-authentication :initarg :mail-authentication + :initform nil + :accessor mail-authentication) + (mail-ssl :initarg :mail-ssl + :initform nil + :accessor mail-ssl)) (:documentation "")) +(defmethod get-site-file-path ((webapp webapp)) + (format nil "~a/site" (document-root webapp))) + +(defmethod get-pages-file-paths ((webapp webapp)) + (mapcar (lambda (pages-file) + (ppcre:regex-replace-all "\\.lisp$" (format nil "~a" pages-file) "")) + (remove-if (lambda (x) (equal x "shared")) + (org-ckons-core::shell-wrapper (format nil "find '~a' -maxdepth 1 -type f -iname 'pages*.lisp' |sort" (document-root webapp)))))) + +(defun make-server-path (relative-path) + "Makes a relative filesystem path into a full one, using +`*server-root*' as the base." + (make-document-root-path *server-root* relative-path)) + +(defun make-document-root-path (document-root relative-path) + "Makes a relative filesystem path into a full one, using +`document-root' as the base." + (concatenate 'string document-root relative-path)) + +(defun make-webapp-path (relative-path) + "Makes an absolute filesystem path to a location in the webapps +folder." + (concatenate 'string *server-root* "webapps/" relative-path)) + +(defun get-options-files () + (mapcar (lambda (webapp-directory) + (format nil "~a/conf/options.lisp" webapp-directory)) + (remove-if (lambda (x) (or (org-ckons-core::match-it "webapps/$" x) + (org-ckons-core::match-it "webapps/shared$" x) + (org-ckons-core::match-it "webapps/CVS$" x) + (org-ckons-core::match-it "webapps/\\.$" x) + (org-ckons-core::match-it "webapps/\\.\\.$" x))) + (org-ckons-core::shell-wrapper (format nil "find '~a' -maxdepth 1 -type d |sort" (make-webapp-path "")))))) + +(defun set-webapp (webapp) + "Sets a `webapp' object in `*webapps*'. The lookup key is the webapp +name. If a webapp already exists under this key, it gets overwritten +with the new one." + (setf (gethash (name webapp) *webapps*) webapp)) + +(defun get-webapp (key) + "Gets the webapp object stored under the key `key'." + (gethash key *webapps*)) + +(defun populate-webapps () + (loop for options-file in (get-options-files) + do (with-open-file (input options-file :direction :input) + (let* ((form (read input))) + (set-webapp (make-instance 'webapp + :name (getf form :name) + :scheme (getf form :scheme) + :url (getf form :url) + :document-root (make-webapp-path (getf form :document-root)) + :title (getf form :title) + :meta-description (getf form :meta-description) + :databases (getf form :databases) + :mail-mx (getf form :mail-mx) + :mail-from (getf form :mail-from) + :mail-postmaster (getf form :mail-postmaster) + :mail-webmaster (getf form :mail-webmaster) + :mail-info (getf form :mail-info) + :mail-login-notify (getf form :mail-login-notify) + :mail-authentication (getf form :mail-authentication) + :mail-ssl (getf form :mail-ssl))))))) + +(defun resume () + "Call this to start the server." + (when (null *acceptor*) + (let ((package (string-downcase (package-name #.*package*)))) + (populate-webapps) + (setf (log-manager) (make-instance 'log-manager :message-class 'formatted-message)) + (start-messenger 'text-file-messenger :filename (format nil "/var/log/lisp/~a.log" package)) + (setf *session-secret* (org-ckons-session::generate-sessionid)) + (populate-webapps) + (setf *acceptor* (start (make-instance 'easy-routes:easy-routes-acceptor + :port *port* + :document-root (make-server-path (format nil "webapps/~a/" package)) + :name (format nil "~a-acceptor" package))))))) + +(defmacro with-request-wrapper (uri page-function &rest args) + (let ((package (string-downcase (package-name #.*package*)))) + `(let (output) + (let* ((*webapp* (get-webapp ,package)) + (*uri* ,uri) + (*header-register* (make-instance 'org-ckons-session::header-register)) + (*sessionid* (ensure-user-session-exists))) + (ensure-user-exists) + (setf output (,page-function ,@args)) + (org-ckons-session::ship-headers *header-register*)) + output))) + +(defmacro define-endpoint (template-and-options var-list page-function &rest args) + "Does the grunt work of creating an `easy-routes' route for each page +you wish to publish." + (let ((name (gensym)) + (uri (first template-and-options)) + (method (getf (rest template-and-options) :method))) + `(progn + (org-ckons-core::logger (format nil "Publishing page. URL = [~a], method = [~a]" ,uri ,method)) + (easy-routes:defroute ,name ,template-and-options + ,var-list + (with-request-wrapper ,uri ,page-function ,@args))))) + +;; base-service + (defmacro loop-intersect-slots ((slot record other-object) &body body) `(loop for ,slot in (intersect-slots ,record (org-ckons-core::map-slot-names ,other-object)) do (when (slot-is-field-p ,slot) ,@body))) +(defclass base-service () + () + (:documentation "")) + (defmethod copy-from-record ((base-service base-service) (record record)) (loop-intersect-slots (slot record base-service) - (setf (slot-value base-service slot) (slot-value record slot)))) + (setf (slot-value base-service slot) (slot-value record slot)))) (defmethod copy-to-record ((base-service base-service) (record record)) (loop-intersect-slots (slot record base-service) - (setf (slot-value record slot) (slot-value base-service slot)))) + (setf (slot-value record slot) (slot-value base-service slot)))) + +(defun base (&optional (start-url "/home")) + (org-ckons-http::html5 + `(html + (head + ((meta :name "viewport" :content "width=device-width, initial-scale=1, shrink-to-fit=no")) + ((meta :charset "utf-8")) + ((title) ,(title *webapp*)) + ,@(mapcar (lambda (css) + `((link :rel "stylesheet" :href ,(getf css :href) :integrity ,(getf css :integrity) :crossorigin ,(getf css :crossorigin)))) + '((:href "https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" :integrity "sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" :crossorigin "anonymous") + (:href "/static/css/stylesheet.css" :crossorigin "anonymous"))) + ,@(mapcar (lambda (js) + `((script :type "text/javascript" :src ,(getf js :src) :integrity ,(getf js :integrity) :crossorigin ,(getf js :crossorigin)))) + '((:src "https://code.jquery.com/jquery-3.7.1.slim.min.js" :integrity "sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8=" :crossorigin "anonymous"))) + ((script :type "text/javascript" :src "/cljs-out/dev-main.js"))) + ((body :onload ,(format nil "resume.core.start(~a)" (if start-url + (format nil "'~a'" start-url) + "null"))) + ((div :id "app")) + ,@(mapcar (lambda (js) + `((script :type "text/javascript" :src ,(getf js :src) :integrity ,(getf js :integrity) :crossorigin ,(getf js :crossorigin)))) + '((:src "https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" :integrity "sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" :crossorigin "anonymous"))))))) + +(define-endpoint ("/" :method :get) () base) diff --git a/lisp/service/menu-service.lisp b/lisp/service/menu-service.lisp index 7102f44..a7b67e3 100644 --- a/lisp/service/menu-service.lisp +++ b/lisp/service/menu-service.lisp @@ -4,11 +4,11 @@ (in-package :resume) (defparameter *menu-config* '((:id "a_menu_home" :label "Home" :handler "/home" :permissions "_Public") - (: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_resumes_skills" :label "Skills" :handler "/resumes/skills" :permissions "resume-view") + (:id "a_menu_resumes" :label "Resumes" :handler "/resume" :permissions "resume-view") + (:id "a_menu_resumes_contactinfo" :label "Contact Info" :handler "/resume/contactinfo" :permissions "resume-view") + (:id "a_menu_resumes_education" :label "Education" :handler "/resume/education" :permissions "resume-view") + (:id "a_menu_resumes_language" :label "Language" :handler "/resume/language" :permissions "resume-view") + (:id "a_menu_resumes_skills" :label "Skills" :handler "/resume/skills" :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 68b2c36..abbb005 100644 --- a/lisp/service/resume-service.lisp +++ b/lisp/service/resume-service.lisp @@ -5,613 +5,701 @@ ;; shared -(defclass resume-service (auth-service) - ((title :initarg :title - :initform nil - :accessor title)) - (:documentation "")) - -;; resume - -(defun resume-json () - (with-auth (instance resume-service "resume-view") - (setf (title instance) "Resumes"))) - -(defclass resume/view-service (resume-service resume) - ((resumes :initarg :resumes +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun state-options (states) + (mapcar (lambda (state) + `(:label ,(format nil "~a ~a" (abbr state) (state state)) :value ,(id state))) + states)) + + (defun visastatus-options (visastatuses) + (mapcar (lambda (visastatus) + `(:label ,(status visastatus) :value ,(id visastatus))) + visastatuses)) + + (defun language-options () + (mapcar (lambda (level) + `(:label ,level :value ,level)) + '("A1" "A2" "B1" "B2" "C1" "C2"))) + + (defclass resume-service (auth-service) + ((title :initarg :title :initform nil - :accessor resumes) - (location-p :initform nil)) - (:documentation "")) - -(defun resume-view-json () - (with-auth (instance resume/view-service "resume-view") - (with-resume-database - (let ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user))) - (setf (resumes instance) (get-records resume-pkg (make-instance 'resume :user_id (id user)) "name asc")))) - (sanitize-rest-json instance) - (loop for resume in (resumes instance) - do (sanitize-json resume)))) - -(defclass resume/add-service (resume/view-service) - ((form :initarg :form - :initform nil - :accessor form)) - (:documentation "")) - -(defun resume-add-json () - (with-auth (instance resume/add-service "resume-modify") - (setf (title instance) "Resume - Add") - (setf (form instance) (make-form "resume-add-form" - nil - t - `((:name "name" :label "Name" :field-type "text" :required "required") - (:label "Add Resume" :field-type "button" :onclick "on_resume_add_submit_clicked()")))))) - -(defun resume-add-submit-json (name) - (declare (special name)) - (with-auth (instance resume/add-service "resume-modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (resume (make-instance 'resume :user_id (id user)))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'resume-add-submit-json)) - do (setf (slot-value resume param) (symbol-value param))) - (insert-resume resume-pkg resume) - (setf (session-value :message) (format nil "Resume \"~a\" created successfully." (name resume)))) - (error (e) - (setf (session-value :errormsg) (format nil "Error creating resume \"~a\". ~a" name e))))))) - -(defclass resume/modify-service (resume/add-service) - () - (:documentation "")) - -(defun resume-modify-json (id) - (with-auth (instance resume/modify-service "resume-modify") - (setf (title instance) "Resume - Modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (resume (get-record resume-pkg (make-instance 'resume :id id :user_id (id user))))) - (if resume - (setf (form instance) (make-form "resume-modify-form" - nil - t - `((:name "id" :field-type "hidden" :value ,(id resume) :required "required") - (:name "name" :label "Name" :field-type "text" :value ,(name resume) :required "required") - (:label "Modify Resume" :field-type "button" :onclick "on_resume_modify_submit_clicked()")))) - (setf (session-value :errormsg) "Error: could not modify resume. Not found.")))))) - -(defun resume-modify-submit-json (id name) - (declare (special id name)) - (with-auth (instance resume/modify-service "resume-modify") - (setf (title instance) "Resume - Modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (resume (get-record resume-pkg (make-instance 'resume :id id :user_id (id user))))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'resume-modify-submit-json)) - do (setf (slot-value resume param) (symbol-value param))) - (update-record resume-pkg resume) - (setf (session-value :message) (format nil "Resume \"~a\" modified successfully." (name resume)))) - (error (e) - (setf (session-value :errormsg) (format nil "Error modifying resume \"~a\". ~a" name e))))))) - -(defclass resume/delete-service (resume/add-service) - () - (:documentation "")) - -(defun resume-delete-json (id) - (with-auth (instance resume/delete-service "resume-modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (resume (get-record resume-pkg (make-instance 'resume :id id :user_id (id user))))) - (if resume - (progn - (delete-resume resume-pkg resume) - (setf (session-value :message) (format nil "Resume \"~a\" deleted successfully." (name resume)))) - (setf (session-value :errormsg) "Error: could not delete resume: not found.")))))) - -;; contactinfo - -(defun contactinfo-json () - (with-auth (instance resume-service "resume-view") - (setf (title instance) "Contact Information"))) - -(defclass contactinfo/view-service (resume-service contactinfo) - ((contactinfos :initarg :contactinfos + :accessor title)) + (:documentation "")) + + ;; resume + + (defun resume-json () + (with-auth (instance resume-service "resume-view") + (setf (title instance) "Resumes"))) + + (defclass resume/view-service (resume-service resume) + ((resumes :initarg :resumes + :initform nil + :accessor resumes) + (location-p :initform nil)) + (:documentation "")) + + (defun resume-view-json () + (with-auth (instance resume/view-service "resume-view") + (with-resume-database + (let ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user))) + (setf (resumes instance) (get-records resume-pkg (make-instance 'resume :user_id (id user)) "name asc")))) + (sanitize-rest-json instance) + (loop for resume in (resumes instance) + do (sanitize-json resume)))) + + (defclass resume/add-service (resume/view-service) + ((form :initarg :form + :initform nil + :accessor form)) + (:documentation "")) + + (defun resume-add-json () + (with-auth (instance resume/add-service "resume-modify") + (setf (title instance) "Resume - Add") + (setf (form instance) (make-form "resume-add-form" + nil + t + `((:name "name" :label "Name" :field-type "text" :required "required") + (:label "Add Resume" :field-type "button" :onclick "on_resume_add_submit_clicked()")))))) + + (defun resume-add-submit-json (name) + (declare (special name)) + (with-auth (instance resume/add-service "resume-modify") + (with-resume-database + (handler-case + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (resume (make-instance 'resume :user_id (id user)))) + (loop for param in (remove-if (lambda (x) + (intersection `(,x) '(id))) + (sb-introspect:function-lambda-list #'resume-add-submit-json)) + do (setf (slot-value resume param) (symbol-value param))) + (insert-record resume-pkg resume) + (setf (session-value :message) (format nil "Resume \"~a\" created successfully." (name resume)))) + (error (e) + (setf (session-value :errormsg) (format nil "Error creating resume \"~a\". ~a" name e))))))) + + (defclass resume/modify-service (resume/add-service) + () + (:documentation "")) + + (defun resume-modify-json (id) + (with-auth (instance resume/modify-service "resume-modify") + (setf (title instance) "Resume - Modify") + (with-resume-database + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (resume (get-record resume-pkg (make-instance 'resume :id id :user_id (id user))))) + (if resume + (setf (form instance) (make-form "resume-modify-form" + nil + t + `((:name "id" :field-type "hidden" :value ,(id resume) :required "required") + (:name "name" :label "Name" :field-type "text" :value ,(name resume) :required "required") + (:label "Modify Resume" :field-type "button" :onclick "on_resume_modify_submit_clicked()")))) + (setf (session-value :errormsg) "Error: could not modify resume. Not found.")))))) + + (defun resume-modify-submit-json (id name) + (declare (special id name)) + (with-auth (instance resume/modify-service "resume-modify") + (setf (title instance) "Resume - Modify") + (with-resume-database + (handler-case + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (resume (get-record resume-pkg (make-instance 'resume :id id :user_id (id user))))) + (loop for param in (remove-if (lambda (x) + (intersection `(,x) '(id))) + (sb-introspect:function-lambda-list #'resume-modify-submit-json)) + do (setf (slot-value resume param) (symbol-value param))) + (update-record resume-pkg resume) + (setf (session-value :message) (format nil "Resume \"~a\" modified successfully." (name resume)))) + (error (e) + (setf (session-value :errormsg) (format nil "Error modifying resume \"~a\". ~a" name e))))))) + + (defclass resume/delete-service (resume/add-service) + () + (:documentation "")) + + (defun resume-delete-json (id) + (with-auth (instance resume/delete-service "resume-modify") + (with-resume-database + (let* ((resume-pkg (make-instance 'resume-pkg)) + (user (get-user)) + (resume (get-record resume-pkg (make-instance 'resume :id id :user_id (id user))))) + (if resume + (progn + (delete-resume resume-pkg resume) + (setf (session-value :message) (format nil "Resume \"~a\" deleted successfully." (name resume)))) + (setf (session-value :errormsg) "Error: could not delete resume: not found.")))))) + + ;; ;; contactinfo + + ;; (defun contactinfo-json () + ;; (with-auth (instance resume-service "resume-view") + ;; (setf (title instance) "Contact Information"))) + + ;; (defclass contactinfo/view-service (resume-service contactinfo) + ;; ((contactinfos :initarg :contactinfos + ;; :initform nil + ;; :accessor contactinfos) + ;; (location-p :initform nil)) + ;; (:documentation "")) + + ;; (defun contactinfo-view-json () + ;; (with-auth (instance contactinfo/view-service "resume-view") + ;; (with-resume-database + ;; (let ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user))) + ;; (setf (contactinfos instance) (get-records resume-pkg (make-instance 'contactinfo-v :user_id (id user)) "state_name asc, city asc, address asc, email asc, phone asc, visastatus asc")))) + ;; (sanitize-rest-json instance) + ;; (loop for contactinfo-v in (contactinfos instance) + ;; do (sanitize-json contactinfo-v)))) + + ;; (defclass contactinfo/add-service (contactinfo/view-service) + ;; ((form :initarg :form + ;; :initform nil + ;; :accessor form)) + ;; (:documentation "")) + + ;; (defun contactinfo-add-json () + ;; (with-auth (instance contactinfo/add-service "resume-modify") + ;; (with-resume-database + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (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") + ;; (setf (form instance) (make-form "contactinfo-add-form" + ;; nil + ;; t + ;; `((:name "address" :label "Address" :field-type "text" :required "required") + ;; (:name "city" :label "City" :field-type "text" :required "required") + ;; (:name "state_id" :label "State" :field-type "select" :options ,(state-options states) :required "required") + ;; (:name "phone" :label "Phone" :field-type "text" :required "required") + ;; (:name "email" :label "Email" :field-type "text" :required "required") + ;; (:name "visastatus_id" :label "VISA Status" :field-type "select" :options ,(visastatus-options visastatuses) :required "required") + ;; (:label "Add Contact Info" :field-type "button" :onclick "on_contactinfo_add_submit_clicked()")))))))) + + ;; (defun contactinfo-add-submit-json (address city state_id phone email visastatus_id) + ;; (declare (special address city state_id phone email visastatus_id)) + ;; (with-auth (instance contactinfo/add-service "resume-modify") + ;; (with-resume-database + ;; (handler-case + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (contactinfo (make-instance 'contactinfo :user_id (id user)))) + ;; (loop for param in (remove-if (lambda (x) + ;; (intersection `(,x) '(id))) + ;; (sb-introspect:function-lambda-list #'contactinfo-add-submit-json)) + ;; do (setf (slot-value contactinfo param) (symbol-value param))) + ;; (insert-contactinfo resume-pkg contactinfo) + ;; (setf (session-value :message) (format nil "Contact Info \"~a, ~a\" created successfully." address city))) + ;; (error (e) + ;; (setf (session-value :errormsg) (format nil "Error creating Contact Info \"~a, ~a\". ~a" address city e))))))) + + ;; (defclass contactinfo/modify-service (contactinfo/add-service) + ;; () + ;; (:documentation "")) + + ;; (defun contactinfo-modify-json (id) + ;; (with-auth (instance contactinfo/modify-service "resume-modify") + ;; (setf (title instance) "Contact Info - 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) "status asc")) + ;; (contactinfo-v (get-record resume-pkg (make-instance 'contactinfo-v :id id :user_id (id user))))) + ;; (if contactinfo-v + ;; (setf (form instance) (make-form "contactinfo-modify-form" + ;; nil + ;; t + ;; `((:name "id" :field-type "hidden" :value ,(id contactinfo-v) :required "required") + ;; (:name "address" :label "Address" :field-type "text" :value ,(address contactinfo-v) :required "required") + ;; (:name "city" :label "City" :field-type "text" :value ,(city contactinfo-v) :required "required") + ;; (:name "state_id" :label "State" :field-type "select" :value ,(state_id contactinfo-v) :options ,(state-options states) :required "required") + ;; (:name "phone" :label "Phone" :field-type "text" :value ,(phone contactinfo-v) :required "required") + ;; (:name "email" :label "Email" :field-type "text" :value ,(email contactinfo-v) :required "required") + ;; (:name "visastatus_id" :label "VISA Status" :field-type "select" :value ,(visastatus_id contactinfo-v) :options ,(visastatus-options visastatuses) :required "required") + ;; (:label "Modify Contact Info" :field-type "button" :onclick "on_contactinfo_modify_submit_clicked()")))) + ;; (setf (session-value :errormsg) "Error: could not modify Contact Info. Not found.")))))) + + ;; (defun contactinfo-modify-submit-json (id address city state_id phone email visastatus_id) + ;; (declare (special id address city state_id phone email visastatus_id)) + ;; (with-auth (instance contactinfo/modify-service "resume-modify") + ;; (setf (title instance) "Contact Info - Modify") + ;; (with-resume-database + ;; (handler-case + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (contactinfo (get-record resume-pkg (make-instance 'contactinfo :id id :user_id (id user))))) + ;; (loop for param in (remove-if (lambda (x) + ;; (intersection `(,x) '(id))) + ;; (sb-introspect:function-lambda-list #'contactinfo-modify-submit-json)) + ;; do (setf (slot-value contactinfo param) (symbol-value param))) + ;; (update-record resume-pkg contactinfo) + ;; (setf (session-value :message) (format nil "Contact Info \"~a, ~a\" modified successfully." address city))) + ;; (error (e) + ;; (setf (session-value :errormsg) (format nil "Error modifying Contact Info \"~a, ~a\". ~a" address city e))))))) + + ;; (defclass contactinfo/delete-service (contactinfo/add-service) + ;; () + ;; (:documentation "")) + + ;; (defun contactinfo-delete-json (id) + ;; (with-auth (instance contactinfo/delete-service "resume-modify") + ;; (with-resume-database + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (contactinfo (get-record resume-pkg (make-instance 'contactinfo :id id :user_id (id user))))) + ;; (if contactinfo + ;; (progn + ;; (delete-record resume-pkg contactinfo) + ;; (setf (session-value :message) (format nil "Contact Info \"~a, ~a\" deleted successfully." (address contactinfo) (city contactinfo)))) + ;; (setf (session-value :errormsg) "Error: could not delete Contact Info: not found.")))))) + + ;; ;; education + + ;; (defun education-json () + ;; (with-auth (instance resume-service "resume-view") + ;; (setf (title instance) "Education"))) + + ;; (defclass education/view-service (resume-service education) + ;; ((educations :initarg :educations + ;; :initform nil + ;; :accessor educations) + ;; (location-p :initform nil)) + ;; (:documentation "")) + + ;; (defun education-view-json () + ;; (with-auth (instance education/view-service "resume-view") + ;; (with-resume-database + ;; (let ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user))) + ;; (setf (educations instance) (get-records resume-pkg (make-instance 'education :user_id (id user)))))) + ;; (sanitize-rest-json instance) + ;; (loop for education in (educations instance) + ;; do (sanitize-json education)))) + + ;; (defclass education/add-service (education/view-service) + ;; ((form :initarg :form + ;; :initform nil + ;; :accessor form)) + ;; (:documentation "")) + + ;; (defun education-add-json () + ;; (with-auth (instance education/add-service "resume-modify") + ;; (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)) + ;; (with-auth (instance education/add-service "resume-modify") + ;; (with-resume-database + ;; (handler-case + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (education (make-instance 'education :user_id (id user)))) + ;; (loop for param in (remove-if (lambda (x) + ;; (intersection `(,x) '(id))) + ;; (sb-introspect:function-lambda-list #'education-add-submit-json)) + ;; do (setf (slot-value education param) (symbol-value param))) + ;; (insert-education resume-pkg education) + ;; (setf (session-value :message) (format nil "Education \"~a, ~a\" created successfully." school major))) + ;; (error (e) + ;; (setf (session-value :errormsg) (format nil "Error creating Education \"~a, ~a\". ~a" school major e))))))) + + ;; (defclass education/modify-service (education/add-service) + ;; () + ;; (:documentation "")) + + ;; (defun education-modify-json (id) + ;; (with-auth (instance education/modify-service "resume-modify") + ;; (setf (title instance) "Education - Modify") + ;; (with-resume-database + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (education (get-record resume-pkg (make-instance 'education :id id :user_id (id user))))) + ;; (if education + ;; (setf (form instance) (make-form "education-modify-form" + ;; nil + ;; t + ;; `((:name "id" :field-type "hidden" :value ,(id education) :required "required") + ;; (:name "school" :label "School" :field-type "text" :value ,(school education) :required "required") + ;; (:name "major" :label "Major" :field-type "text" :value ,(major education) :required "required") + ;; (: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 "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.")))))) + + ;; (defun education-modify-submit-json (id school major minor degree progress start_date end_date) + ;; (declare (special id school major minor degree progress start_date end_date)) + ;; (with-auth (instance education/modify-service "resume-modify") + ;; (setf (title instance) "Education - Modify") + ;; (with-resume-database + ;; (handler-case + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (education (get-record resume-pkg (make-instance 'education :id id :user_id (id user))))) + ;; (loop for param in (remove-if (lambda (x) + ;; (intersection `(,x) '(id))) + ;; (sb-introspect:function-lambda-list #'education-modify-submit-json)) + ;; do (setf (slot-value education param) (symbol-value param))) + ;; (update-record resume-pkg education) + ;; (setf (session-value :message) (format nil "Education \"~a, ~a\" modified successfully." school major))) + ;; (error (e) + ;; (setf (session-value :errormsg) (format nil "Error modifying Education \"~a, ~a\". ~a" school major e))))))) + + ;; (defclass education/delete-service (education/add-service) + ;; () + ;; (:documentation "")) + + ;; (defun education-delete-json (id) + ;; (with-auth (instance education/delete-service "resume-modify") + ;; (with-resume-database + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (education (get-record resume-pkg (make-instance 'education :id id :user_id (id user))))) + ;; (if education + ;; (progn + ;; (delete-record resume-pkg education) + ;; (setf (session-value :message) (format nil "Education \"~a, ~a\" deleted successfully." (school education) (major education)))) + ;; (setf (session-value :errormsg) "Error: could not delete Education: not found.")))))) + + ;; ;; language + + ;; (defun language-json () + ;; (with-auth (instance resume-service "resume-view") + ;; (setf (title instance) "Languages"))) + + ;; (defclass language/view-service (resume-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-records resume-pkg (make-instance 'language :user_id (id 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-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.")))))) + + ;; ;; skill + + ;; (defun skill-json () + ;; (with-auth (instance resume-service "resume-view") + ;; (setf (title instance) "Skills"))) + + ;; (defclass skill/view-service (resume-service skill) + ;; ((skills :initarg :skills + ;; :initform nil + ;; :accessor skills) + ;; (location-p :initform nil)) + ;; (:documentation "")) + + ;; (defun skill-view-json () + ;; (with-auth (instance skill/view-service "resume-view") + ;; (with-resume-database + ;; (let ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user))) + ;; (setf (skills instance) (get-records resume-pkg (make-instance 'skill :user_id (id user)))))) + ;; (sanitize-rest-json instance) + ;; (loop for skill in (skills instance) + ;; do (sanitize-json skill)))) + + ;; (defclass skill/add-service (skill/view-service) + ;; ((form :initarg :form + ;; :initform nil + ;; :accessor form)) + ;; (:documentation "")) + + ;; (defun skill-add-json () + ;; (with-auth (instance skill/add-service "resume-modify") + ;; (setf (title instance) "Skill - Add") + ;; (setf (form instance) (make-form "skill-add-form" + ;; nil + ;; t + ;; `((:name "skill" :label "Skill" :field-type "text" :required "required") + ;; (:label "Add Skill" :field-type "button" :onclick "on_skill_add_submit_clicked()")))))) + + ;; (defun skill-add-submit-json (skill) + ;; (declare (special skill)) + ;; (with-auth (instance skill/add-service "resume-modify") + ;; (with-resume-database + ;; (handler-case + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (skill (make-instance 'skill :user_id (id user)))) + ;; (loop for param in (remove-if (lambda (x) + ;; (intersection `(,x) '(id))) + ;; (sb-introspect:function-lambda-list #'skill-add-submit-json)) + ;; do (setf (slot-value skill param) (symbol-value param))) + ;; (insert-skill resume-pkg skill) + ;; (setf (session-value :message) (format nil "Skill \"~a\" created successfully." skill))) + ;; (error (e) + ;; (setf (session-value :errormsg) (format nil "Error creating Skill \"~a\". ~a" skill e))))))) + + ;; (defclass skill/modify-service (skill/add-service) + ;; () + ;; (:documentation "")) + + ;; (defun skill-modify-json (id) + ;; (with-auth (instance skill/modify-service "resume-modify") + ;; (setf (title instance) "Skill - Modify") + ;; (with-resume-database + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (skill (get-record resume-pkg (make-instance 'skill :id id :user_id (id user))))) + ;; (if skill + ;; (setf (form instance) (make-form "skill-modify-form" + ;; nil + ;; t + ;; `((:name "id" :field-type "hidden" :value ,(id skill) :required "required") + ;; (:name "skill" :label "Skill" :field-type "text" :value ,(skill skill) :required "required") + ;; (:label "Modify Skill" :field-type "button" :onclick "on_skill_modify_submit_clicked()")))) + ;; (setf (session-value :errormsg) "Error: could not modify Skill. Not found.")))))) + + ;; (defun skill-modify-submit-json (id skill) + ;; (declare (special id skill)) + ;; (with-auth (instance skill/modify-service "resume-modify") + ;; (setf (title instance) "Skill - Modify") + ;; (with-resume-database + ;; (handler-case + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (skill (get-record resume-pkg (make-instance 'skill :id id :user_id (id user))))) + ;; (loop for param in (remove-if (lambda (x) + ;; (intersection `(,x) '(id))) + ;; (sb-introspect:function-lambda-list #'skill-modify-submit-json)) + ;; do (setf (slot-value skill param) (symbol-value param))) + ;; (update-record resume-pkg skill) + ;; (setf (session-value :message) (format nil "Skill \"~a\" modified successfully." skill))) + ;; (error (e) + ;; (setf (session-value :errormsg) (format nil "Error modifying Skill \"~a\". ~a" skill e))))))) + + ;; (defclass skill/delete-service (skill/add-service) + ;; () + ;; (:documentation "")) + + ;; (defun skill-delete-json (id) + ;; (with-auth (instance skill/delete-service "resume-modify") + ;; (with-resume-database + ;; (let* ((resume-pkg (make-instance 'resume-pkg)) + ;; (user (get-user)) + ;; (skill (get-record resume-pkg (make-instance 'skill :id id :user_id (id user))))) + ;; (if skill + ;; (progn + ;; (delete-record resume-pkg skill) + ;; (setf (session-value :message) (format nil "Skill \"~a\" deleted successfully." (skill skill)))) + ;; (setf (session-value :errormsg) "Error: could not delete Skill: not found.")))))) + + ;; macros + + (defclass resume-component/view-service (resume-service) + ((components :initarg components :initform nil - :accessor contactinfos) - (location-p :initform nil)) - (:documentation "")) - -(defun contactinfo-view-json () - (with-auth (instance contactinfo/view-service "resume-view") - (with-resume-database - (let ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user))) - (setf (contactinfos instance) (get-records resume-pkg (make-instance 'contactinfo-v :user_id (id user)) "state_name asc, city asc, address asc, email asc, phone asc, visastatus asc")))) - (sanitize-rest-json instance) - (loop for contactinfo-v in (contactinfos instance) - do (sanitize-json contactinfo-v)))) - -(defclass contactinfo/add-service (contactinfo/view-service) - ((form :initarg :form - :initform nil - :accessor form)) - (:documentation "")) - -(defun state-options (states) - (mapcar (lambda (state) - `(:label ,(format nil "~a ~a" (abbr state) (state state)) :value ,(id state))) - states)) - -(defun visastatus-options (visastatuses) - (mapcar (lambda (visastatus) - `(:label ,(status visastatus) :value ,(id visastatus))) - visastatuses)) - -(defun contactinfo-add-json () - (with-auth (instance contactinfo/add-service "resume-modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (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") - (setf (form instance) (make-form "contactinfo-add-form" - nil - t - `((:name "address" :label "Address" :field-type "text" :required "required") - (:name "city" :label "City" :field-type "text" :required "required") - (:name "state_id" :label "State" :field-type "select" :options ,(state-options states) :required "required") - (:name "phone" :label "Phone" :field-type "text" :required "required") - (:name "email" :label "Email" :field-type "text" :required "required") - (:name "visastatus_id" :label "VISA Status" :field-type "select" :options ,(visastatus-options visastatuses) :required "required") - (:label "Add Contact Info" :field-type "button" :onclick "on_contactinfo_add_submit_clicked()")))))))) - -(defun contactinfo-add-submit-json (address city state_id phone email visastatus_id) - (declare (special address city state_id phone email visastatus_id)) - (with-auth (instance contactinfo/add-service "resume-modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (contactinfo (make-instance 'contactinfo :user_id (id user)))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'contactinfo-add-submit-json)) - do (setf (slot-value contactinfo param) (symbol-value param))) - (insert-contactinfo resume-pkg contactinfo) - (setf (session-value :message) (format nil "Contact Info \"~a, ~a\" created successfully." address city))) - (error (e) - (setf (session-value :errormsg) (format nil "Error creating Contact Info \"~a, ~a\". ~a" address city e))))))) - -(defclass contactinfo/modify-service (contactinfo/add-service) - () - (:documentation "")) - -(defun contactinfo-modify-json (id) - (with-auth (instance contactinfo/modify-service "resume-modify") - (setf (title instance) "Contact Info - 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) "status asc")) - (contactinfo-v (get-record resume-pkg (make-instance 'contactinfo-v :id id :user_id (id user))))) - (if contactinfo-v - (setf (form instance) (make-form "contactinfo-modify-form" - nil - t - `((:name "id" :field-type "hidden" :value ,(id contactinfo-v) :required "required") - (:name "address" :label "Address" :field-type "text" :value ,(address contactinfo-v) :required "required") - (:name "city" :label "City" :field-type "text" :value ,(city contactinfo-v) :required "required") - (:name "state_id" :label "State" :field-type "select" :value ,(state_id contactinfo-v) :options ,(state-options states) :required "required") - (:name "phone" :label "Phone" :field-type "text" :value ,(phone contactinfo-v) :required "required") - (:name "email" :label "Email" :field-type "text" :value ,(email contactinfo-v) :required "required") - (:name "visastatus_id" :label "VISA Status" :field-type "select" :value ,(visastatus_id contactinfo-v) :options ,(visastatus-options visastatuses) :required "required") - (:label "Modify Contact Info" :field-type "button" :onclick "on_contactinfo_modify_submit_clicked()")))) - (setf (session-value :errormsg) "Error: could not modify Contact Info. Not found.")))))) - -(defun contactinfo-modify-submit-json (id address city state_id phone email visastatus_id) - (declare (special id address city state_id phone email visastatus_id)) - (with-auth (instance contactinfo/modify-service "resume-modify") - (setf (title instance) "Contact Info - Modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (contactinfo (get-record resume-pkg (make-instance 'contactinfo :id id :user_id (id user))))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'contactinfo-modify-submit-json)) - do (setf (slot-value contactinfo param) (symbol-value param))) - (update-record resume-pkg contactinfo) - (setf (session-value :message) (format nil "Contact Info \"~a, ~a\" modified successfully." address city))) - (error (e) - (setf (session-value :errormsg) (format nil "Error modifying Contact Info \"~a, ~a\". ~a" address city e))))))) - -(defclass contactinfo/delete-service (contactinfo/add-service) - () - (:documentation "")) - -(defun contactinfo-delete-json (id) - (with-auth (instance contactinfo/delete-service "resume-modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (contactinfo (get-record resume-pkg (make-instance 'contactinfo :id id :user_id (id user))))) - (if contactinfo - (progn - (delete-record resume-pkg contactinfo) - (setf (session-value :message) (format nil "Contact Info \"~a, ~a\" deleted successfully." (address contactinfo) (city contactinfo)))) - (setf (session-value :errormsg) "Error: could not delete Contact Info: not found.")))))) - -;; education - -(defun education-json () - (with-auth (instance resume-service "resume-view") - (setf (title instance) "Education"))) - -(defclass education/view-service (resume-service education) - ((educations :initarg :educations - :initform nil - :accessor educations) - (location-p :initform nil)) - (:documentation "")) - -(defun education-view-json () - (with-auth (instance education/view-service "resume-view") - (with-resume-database - (let ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user))) - (setf (educations instance) (get-records resume-pkg (make-instance 'education :user_id (id user)))))) - (sanitize-rest-json instance) - (loop for education in (educations instance) - do (sanitize-json education)))) - -(defclass education/add-service (education/view-service) - ((form :initarg :form - :initform nil - :accessor form)) - (:documentation "")) - -(defun education-add-json () - (with-auth (instance education/add-service "resume-modify") - (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)) - (with-auth (instance education/add-service "resume-modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (education (make-instance 'education :user_id (id user)))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'education-add-submit-json)) - do (setf (slot-value education param) (symbol-value param))) - (insert-education resume-pkg education) - (setf (session-value :message) (format nil "Education \"~a, ~a\" created successfully." school major))) - (error (e) - (setf (session-value :errormsg) (format nil "Error creating Education \"~a, ~a\". ~a" school major e))))))) - -(defclass education/modify-service (education/add-service) - () - (:documentation "")) - -(defun education-modify-json (id) - (with-auth (instance education/modify-service "resume-modify") - (setf (title instance) "Education - Modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (education (get-record resume-pkg (make-instance 'education :id id :user_id (id user))))) - (if education - (setf (form instance) (make-form "education-modify-form" - nil - t - `((:name "id" :field-type "hidden" :value ,(id education) :required "required") - (:name "school" :label "School" :field-type "text" :value ,(school education) :required "required") - (:name "major" :label "Major" :field-type "text" :value ,(major education) :required "required") - (: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 "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.")))))) - -(defun education-modify-submit-json (id school major minor degree progress start_date end_date) - (declare (special id school major minor degree progress start_date end_date)) - (with-auth (instance education/modify-service "resume-modify") - (setf (title instance) "Education - Modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (education (get-record resume-pkg (make-instance 'education :id id :user_id (id user))))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'education-modify-submit-json)) - do (setf (slot-value education param) (symbol-value param))) - (update-record resume-pkg education) - (setf (session-value :message) (format nil "Education \"~a, ~a\" modified successfully." school major))) - (error (e) - (setf (session-value :errormsg) (format nil "Error modifying Education \"~a, ~a\". ~a" school major e))))))) - -(defclass education/delete-service (education/add-service) - () - (:documentation "")) - -(defun education-delete-json (id) - (with-auth (instance education/delete-service "resume-modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (education (get-record resume-pkg (make-instance 'education :id id :user_id (id user))))) - (if education - (progn - (delete-record resume-pkg education) - (setf (session-value :message) (format nil "Education \"~a, ~a\" deleted successfully." (school education) (major education)))) - (setf (session-value :errormsg) "Error: could not delete Education: not found.")))))) - -;; language - -(defun language-json () - (with-auth (instance resume-service "resume-view") - (setf (title instance) "Languages"))) - -(defclass language/view-service (resume-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-records resume-pkg (make-instance 'language :user_id (id 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 () - (mapcar (lambda (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.")))))) - -;; skill - -(defun skill-json () - (with-auth (instance resume-service "resume-view") - (setf (title instance) "Skills"))) - -(defclass skill/view-service (resume-service skill) - ((skills :initarg :skills + :accessor components) + (location-p :initform nil)) + (:documentation "")) + + (defclass resume-component/modify-service (resume-component/view-service) + ((form :initarg :form :initform nil - :accessor skills) - (location-p :initform nil)) - (:documentation "")) - -(defun skill-view-json () - (with-auth (instance skill/view-service "resume-view") - (with-resume-database - (let ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user))) - (setf (skills instance) (get-records resume-pkg (make-instance 'skill :user_id (id user)))))) - (sanitize-rest-json instance) - (loop for skill in (skills instance) - do (sanitize-json skill)))) - -(defclass skill/add-service (skill/view-service) - ((form :initarg :form - :initform nil - :accessor form)) - (:documentation "")) - -(defun skill-add-json () - (with-auth (instance skill/add-service "resume-modify") - (setf (title instance) "Skill - Add") - (setf (form instance) (make-form "skill-add-form" - nil - t - `((:name "skill" :label "Skill" :field-type "text" :required "required") - (:label "Add Skill" :field-type "button" :onclick "on_skill_add_submit_clicked()")))))) - -(defun skill-add-submit-json (skill) - (declare (special skill)) - (with-auth (instance skill/add-service "resume-modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (skill (make-instance 'skill :user_id (id user)))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'skill-add-submit-json)) - do (setf (slot-value skill param) (symbol-value param))) - (insert-skill resume-pkg skill) - (setf (session-value :message) (format nil "Skill \"~a\" created successfully." skill))) - (error (e) - (setf (session-value :errormsg) (format nil "Error creating Skill \"~a\". ~a" skill e))))))) - -(defclass skill/modify-service (skill/add-service) - () - (:documentation "")) - -(defun skill-modify-json (id) - (with-auth (instance skill/modify-service "resume-modify") - (setf (title instance) "Skill - Modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (skill (get-record resume-pkg (make-instance 'skill :id id :user_id (id user))))) - (if skill - (setf (form instance) (make-form "skill-modify-form" - nil - t - `((:name "id" :field-type "hidden" :value ,(id skill) :required "required") - (:name "skill" :label "Skill" :field-type "text" :value ,(skill skill) :required "required") - (:label "Modify Skill" :field-type "button" :onclick "on_skill_modify_submit_clicked()")))) - (setf (session-value :errormsg) "Error: could not modify Skill. Not found.")))))) - -(defun skill-modify-submit-json (id skill) - (declare (special id skill)) - (with-auth (instance skill/modify-service "resume-modify") - (setf (title instance) "Skill - Modify") - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (skill (get-record resume-pkg (make-instance 'skill :id id :user_id (id user))))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #'skill-modify-submit-json)) - do (setf (slot-value skill param) (symbol-value param))) - (update-record resume-pkg skill) - (setf (session-value :message) (format nil "Skill \"~a\" modified successfully." skill))) - (error (e) - (setf (session-value :errormsg) (format nil "Error modifying Skill \"~a\". ~a" skill e))))))) - -(defclass skill/delete-service (skill/add-service) - () - (:documentation "")) - -(defun skill-delete-json (id) - (with-auth (instance skill/delete-service "resume-modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (skill (get-record resume-pkg (make-instance 'skill :id id :user_id (id user))))) - (if skill - (progn - (delete-record resume-pkg skill) - (setf (session-value :message) (format nil "Skill \"~a\" deleted successfully." (skill skill)))) - (setf (session-value :errormsg) "Error: could not delete Skill: not found.")))))) - -;; macro - -(defmacro define-resume-component ((component-s rest-args) &body input-form-fields) + :accessor form)) + (:documentation ""))) + +;; (defmacro ,func-add-s () +;; `(with-auth (instance ,,class-modify-s "resume-modify") +;; (setf (title instance) (format nil "~a - Add" ,,component)) +;; (setf (form instance) (make-form ,,form-add +;; nil +;; t +;; `(() ;;,,@input-add-fields +;; (:label ,,,(format nil "Add ~a" component) :field-type "button" :onclick ,,(format nil "on_~a_add_submit_clicked()" component-lcase))))))) + +;; (defmacro ,func-add-submit-s (,@arg-names) +;; `(progn +;; (declare (special ,,@arg-names)) +;; (with-auth (instance ,,class-modify-s "resume-modify") +;; (with-resume-database +;; (handler-case +;; (let* ((resume-pkg (make-instance 'resume-pkg)) +;; (user (get-user)) +;; (,,component-s (make-instance ',,component-s :user_id (id user)))) +;; (loop for param in (remove-if (lambda (x) +;; (intersection `(,x) '(id))) +;; (sb-introspect:function-lambda-list #',func-add-submit-s)) +;; do (setf (slot-value ,,component-s param) (symbol-value param))) +;; (insert-record resume-pkg ,,component-s) +;; (setf (session-value :message) (format nil "~a created successfully." ,,component))) +;; (error (e) +;; (setf (session-value :errormsg) (format nil "Error creating ~a. ~a" ,,component e)))))))) + +;; (defmacro ,func-modify-s (id) +;; `(with-auth (instance ,,class-modify-s "resume-modify") +;; (setf (title instance) (format nil "~a - Modify" ,,component)) +;; (with-resume-database +;; (let* ((resume-pkg (make-instance 'resume-pkg)) +;; (user (get-user)) +;; (,,component-s (get-record resume-pkg (make-instance ',,component-s :id ,id :user_id (id user))))) +;; (if ,,component-s +;; (setf (form instance) (make-form ,,form-modify +;; nil +;; t +;; `((:name "id" :field-type "hidden" :value ,(id ,component-s) :required "required") +;; ;;,,@input-modify-fields +;; (:label ,,,(format nil "Modify ~a" component) :field-type "button" :onclick ,,(format nil "on_~a_modify_submit_clicked()" component-lcase))))) +;; (setf (session-value :errormsg) (format nil "Error: could not modify ~a. Not found." ,,component))))))) + +;; (defmacro ,func-modify-submit-s (,@(append '(id) arg-names)) +;; `(progn +;; (declare (special ,,@(append '(id) arg-names))) +;; (with-auth (instance ,,class-modify-s "resume-modify") +;; (setf (title instance) (format nil "~a - Modify" ,,component)) +;; (with-resume-database +;; (handler-case +;; (let* ((resume-pkg (make-instance 'resume-pkg)) +;; (user (get-user)) +;; (,,component-s (get-record resume-pkg (make-instance ',,component-s :id ,id :user_id (id user))))) +;; (loop for param in (remove-if (lambda (x) +;; (intersection `(,x) '(id))) +;; (sb-introspect:function-lambda-list #',func-modify-submit-s)) +;; do (setf (slot-value ,,component-s param) (symbol-value param))) +;; (update-record resume-pkg ,,component-s) +;; (setf (session-value :message) (format nil "~a modified successfully." ,,component))) +;; (error (e) +;; (setf (session-value :errormsg) (format nil "Error modifying ~a. ~a" ,,component e)))))))) + +;; (defmacro ,func-delete-s (id) +;; `(with-auth (instance ,,class-modify-s "resume-modify") +;; (with-resume-database +;; (let* ((resume-pkg (make-instance 'resume-pkg)) +;; (user (get-user)) +;; (,,component-s (get-record resume-pkg (make-instance ',,component-s :id ,id :user_id (id user))))) +;; (if ,,component-s +;; (progn +;; (delete-record resume-pkg ,,component-s) +;; (setf (session-value :message) (format nil "~a deleted successfully." ,,component))) +;; (setf (session-value :errormsg) (format nil "Error: could not delete ~a: not found." ,,component))))))) + +(defmacro define-resume-component ((component-s rest-args input-add-fields input-modify-fields)) "`component-s' is a symbol that matches the component's record object name, i.e SKILL, JOB, EDUCATION, LANGUAGE, CONTACTINFO. This will be used all over the place. The record name equals the component name. @@ -619,100 +707,56 @@ used all over the place. The record name equals the component name. `rest-args' is the list of REST API arguments for the add and modify forms. In the form like this example: ((id :parameter-type 'integer)) -`input-form-fields' is a list of generic form fields that gets -inserted into the add and modify forms." - (let* ((component (symbol-name component-s)) +`input-add-fields' and `input-modify-fields' are lists of generic form +fields that get inserted into the add and modify forms." + (let* ( + (component (symbol-name component-s)) (component-lcase (string-downcase component)) (components-s (intern (format nil "~aS" component))) - (components-k (intern (format nil "~aS" component) 'keyword)) + ;; (components-k (intern (format nil "~aS" component) 'keyword)) (arg-names (loop for arg in rest-args collect (car arg))) - (macro-root-s (intern (format nil ".~a" component))) - (macro-view-s (intern (format nil "~.a-VIEW" component))) - (macro-add-s (intern (format nil "~.a-ADD" component))) - (macro-add-submit-s (intern (format nil ".~a-ADD-SUBMIT" component))) - (macro-modify-s (intern (format nil ".~a-MODIFY" component))) - (macro-modify-submit-s (intern (format nil ".~a-MODIFY-SUBMIT" component))) - (macro-delete-s (intern (format nil ".~a-DELETE" component))) (func-root-s (intern (format nil "~a-JSON" component))) (func-view-s (intern (format nil "~a-VIEW-JSON" component))) (func-add-s (intern (format nil "~a-ADD-JSON" component))) (func-add-submit-s (intern (format nil "~a-ADD-SUBMIT-JSON" component))) - (func-modify-s (intern (format nil "~a-MODIFY-JSON" component))) - (func-modify-submit-s (intern (format nil "~a-MODIFY-SUBMIT-JSON" component))) - (func-delete-s (intern (format nil "~a-DELETE-JSON" component))) - (class-view-s (intern (format nil "~a/VIEW-SERVICE" component))) - (class-modify-s (intern (format nil "~a/MODIFY-SERVICE" component))) - (form-add (intern (format nil "~a-add-form" component-lcase))) - (form-modify (format nil "~a-modify-form" component-lcase))) + ;; (func-modify-s (intern (format nil "~a-MODIFY-JSON" component))) + ;; (func-modify-submit-s (intern (format nil "~a-MODIFY-SUBMIT-JSON" component))) + ;; (func-delete-s (intern (format nil "~a-DELETE-JSON" component))) + (form-add (format nil "~a-add-form" component-lcase)) + ;; (form-modify (format nil "~a-modify-form" component-lcase)) + ) `(progn - (defmacro ,macro-root-s () - `(,func-root-s)) - - (defmacro ,macro-view-s () - `(,func-view-s)) - - (defmacro ,macro-add-s () - `(,func-add-s)) - - (defmacro ,macro-add-submit-s () - `(,macro-add-submit-s ,arg-names)) - - (defmacro ,macro-modify-s () - `(,func-modify-s id)) - - (defmacro ,macro-modify-submit-s () - `(,func-modify-submit-s ,(append '(id) arg-names))) - - (defmacro ,macro-delete-s () - `(,func-delete-s id)) - - (define-endpoint (,(format nil ("/resume/~a" component-lcase) :method :get) () ,macro-root-s)) - (define-endpoint (,(format nil ("/resume/~a/view" component-lcase) :method :get) () ,macro-view-s)) - (define-endpoint (,(format nil ("/resume/~a/add" component-lcase) :method :post) () ,macro-add-s)) - (define-endpoint (,(format nil ("/resume/~a/add/submit" component-lcase) :method :post) (&post ,@rest-args) ,macro-add-submit-s)) - (define-endpoint (,(format nil ("/resume/~a/modify" component-lcase) :method :post) (&post (id :parameter-type 'integer)) ,macro-modify-s)) - (define-endpoint (,(format nil ("/resume/~a/modify/submit" component-lcase) :method :post) (&post (id :parameter-type 'integer) ,@rest-args) ,macro-modify-submit-s)) - (define-endpoint (,(format nil ("/resume/~a/delete/:id" component-lcase) :method :delete) (&path (id 'integer)) ,macro-delete-s)) - (defun ,func-root-s () (with-auth (instance resume-service "resume-view") (setf (title instance) ,component))) - (defclass ,class-view-s (resume-service) - ((,components-s :initarg ,components-k - :initform nil - :accessor ,components-s) - (location-p :initform nil)) - (:documentation "")) - (defun ,func-view-s () - (with-auth (instance ,class-view-s "resume-view") + (with-auth (instance resume-component/view-service "resume-view") (with-resume-database (let ((resume-pkg (make-instance 'resume-pkg)) (user (get-user))) - (setf (,components-s instance) (get-records resume-pkg (make-instance ',component-s :user_id (id user)))))) + (setf (components instance) (get-records resume-pkg + (make-instance ',component-s + :user_id (id user) + :*table "resume.contactinfo_v") + "state_abbr asc, city asc, address asc")))) (sanitize-rest-json instance) - (loop for ,component-s in (,components-s instance) - do (sanitize-json ,component-s)))) - - (defclass ,class-modify-s (,class-view-s) - ((form :initarg :form - :initform nil - :accessor form)) - (:documentation "")) - + (loop for component in (components instance) + do (sanitize-json component)))) + (defun ,func-add-s () - (with-auth (instance ,class-modify-s "resume-modify") - (setf (title instance) (format nil "~a - Add" ,component)) - (setf (form instance) (make-form ,form-add - nil - t - `(,,@input-form-fields - (:label ,(format nil "Add ~a" ,component) :field-type "button" :onclick ,(format nil "on_~a_add_submit_clicked()" ,component-lcase))))))) - - (defun ,func-add-submit-s (,arg-names) - (declare (special ,arg-names)) - (with-auth (instance ,class-modify-s "resume-modify") + (with-auth (instance resume-component/modify-service "resume-modify") + (with-resume-database + (let ((resume-pkg (make-instance 'resume-pkg))) + (setf (title instance) (format nil "~a - Add" ,component)) + (setf (form instance) (make-form ,form-add + nil + t + ,input-add-fields)))))) + + (defun ,func-add-submit-s (,@arg-names) + (declare (special ,@arg-names)) + (with-auth (instance resume-component/modify-service "resume-modify") (with-resume-database (handler-case (let* ((resume-pkg (make-instance 'resume-pkg)) @@ -727,51 +771,40 @@ inserted into the add and modify forms." (error (e) (setf (session-value :errormsg) (format nil "Error creating ~a. ~a" ,component e))))))) - (defun ,func-modify-s (id) - (with-auth (instance ,class-modify-s "resume-modify") - (setf (title instance) (format nil "~a - Modify" ,component)) - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (,compnent-s (get-record resume-pkg (make-instance ',component-s :id id :user_id (id user))))) - (if ,component-s - (setf (form instance) (make-form (,form-modify - nil - t - `((:name "id" :field-type "hidden" :value ,(id ,component-s) :required "required") - ,@input-form-fields - (:label ,(format nil "Modify ~a" ,component) :field-type "button" :onclick ,(format nil "on_~a_add_submit_clicked()" ,component-lcase))))) - (setf (session-value :errormsg) (format nil "Error: could not modify ~a. Not found." ,component))))))) - - (defun ,func-modify-submit-s (,(append '(id) arg-names)) - (declare (special ,(append '(id) arg-names)) - (with-auth (instance ,class-modify-s "resume-modify") - (setf (title instance) (format nil "~a - Modify" ,component)) - (with-resume-database - (handler-case - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (,compnent-s (get-record resume-pkg (make-instance ',component-s :id id :user_id (id user))))) - (loop for param in (remove-if (lambda (x) - (intersection `(,x) '(id))) - (sb-introspect:function-lambda-list #',func-modify-submit-s)) - do (setf (slot-value ,component-s param) (symbol-value param))) - (update-record resume-pkg ,component-s) - (setf (session-value :message) (format nil "~a modified successfully." ,component))) - (error (e) - (setf (session-value :errormsg) (format nil "Error modifying ~a. ~a" ,component e)))))))) - - (defun ,func-delete-s (id) - (with-auth (instance ,class-modify-s "resume-modify") - (with-resume-database - (let* ((resume-pkg (make-instance 'resume-pkg)) - (user (get-user)) - (,compnent-s (get-record resume-pkg (make-instance ',component-s :id id :user_id (id user))))) - (if ,component-s - (progn - (delete-record resume-pkg ,component-s) - (setf (session-value :message) (format nil "~a deleted successfully." ,componen))) - (setf (session-value :errormsg) (format nil "Error: could not delete ~a: not found." ,component))))))))))) - -(define-resume-component ('contactinfo '((address :parameter-type 'string) (city :parameter-type 'string) (state_id :parameter-type 'integer) (phone :parameter-type 'string) (email :parameter-type 'string) (visastatus_id :parameter-type 'integer))) - input-form-fields) + ;; (defun ,func-modify-s () + ;; (,func-modify-s id)) + + ;; (defun ,func-modify-submit-s () + ;; (,func-modify-submit-s ,@(append '(id) arg-names))) + + ;; (defun ,func-delete-s () + ;; (,func-delete-s id)) + + (define-endpoint (,(format nil "/resume/~a" component-lcase) :method :get) () ,func-root-s) + (define-endpoint (,(format nil "/resume/~a/view" component-lcase) :method :get) () ,func-view-s) + (define-endpoint (,(format nil "/resume/~a/add" component-lcase) :method :post) () ,func-add-s) + (define-endpoint (,(format nil "/resume/~a/add/submit" component-lcase) :method :post) (&post ,@rest-args) ,func-add-submit-s ,@arg-names) + ;; (define-endpoint (,(format nil "/resume/~a/modify" component-lcase) :method :post) (&post (id :parameter-type 'integer)) ,func-modify-s) + ;; (define-endpoint (,(format nil "/resume/~a/modify/submit" component-lcase) :method :post) (&post (id :parameter-type 'integer) ,@rest-args) ,func-modify-submit-s) + ;; (define-endpoint (,(format nil "/resume/~a/delete/:id" component-lcase) :method :delete) (&path (id 'integer)) ,func-delete-s) + ))) + +(define-resume-component (contactinfo + ((address :parameter-type 'string) (city :parameter-type 'string) (state_id :parameter-type 'integer) (phone :parameter-type 'string) (email :parameter-type 'string) (url :parameter-type 'string) (visastatus_id :parameter-type 'integer)) + `((:name "address" :label "Address" :field-type "text" :required "required") + (:name "city" :label "City" :field-type "text" :required "required") + (:name "state_id" :label "State" :field-type "select" :options ,(state-options (get-records resume-pkg (make-instance 'states) "abbr asc")) :required "required") + (:name "phone" :label "Phone" :field-type "text" :required "required") + (:name "email" :label "Email" :field-type "text" :required "required") + (:name "url" :label "URL" :field-type "text") + (:name "visastatus_id" :label "VISA Status" :field-type "select" :options ,(visastatus-options (get-records resume-pkg (make-instance 'visastatus) "visastatus asc")) :required "required") + (:label "Add CONTACTINFO" :field-type "button" :onclick "on_contactinfo_add_submit_clicked()")) + `((:name "address" :label "Address" :field-type "text" :value ,(address contactinfo) :required "required") + (:name "city" :label "City" :field-type "text" :value ,(city contactinfo) :required "required") + ;;(:name "state_id" :label "State" :field-type "select" :value ,(state_id contactinfo) :options ,(state-options states) :required "required") + (:name "phone" :label "Phone" :field-type "text" :value ,(phone contactinfo) :required "required") + (:name "email" :label "Email" :field-type "text" :value ,(email contactinfo) :required "required") + (:name "url" :label "URL" :field-type "text" :value ,(url contactinfo)) + ;;(:name "visastatus_id" :label "VISA Status" :field-type "select" :value (visastatus_id contactinfo-v) :options (visastatus-options visastatuses) :required "required")) + ))) + diff --git a/lisp/sql/contactinfo.lisp b/lisp/sql/contactinfo.lisp index efaed37..353a78d 100644 --- a/lisp/sql/contactinfo.lisp +++ b/lisp/sql/contactinfo.lisp @@ -25,15 +25,13 @@ (email :initarg :email :initform nil :accessor email) + (url :initarg :url + :initform nil + :accessor url) (visastatus_id :initarg :visastatus_id :initform nil :accessor visastatus_id) - (*table :initform "resume.contactinfo") - (*where-expression :initform "id = ~a")) - (:documentation "Holds the data for a resume.contactinfo record.")) - -(defclass contactinfo-v (contactinfo) - ((state_name :initarg :state_name + (state_name :initarg :state_name :initform nil :accessor state_name) (state_abbr :initarg :state_abbr @@ -42,6 +40,6 @@ (visastatus :initarg :visastatus :initform nil :accessor visastatus) - (*table :initform "resume.contactinfo_v") + (*table :initform "resume.contactinfo") (*where-expression :initform "id = ~a")) - (:documentation "Holds the data for a resume.contactinfo_v record.")) + (:documentation "Holds the data for a resume.contactinfo record.")) diff --git a/lisp/webapps/resume/clojurescript/resume/src/core.cljs b/lisp/webapps/resume/clojurescript/resume/src/core.cljs index 6f21e53..0e9d9f8 100644 --- a/lisp/webapps/resume/clojurescript/resume/src/core.cljs +++ b/lisp/webapps/resume/clojurescript/resume/src/core.cljs @@ -1337,7 +1337,7 @@ [:th {:scope "col"} "Mod"] [:th {:scope "col"} "Del"]]] [:tbody - (for [contactinfo (get jsonobj "contactinfos")] + (for [contactinfo (get jsonobj "components")] [:tr [:td (get contactinfo "address")] [:td (get contactinfo "city")] diff --git a/lisp/webapps/resume/site.lisp b/lisp/webapps/resume/site.lisp index a8af2d6..8ebce16 100644 --- a/lisp/webapps/resume/site.lisp +++ b/lisp/webapps/resume/site.lisp @@ -3,29 +3,6 @@ (in-package :resume) -(defmacro .base (&optional (start-url "/home")) - `(org-ckons-http::html5 - `(html - (head - ((meta :name "viewport" :content "width=device-width, initial-scale=1, shrink-to-fit=no")) - ((meta :charset "utf-8")) - ((title) ,(title *webapp*)) - ,@(mapcar (lambda (css) - `((link :rel "stylesheet" :href ,(getf css :href) :integrity ,(getf css :integrity) :crossorigin ,(getf css :crossorigin)))) - '((:href "https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" :integrity "sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" :crossorigin "anonymous") - (:href "/static/css/stylesheet.css" :crossorigin "anonymous"))) - ,@(mapcar (lambda (js) - `((script :type "text/javascript" :src ,(getf js :src) :integrity ,(getf js :integrity) :crossorigin ,(getf js :crossorigin)))) - '((:src "https://code.jquery.com/jquery-3.7.1.slim.min.js" :integrity "sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8=" :crossorigin "anonymous"))) - ((script :type "text/javascript" :src "/cljs-out/dev-main.js"))) - ((body :onload ,(format nil "resume.core.start(~a)" ,(if start-url - (format nil "'~a'" start-url) - "null"))) - ((div :id "app")) - ,@(mapcar (lambda (js) - `((script :type "text/javascript" :src ,(getf js :src) :integrity ,(getf js :integrity) :crossorigin ,(getf js :crossorigin)))) - '((:src "https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" :integrity "sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" :crossorigin "anonymous"))))))) - (defmacro .location () `(location-json location)) @@ -152,91 +129,90 @@ (defmacro .resume-delete () `(resume-delete-json id)) -(defmacro .contactinfo () - `(contactinfo-json)) +;; (defmacro .contactinfo () +;; `(contactinfo-json)) -(defmacro .contactinfo-view () - `(contactinfo-view-json)) +;; (defmacro .contactinfo-view () +;; `(contactinfo-view-json)) -(defmacro .contactinfo-add () - `(contactinfo-add-json)) +;; (defmacro .contactinfo-add () +;; `(contactinfo-add-json)) -(defmacro .contactinfo-add-submit () - `(contactinfo-add-submit-json address city state_id phone email visastatus_id)) +;; (defmacro .contactinfo-add-submit () +;; `(contactinfo-add-submit-json address city state_id phone email visastatus_id)) -(defmacro .contactinfo-modify () - `(contactinfo-modify-json id)) +;; (defmacro .contactinfo-modify () +;; `(contactinfo-modify-json id)) -(defmacro .contactinfo-modify-submit () - `(contactinfo-modify-submit-json id address city state_id phone email visastatus_id)) +;; (defmacro .contactinfo-modify-submit () +;; `(contactinfo-modify-submit-json id address city state_id phone email visastatus_id)) -(defmacro .contactinfo-delete () - `(contactinfo-delete-json id)) +;; (defmacro .contactinfo-delete () +;; `(contactinfo-delete-json id)) -(defmacro .education () - `(education-json)) +;; (defmacro .education () +;; `(education-json)) -(defmacro .education-view () - `(education-view-json)) +;; (defmacro .education-view () +;; `(education-view-json)) -(defmacro .education-add () - `(education-add-json)) +;; (defmacro .education-add () +;; `(education-add-json)) -(defmacro .education-add-submit () - `(education-add-submit-json school major minor degree progress start_date end_date)) +;; (defmacro .education-add-submit () +;; `(education-add-submit-json school major minor degree progress start_date end_date)) -(defmacro .education-modify () - `(education-modify-json id)) +;; (defmacro .education-modify () +;; `(education-modify-json id)) -(defmacro .education-modify-submit () - `(education-modify-submit-json id school major minor degree progress start_date end_date)) +;; (defmacro .education-modify-submit () +;; `(education-modify-submit-json id school major minor degree progress start_date end_date)) -(defmacro .education-delete () - `(education-delete-json id)) +;; (defmacro .education-delete () +;; `(education-delete-json id)) -(defmacro .language () - `(language-json)) +;; (defmacro .language () +;; `(language-json)) -(defmacro .language-view () - `(language-view-json)) +;; (defmacro .language-view () +;; `(language-view-json)) -(defmacro .language-add () - `(language-add-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-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 () +;; `(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-modify-submit () +;; `(language-modify-submit-json id name understanding_listening understanding_reading speaking_interaction speaking_production writing)) -(defmacro .language-delete () - `(language-delete-json id)) +;; (defmacro .language-delete () +;; `(language-delete-json id)) -(defmacro .skill () - `(skill-json)) +;; (defmacro .skill () +;; `(skill-json)) -(defmacro .skill-view () - `(skill-view-json)) +;; (defmacro .skill-view () +;; `(skill-view-json)) -(defmacro .skill-add () - `(skill-add-json)) +;; (defmacro .skill-add () +;; `(skill-add-json)) -(defmacro .skill-add-submit () - `(skill-add-submit-json skill)) +;; (defmacro .skill-add-submit () +;; `(skill-add-submit-json skill)) -(defmacro .skill-modify () - `(skill-modify-json id)) +;; (defmacro .skill-modify () +;; `(skill-modify-json id)) -(defmacro .skill-modify-submit () - `(skill-modify-submit-json id skill)) +;; (defmacro .skill-modify-submit () +;; `(skill-modify-submit-json id skill)) -(defmacro .skill-delete () - `(skill-delete-json id)) +;; (defmacro .skill-delete () +;; `(skill-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) (define-endpoint ("/home" :method :post) (&post (message :parameter-type 'string) (errormsg :parameter-type 'string)) .home-post) @@ -265,7 +241,7 @@ (define-endpoint ("/users/view" :method :get) () .users-view) (define-endpoint ("/users/add" :method :post) () .users-add) (define-endpoint ("/users/add/submit" :method :post) (&post (role_groups :parameter-type 'string) (first_name :parameter-type 'string) (last_name :parameter-type 'string) (email :parameter-type 'string)) .users-add-submit) -(define-endpoint ("/register/:hash" :method :get) (&path (hash 'string)) .base (format nil "/register/~a" hash)) +(define-endpoint ("/register/:hash" :method :get) (&path (hash 'string)) base (format nil "/register/~a" hash)) (define-endpoint ("/users/register" :method :post) (&post (hash :parameter-type 'string)) .users-register) (define-endpoint ("/users/register/form" :method :post) (&post (hash :parameter-type 'string)) .users-register-form) (define-endpoint ("/users/register/submit" :method :post) (&post (hash :parameter-type 'string) (username :parameter-type 'string) (pwd :parameter-type 'string) (pwd2 :parameter-type 'string) (phone :parameter-type 'string)) .users-register-submit) @@ -280,31 +256,31 @@ (define-endpoint ("/resume/modify" :method :post) (&post (id :parameter-type 'integer)) .resume-modify) (define-endpoint ("/resume/modify/submit" :method :post) (&post (id :parameter-type 'integer) (name :parameter-type 'string)) .resume-modify-submit) (define-endpoint ("/resume/delete/:id" :method :delete) (&path (id 'integer)) .resume-delete) -(define-endpoint ("/resume/contactinfo" :method :get) () .contactinfo) -(define-endpoint ("/resume/contactinfo/view" :method :get) () .contactinfo-view) -(define-endpoint ("/resume/contactinfo/add" :method :post) () .contactinfo-add) -(define-endpoint ("/resume/contactinfo/add/submit" :method :post) (&post (address :parameter-type 'string) (city :parameter-type 'string) (state_id :parameter-type 'integer) (phone :parameter-type 'string) (email :parameter-type 'string) (visastatus_id :parameter-type 'integer)) .contactinfo-add-submit) -(define-endpoint ("/resume/contactinfo/modify" :method :post) (&post (id :parameter-type 'integer)) .contactinfo-modify) -(define-endpoint ("/resume/contactinfo/modify/submit" :method :post) (&post (id :parameter-type 'integer) (address :parameter-type 'string) (city :parameter-type 'string) (state_id :parameter-type 'integer) (phone :parameter-type 'string) (email :parameter-type 'string) (visastatus_id :parameter-type 'integer)) .contactinfo-modify-submit) -(define-endpoint ("/resume/contactinfo/delete/:id" :method :delete) (&path (id 'integer)) .contactinfo-delete) -(define-endpoint ("/resume/education" :method :get) () .education) -(define-endpoint ("/resume/education/view" :method :get) () .education-view) -(define-endpoint ("/resume/education/add" :method :post) () .education-add) -(define-endpoint ("/resume/education/add/submit" :method :post) (&post (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-add-submit) -(define-endpoint ("/resume/education/modify" :method :post) (&post (id :parameter-type 'integer)) .education-modify) -(define-endpoint ("/resume/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 ("/resume/education/delete/:id" :method :delete) (&path (id 'integer)) .education-delete) -(define-endpoint ("/resume/language" :method :get) () .language) -(define-endpoint ("/resume/language/view" :method :get) () .language-view) -(define-endpoint ("/resume/language/add" :method :post) () .language-add) -(define-endpoint ("/resume/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 ("/resume/language/modify" :method :post) (&post (id :parameter-type 'integer)) .language-modify) -(define-endpoint ("/resume/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 ("/resume/language/delete/:id" :method :delete) (&path (id 'integer)) .language-delete) -(define-endpoint ("/resume/skill" :method :get) () .skill) -(define-endpoint ("/resume/skill/view" :method :get) () .skill-view) -(define-endpoint ("/resume/skill/add" :method :post) () .skill-add) -(define-endpoint ("/resume/skill/add/submit" :method :post) (&post (skill :parameter-type 'string)) .skill-add-submit) -(define-endpoint ("/resume/skill/modify" :method :post) (&post (id :parameter-type 'integer)) .skill-modify) -(define-endpoint ("/resume/skill/modify/submit" :method :post) (&post (id :parameter-type 'integer) (skill :parameter-type 'string)) .skill-modify-submit) -(define-endpoint ("/resume/skill/delete/:id" :method :delete) (&path (id 'integer)) .skill-delete) +;; (define-endpoint ("/resume/contactinfo" :method :get) () .contactinfo) +;; (define-endpoint ("/resume/contactinfo/view" :method :get) () .contactinfo-view) +;; (define-endpoint ("/resume/contactinfo/add" :method :post) () .contactinfo-add) +;; (define-endpoint ("/resume/contactinfo/add/submit" :method :post) (&post (address :parameter-type 'string) (city :parameter-type 'string) (state_id :parameter-type 'integer) (phone :parameter-type 'string) (email :parameter-type 'string) (visastatus_id :parameter-type 'integer)) .contactinfo-add-submit) +;; (define-endpoint ("/resume/contactinfo/modify" :method :post) (&post (id :parameter-type 'integer)) .contactinfo-modify) +;; (define-endpoint ("/resume/contactinfo/modify/submit" :method :post) (&post (id :parameter-type 'integer) (address :parameter-type 'string) (city :parameter-type 'string) (state_id :parameter-type 'integer) (phone :parameter-type 'string) (email :parameter-type 'string) (visastatus_id :parameter-type 'integer)) .contactinfo-modify-submit) +;; (define-endpoint ("/resume/contactinfo/delete/:id" :method :delete) (&path (id 'integer)) .contactinfo-delete) +;; (define-endpoint ("/resume/education" :method :get) () .education) +;; (define-endpoint ("/resume/education/view" :method :get) () .education-view) +;; (define-endpoint ("/resume/education/add" :method :post) () .education-add) +;; (define-endpoint ("/resume/education/add/submit" :method :post) (&post (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-add-submit) +;; (define-endpoint ("/resume/education/modify" :method :post) (&post (id :parameter-type 'integer)) .education-modify) +;; (define-endpoint ("/resume/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 ("/resume/education/delete/:id" :method :delete) (&path (id 'integer)) .education-delete) +;; (define-endpoint ("/resume/language" :method :get) () .language) +;; (define-endpoint ("/resume/language/view" :method :get) () .language-view) +;; (define-endpoint ("/resume/language/add" :method :post) () .language-add) +;; (define-endpoint ("/resume/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 ("/resume/language/modify" :method :post) (&post (id :parameter-type 'integer)) .language-modify) +;; (define-endpoint ("/resume/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 ("/resume/language/delete/:id" :method :delete) (&path (id 'integer)) .language-delete) +;; (define-endpoint ("/resume/skill" :method :get) () .skill) +;; (define-endpoint ("/resume/skill/view" :method :get) () .skill-view) +;; (define-endpoint ("/resume/skill/add" :method :post) () .skill-add) +;; (define-endpoint ("/resume/skill/add/submit" :method :post) (&post (skill :parameter-type 'string)) .skill-add-submit) +;; (define-endpoint ("/resume/skill/modify" :method :post) (&post (id :parameter-type 'integer)) .skill-modify) +;; (define-endpoint ("/resume/skill/modify/submit" :method :post) (&post (id :parameter-type 'integer) (skill :parameter-type 'string)) .skill-modify-submit) +;; (define-endpoint ("/resume/skill/delete/:id" :method :delete) (&path (id 'integer)) .skill-delete) diff --git a/lisp/webapps/webapp-loader.lisp b/lisp/webapps/webapp-loader.lisp index 41a00da..1fb7d2e 100644 --- a/lisp/webapps/webapp-loader.lisp +++ b/lisp/webapps/webapp-loader.lisp @@ -3,175 +3,3 @@ (in-package :resume) -(defvar *acceptor* nil) -(defvar *dispatch-table* '(#'dispatch-easy-handlers #'default-dispatcher)) -(defvar *webapps* (make-hash-table :test 'equal)) -(defvar *webapp* nil) -(defvar *uri* nil) -(defvar *header-register* nil) -(defvar *sessionid* nil) -(defparameter *port* 3014) -(defparameter *server-root* (namestring (asdf:system-relative-pathname (intern (package-name #.*package*)) "./")) - "The location of the web server root on the filesystem.") - -(defclass webapp () - ((name :initarg :name - :initform nil - :accessor name - :documentation "The name of the webapp as used in the code. A -string used as the key to any webapp config lookup.") - (scheme :initarg :scheme - :initform nil - :accessor scheme) - (url :initarg :url - :initform nil - :accessor url - :documentation "The domain portion of the URL to the -root of the webapp.") - (document-root :initarg :document-root - :initform nil - :accessor document-root - :documentation "The absolute filesystem path to the -webapp's top-level directory which is inside the webapps folder.") - (title :initarg :title - :initform nil - :accessor title - :documentation "The default title that shows up in -the browser title bar.") - (meta-description :initarg :meta-description - :initform nil - :accessor meta-description - :documentation "The text that goes into the META DESCRIPTION -tag, and anywhere else we want to put this text so that it will show -up in Google.") - (databases :initarg :databases - :initform nil - :accessor databases) - (mail-mx :initarg :mail-mx - :initform nil - :accessor mail-mx) - (mail-from :initarg :mail-from - :initform nil - :accessor mail-from) - (mail-postmaster :initarg :mail-postmaster - :initform nil - :accessor mail-postmaster) - (mail-webmaster :initarg :mail-webmaster - :initform nil - :accessor mail-webmaster) - (mail-info :initarg :mail-info - :initform nil - :accessor mail-info) - (mail-login-notify :initarg :mail-login-notify - :initform nil - :accessor mail-login-notify) - (mail-authentication :initarg :mail-authentication - :initform nil - :accessor mail-authentication) - (mail-ssl :initarg :mail-ssl - :initform nil - :accessor mail-ssl)) - (:documentation "")) - -(defmethod get-site-file-path ((webapp webapp)) - (format nil "~a/site" (document-root webapp))) - -(defmethod get-pages-file-paths ((webapp webapp)) - (mapcar (lambda (pages-file) - (ppcre:regex-replace-all "\\.lisp$" (format nil "~a" pages-file) "")) - (remove-if (lambda (x) (equal x "shared")) - (org-ckons-core::shell-wrapper (format nil "find '~a' -maxdepth 1 -type f -iname 'pages*.lisp' |sort" (document-root webapp)))))) - -(defun make-server-path (relative-path) - "Makes a relative filesystem path into a full one, using -`*server-root*' as the base." - (make-document-root-path *server-root* relative-path)) - -(defun make-document-root-path (document-root relative-path) - "Makes a relative filesystem path into a full one, using -`document-root' as the base." - (concatenate 'string document-root relative-path)) - -(defun make-webapp-path (relative-path) - "Makes an absolute filesystem path to a location in the webapps -folder." - (concatenate 'string *server-root* "webapps/" relative-path)) - -(defun get-options-files () - (mapcar (lambda (webapp-directory) - (format nil "~a/conf/options.lisp" webapp-directory)) - (remove-if (lambda (x) (or (org-ckons-core::match-it "webapps/$" x) - (org-ckons-core::match-it "webapps/shared$" x) - (org-ckons-core::match-it "webapps/CVS$" x) - (org-ckons-core::match-it "webapps/\\.$" x) - (org-ckons-core::match-it "webapps/\\.\\.$" x))) - (org-ckons-core::shell-wrapper (format nil "find '~a' -maxdepth 1 -type d |sort" (make-webapp-path "")))))) - -(defun set-webapp (webapp) - "Sets a `webapp' object in `*webapps*'. The lookup key is the webapp -name. If a webapp already exists under this key, it gets overwritten -with the new one." - (setf (gethash (name webapp) *webapps*) webapp)) - -(defun get-webapp (key) - "Gets the webapp object stored under the key `key'." - (gethash key *webapps*)) - -(defun populate-webapps () - (loop for options-file in (get-options-files) - do (with-open-file (input options-file :direction :input) - (let* ((form (read input))) - (set-webapp (make-instance 'webapp - :name (getf form :name) - :scheme (getf form :scheme) - :url (getf form :url) - :document-root (make-webapp-path (getf form :document-root)) - :title (getf form :title) - :meta-description (getf form :meta-description) - :databases (getf form :databases) - :mail-mx (getf form :mail-mx) - :mail-from (getf form :mail-from) - :mail-postmaster (getf form :mail-postmaster) - :mail-webmaster (getf form :mail-webmaster) - :mail-info (getf form :mail-info) - :mail-login-notify (getf form :mail-login-notify) - :mail-authentication (getf form :mail-authentication) - :mail-ssl (getf form :mail-ssl))))))) - -(defun resume () - "Call this to start the server." - (when (null *acceptor*) - (let ((package (string-downcase (package-name #.*package*)))) - (populate-webapps) - (setf (log-manager) (make-instance 'log-manager :message-class 'formatted-message)) - (start-messenger 'text-file-messenger :filename (format nil "/var/log/lisp/~a.log" package)) - (setf *session-secret* (org-ckons-session::generate-sessionid)) - (populate-webapps) - (setf *acceptor* (start (make-instance 'easy-routes:easy-routes-acceptor - :port *port* - :document-root (make-server-path (format nil "webapps/~a/" package)) - :name (format nil "~a-acceptor" package))))))) - -(defmacro with-request-wrapper (uri page-function &rest args) - (let ((package (string-downcase (package-name #.*package*)))) - `(let (output) - (let* ((*webapp* (get-webapp ,package)) - (*uri* ,uri) - (*header-register* (make-instance 'org-ckons-session::header-register)) - (*sessionid* (ensure-user-session-exists))) - (ensure-user-exists) - (setf output (,page-function ,@args)) - (org-ckons-session::ship-headers *header-register*)) - output))) - -(defmacro define-endpoint (template-and-options var-list page-function &rest args) - "Does the grunt work of creating an `easy-routes' route for each page -you wish to publish." - (let ((name (gensym)) - (uri (first template-and-options)) - (method (getf (rest template-and-options) :method))) - `(progn - (org-ckons-core::logger (format nil "Publishing page. URL = [~a], method = [~a]" ,uri ,method)) - (easy-routes:defroute ,name ,template-and-options - ,var-list - (with-request-wrapper ,uri ,page-function ,@args))))) diff --git a/sql/tables/resume.contactinfo.sql b/sql/tables/resume.contactinfo.sql index 8523270..7a89fb7 100644 --- a/sql/tables/resume.contactinfo.sql +++ b/sql/tables/resume.contactinfo.sql @@ -8,5 +8,6 @@ create table resume.contactinfo ( state_id bigint not null references resume.states(id), phone character varying(255) not null, email character varying(255) not null, + url character varying(255) not null, visastatus_id bigint not null references resume.visastatus(id) ); diff --git a/sql/views/resume.contactinfo_v.sql b/sql/views/resume.contactinfo_v.sql index 4c4eb79..65f992b 100644 --- a/sql/views/resume.contactinfo_v.sql +++ b/sql/views/resume.contactinfo_v.sql @@ -10,6 +10,7 @@ select c.id, s.abbr as state_abbr, c.phone, c.email, + c.url, c.visastatus_id, v.status as visastatus from resume.contactinfo c -- cgit v1.3