]> git.plutz.net Git - lobster/commitdiff
merge from confetti
authorPaul Hänsch <paul@plutz.net>
Sat, 6 Feb 2021 22:40:32 +0000 (23:40 +0100)
committerPaul Hänsch <paul@plutz.net>
Sat, 6 Feb 2021 22:40:32 +0000 (23:40 +0100)
21 files changed:
cards/edit_card.sh
cards/index.cgi
cards/l10n.sh
cards/list.sh
cards/update_card.sh
cards/widgets.sh
index.cgi
pdiread.sh
therapies/autosave.js [new file with mode: 0644]
therapies/index.cgi [new file with mode: 0755]
therapies/l10n.sh [new file with mode: 0755]
therapies/page.sh [new file with mode: 0755]
therapies/therapy.css [moved from therapy/therapy.css with 90% similarity]
therapies/therapy_background.png [moved from therapy/therapy_background.png with 100% similarity]
therapies/therapy_background.xcf [moved from therapy/therapy_background.xcf with 100% similarity]
therapies/therapy_draw.js [moved from therapy/therapy_draw.js with 87% similarity]
therapies/update_therapy.sh [new file with mode: 0755]
therapy/text_therapy.sh [deleted file]
therapy/therapy.html.sh [deleted file]
therapy/therapy.sh [deleted file]
therapy/update_therapy.sh [deleted file]

index 4239cc5968c03b5e58d11a96d0e0ae22f68de41f..16d759999893c539a5884390ccc147a68772192b 100755 (executable)
@@ -26,11 +26,11 @@ filter="$(REF f)"
 order="$(REF o)"
 
 if tempfile="$(SLOCK "$cardfile" "$locktimeout")"; then
-  REDIRECT "/cards/?o=${order}&f=${filter}&e=${card}"
+  REDIRECT "/cards/?o=${order}&f=${filter}&e=${card#/}"
 elif [ -f "$tempfile" ]; then
   SET_COOKIE session message="SESSLOCK"
-  REDIRECT "/cards/?o=${order}&f=${filter}#${card}"
+  REDIRECT "/cards/?o=${order}&f=${filter}#${card#/}"
 else
   SET_COOKIE session message="EDITLOCK"
-  REDIRECT "/cards/?o=${order}&f=${filter}#${card}"
+  REDIRECT "/cards/?o=${order}&f=${filter}#${card#/}"
 fi
index 934c19ac3bf2499b3aee9adf0440188739a6e3f2..0bb4f827c26cf53b7c934039d5260f3a88abe739 100755 (executable)
@@ -11,15 +11,20 @@ filter="$(GET f)"
 order="$(GET o)"
 edit="$(GET e |PATH)"
 
-[ "$order" ] || order=firstname
+[ "$order" ] || order=lastname
 edit="${edit##*/}"
 
+list_hi_companies(){
+  sed -rn 's;^X-HEALTH-INSURANCE:([^\;]+)\;.*$;\1;p' ${_DATA}/vcard/*vcf \
+  | sort -u
+}
+
 { w_filter_diag
   printf '
   [form class="newcard" action="/cards/new_card.sh" method="POST"
+    [a href="#top" . %s]
     [button type="submit" %s]
-    [input name="seed" placeholder="%s"]
-  ]' "$(l10n newcard)" "$(l10n vcf_seed_label)"
+  ]' "$(l10n top)" "$(l10n newcard)"
   [ "$edit" ] && edit_card "$edit"
   list_cards
 } | yield_page cards #/cards/cards.css
index 2d9dc06362d250a5719f378aa0e9ef8a61867bee..f991e4fddb901c95fa7ed02039c691075a5e6632 100755 (executable)
@@ -32,6 +32,8 @@ l10n(){
     prescriptions) printf %s "Verord&shy;nungen";;
     new_prescription) printf %s "Neue Verord&shy;nung";;
     no_icd) printf %s "Kein ICD Code";;
+    therapy) printf %s "Therapie";;
+    therapies) printf %s "Therapien";;
   
     X-ZACK-JOINDATE)  printf %s "Anmelde&shy;datum";;
     X-ZACK-LEAVEDATE) printf %s "Abmelde&shy;datum";;
index cd0d21f1e320aa958839b8fdbe75dec051286da9..03fa97340bd546d83cdccc36f35b9c2ed90401ab 100755 (executable)
@@ -13,47 +13,26 @@ edit_card(){
   else
     card="$(pdi_load "$tempfile")"
     cat <<-EOF
-       [form .card #${cardfile##*/} action="/cards/update_card.sh" method="POST"
+       [span .card-anchor #${cardfile##*/}]
+       [form .card action="/cards/update_card.sh" method="POST"
          [input type="hidden" name="tid" value="$(transid ${tempfile})"]
          [div .section .basic $(
            edit_item "$card" N GENDER
            [ "$(pdi_count "$card" NICKNAME)" -gt 0 ] \
            && edit_item "$card" NICKNAME
            edit_item "$card" BDAY
-           edit_item "$card" X-ZACK-JOINDATE
-           [ "$(pdi_count "$card" X-ZACK-LEAVEDATE)" -gt 0 ] \
-           && edit_item "$card" X-ZACK-LEAVEDATE
            card_item "$card" SOUND PHOTO LOGO
          )]
-         [div .section .phone   $(edit_item "$card" TEL)]
-         [div .section .message $(
-           edit_item "$card" EMAIL
-           [ $(pdi_count "$card" IMPP) -gt 0 ] && edit_item "$card" IMPP
-           [ $(pdi_count "$card" URL ) -gt 0 ] && edit_item "$card" URL
-         )]
+         [div .section .phone   $(
+            edit_item "$card" TEL EMAIL
+           [ $(pdi_count "$card" IMPP) -gt 0 ] \
+            && edit_item "$card" IMPP
+           [ $(pdi_count "$card" URL ) -gt 0 ] \
+            && edit_item "$card" URL
+          )]
          [div .section .address $(edit_item "$card" ADR)]
-         [div .section .note    $(edit_item "$card" NOTE)]
-         [div .section .attendance
-           [h3 $(l10n course_attendance) ] $(
-           for course in "$_DATA"/ical/*.ics; do
-             printf '[label [input type="checkbox" name="attendance" value="%s" %s] %s]' \
-                    "${course##*/}" \
-                    "$(grep -qF "${course##*/} ${cardfile##*/}" "$_DATA/mappings/attendance" \
-                       && printf 'checked="checked"'
-                      )" \
-                    "$(pdi_value "$(pdi_load "$course")" SUMMARY || l10n "(unnamed course)" |unescape |HTML)"
-           done)
-           [h3 $(l10n CATEGORIES) ] $(
-           grep -xE '[^ ]+' "$_DATA"/mappings/categories |while read -r cat; do
-             printf '[label [input type="checkbox" name="CATEGORIES" value="%s" %s] %s]' \
-                    "$(HTML "$cat")" \
-                    "$(seq 1 $(pdi_count "$card" CATEGORIES) |while read c; do
-                      pdi_value "$card" CATEGORIES $c |grep -qxF "$cat" \
-                      && printf 'checked="checked"' && break
-                    done)" \
-                    "$(HTML "$cat")"
-           done)
-         ]
+         [div .section .insurance $(edit_item "$card" X-HEALTH-INSURANCE)]
+         [div .section .note    $(edit_item "$card" NOTE X-CLIENT-REFERRAL)]
          [div .control
            [div .item .delete label="$(l10n edit_delete)"
               [input type="checkbox" #delete]
@@ -81,23 +60,24 @@ edit_card(){
 print_card(){
   local cardfile="$1"
   local card="$(pdi_load "$cardfile")"
+  local N1 N2 N3 N4 N5
+  IFS=\; read N1 N2 N3 N4 N5 <<-EOF
+       $(pdi_value "$card" N |pdi_unescape |HTML)
+       EOF
+
   cat <<-EOF
     [div .card #${cardfile##*/}
-      [div .section .basic . $(
-        card_item "$card" FN GENDER NICKNAME BDAY X-ZACK-JOINDATE X-ZACK-LEAVEDATE SOUND PHOTO LOGO
+      [div .section .basic
+      [h2 .item .FN . $N4 $N1 $N5]
+      [span .item .firstname . $N2 $N3]
+      $(
+        card_item "$card" GENDER NICKNAME BDAY X-ZACK-JOINDATE X-ZACK-LEAVEDATE SOUND PHOTO LOGO
       )]
-      [div .section .phone   . $(card_item "$card" TEL)]
-      [div .section .message . $(card_item "$card" EMAIL IMPP URL)]
-      [div .section .address . $(card_item "$card" ADR)]
-      [div .section .note    . $(card_item "$card" NOTE)]
-      [div .section .attendance [h3 $(l10n course_attendance) ] [ul
-        $(grep -F "    ${cardfile##*/}" "$_DATA/mappings/attendance" |while read each discard; do
-          printf '[li [a .item .attendance href="/courses#%s" . %s]]' \
-                 "$each" \
-                 "$(pdi_value "$(pdi_load "$_DATA/ical/$each")" SUMMARY || l10n "(unnamed course)" |unescape |HTML)"
-        done)]
-        $(card_item "$card" CATEGORIES)
-      ]
+      [div .section .address   $(card_item "$card" ADR)]
+      [div .section .phone     $(card_item "$card" TEL EMAL IMPP URL)]
+      [div .section .insurance $(card_item "$card" X-HEALTH-INSURANCE)]
+      [div .section .note      $(card_item "$card" NOTE X-CLIENT-REFERRAL)]
+      [div .section .therapies $(card_item "$card" therapies)]
       [div .control
         [a .item href="/cards/edit_card.sh?card=${cardfile##*/}" $(l10n edit)]
         [a .item href="/cards/export_card.sh?card=${cardfile##*/}" $(l10n vcf_export)]
@@ -111,8 +91,6 @@ print_cards(){
 
   while read cardfile; do
     cachefile="${_DATA}/cache/${cardfile##*/}.cache"
-    # if [ -s "$cachefile" -a "$cachefile" -nt "$cardfile" \
-    #                      -a "$cachefile" -nt "${_EXEC}/cards" ]; then
     if [ -s "$cachefile" -a "$cachefile" -nt "$cardfile" ]; then
       cat "$cachefile"
     else
@@ -121,31 +99,6 @@ print_cards(){
   done
 }
 
-filter_attendance(){
-  fatt="$1"
-  attfile="$_DATA/mappings/attendance"
-
-  if [ ! "$fatt" ]; then
-    # debug 'list all'
-    printf '%s\n' "$_DATA/vcard"/*.vcf
-  elif [ "${fatt#* }" = "${fatt}" ]; then
-    # debug "list $fatt"
-    grep -xiE "(${fatt})       .+vcf" "$attfile" \
-    | while read vcf; do
-      printf '%s/vcard/%s\n' "$_DATA" "${vcf##*        }"
-    done
-  else
-    # debug "filter ${fatt%% *}"
-    filter_attendance "${fatt#* }" \
-    | while read vcf; do
-      grep -xiE "(${fatt%% *}) ${vcf##*/}" "$attfile"
-    done \
-    | while read vcf; do
-      printf '%s/vcard/%s\n' "$_DATA" "${vcf##*        }"
-    done
-  fi
-}
-
 filter_cards(){
   local filter f fex='x;p;'
 
@@ -156,11 +109,10 @@ filter_cards(){
 
   while [ "$filter" ]; do
     f="${filter%%^*}" filter="${filter#*^}"
+    debug "Filter: $f"
     case $f in
       '') break
         ;;
-      COURSE:*) fatt="${fatt}${fatt:+ }${f#*:}"
-        ;;
       ANY:*) fex="/\n.*(\;[^:]*)?:[^\n]*(${f#*:})[^\n]*\r?\n/{${fex}}"
         ;;
       NAME:*) fex="/\n(N|FN|NICKNAME)(\;[^:]*)?:[^\n]*(${f#*:})[^\n]*\r?\n/{${fex}}"
@@ -172,12 +124,10 @@ filter_cards(){
     esac
   done
 
-  # for cardfile in "${_DATA}"/vcard/*.vcf; do
-  filter_attendance "$fatt" |while read cardfile; do
-    printf '%s\n' "$cardfile"
-    cat "$cardfile"
+  for cardfile in "${_DATA}"/vcard/*.vcf; do
+    printf '%s\n' "$cardfile" "$(grep -vxE " *${CR}?" "$cardfile")"
   done \
-  | sed -nE ':X; /\nEND\;?:VCARD\r?$/!{ N; bX; }; h; s;\n.*$;;; x; s;^[^\n]+\n;;;
+  | sed -En ':X; /\nEND;?:VCARD\r?$/!{ N; bX; }; h; s;\n.*$;;; x; s;^[^\n]+\n;;;
              '"$upcase""$fex"
 }
 
index d942e9abdbc527aa5ff803bc8c0b4dd501355778..2ee69318c28da5c502d6e89a4c9b6364cebbe9c3 100755 (executable)
@@ -22,7 +22,7 @@
 . "$_EXEC/cgilite/storage.sh"
 
 unset filter order card action newfield
-unset cardfile attfile tempfile
+unset cardfile tempfile
 unset vcf field cnt delete_key
 
 filter="$(REF f)"
@@ -30,7 +30,6 @@ order="$(REF o)"
 
 card="$(POST card |PATH)"; card="${card##*/}"
 cardfile="$_DATA/vcard/${card}"
-attfile="$_DATA/mappings/attendance"
 
 action="$(POST action)"
 newfield="$(POST newfield |grep -m 1 -xE '[A-Z][A-Z0-9-]*')"
@@ -50,17 +49,9 @@ elif [ "$(POST tid)" != "$(transid "$tempfile")" ]; then
   exit 0
 fi
 
-vcf_escape(){
-  for each in "$@"; do
-    printf %s\\n "$each" \
-    | sed -E ':X;$!{N;bX}; s;\r\n;\n;g; s;([;,\\]);\\\1;g; s;\n;\\n;g;'
-  done \
-  | sed -E ':X;$!{N;bX}; s;\n;\;;g'
-}
-
 # [ "${_POST[hi_select]}" = "list" ] || _POST[hi_company]="${_POST[hi_other]}"
 # [ -n "${_POST[hi_company]}${_POST[hi_number]}${_POST[hi_status]}" ] \
-# && _POST[X-HEALTH-INSURANCE]="$(vcf_escape "${_POST[hi_company]}" "${_POST[hi_number]}" "${_POST[hi_status]}")"
+# && _POST[X-HEALTH-INSURANCE]="$(pdi_escape "${_POST[hi_company]}" "${_POST[hi_number]}" "${_POST[hi_status]}")"
 
 vcf="$(pdi_load "$tempfile")"
 
@@ -76,14 +67,28 @@ for field in $(POST_KEYS |grep -xE '[A-Z][A-Z0-9-]*'); do
   for cnt in $(seq 1 $(POST_COUNT "$field")); do
     case "$field" in
       # (TEL)
-      #   printf '%s;TYPE=%s:%s\r\n' "${field}" "${_POST[phonetype${key#TEL}]}" "$(vcf_escape "$(POST "$field" "$cnt")")"
+      #   printf '%s;TYPE=%s:%s\r\n' "${field}" "${_POST[phonetype${key#TEL}]}" "$(pdi_escape "$(POST "$field" "$cnt")")"
       #   ;;
+      X-HEALTH-INSURANCE)
+        hi_select="$(POST "$field" "$cnt")"
+        if [ "$hi_select" = list ]; then
+          vcf="$(pdi_update_value "$vcf" "$field" "$cnt" "$(pdi_escape "$(POST "hi_company" "$cnt")" \
+                                                                       "$(POST "hi_number" "$cnt")" \
+                                                                       "$(POST "hi_status" "$cnt")" \
+                                                          )")"
+        elif [ "$hi_select" = other ]; then
+          vcf="$(pdi_update_value "$vcf" "$field" "$cnt" "$(pdi_escape "$(POST "hi_other" "$cnt")" \
+                                                                       "$(POST "hi_number" "$cnt")" \
+                                                                       "$(POST "hi_status" "$cnt")" \
+                                                          )")"
+        fi
+        ;;
       TEL)
          vcf="$(pdi_update_attrib "$vcf" TEL $cnt TYPE="$(POST teltype $cnt |grep -Exm1 'HOME|WORK|CELL|FAX')")"
-         vcf="$(pdi_update_value "$vcf" "$field" "$cnt" "$(vcf_escape "$(POST "$field" "$cnt")")")"
+         vcf="$(pdi_update_value "$vcf" "$field" "$cnt" "$(pdi_escape "$(POST "$field" "$cnt")")")"
          ;;
       *)
-         vcf="$(pdi_update_value "$vcf" "$field" "$cnt" "$(vcf_escape "$(POST "$field" "$cnt")")")"
+         vcf="$(pdi_update_value "$vcf" "$field" "$cnt" "$(pdi_escape "$(POST "$field" "$cnt")")")"
         ;;
     esac
 done; done
@@ -101,51 +106,26 @@ vcf="$(printf '%s\n' "$vcf" |sed -E "/^[^:]+:delete=${delete_key}\$/d")"
 if [ "$action" = addfield ]; then
   vcf="$(pdi_update_value "$vcf" "$newfield" $(( $(pdi_count "$vcf" "$newfield") + 1 )) '')"
 fi
-printf '%s' "$vcf" |grep -vx '' >"$tempfile"
+printf '%s' "$vcf" | sed -E '/^$/d; s/^([^:]+);:/\1:/;' >"$tempfile"
 
 case "$action" in
   addfield)
-    REDIRECT "/cards/?o=${order}&f=${filter}&e=${card}"
+    REDIRECT "/cards/?o=${order}&f=${filter}&e=${card#/}"
     ;;
   update)
-    if LOCK "$attfile"; then
-      grep -F "        ${card}" "$attfile" |while read course junk; do
-        touch "$_DATA/ical/${course}"
-      done
-      sed -i -E "/^.+  ${card}\$/d" "$attfile"
-      seq 1 $(POST_COUNT attendance) |while read n; do
-        printf '%s     %s\n' "$(POST attendance $n)" "$card"
-      done >>"$attfile"
-      grep -F "        ${card}" "$attfile" |while read course junk; do
-        touch "$_DATA/ical/${course}"
-      done
-      RELEASE "$attfile"
-    else
-      SET_COOKIE 0 message="COULD NOT UPDATE COURSE MAPPINGS"
-    fi
-
     cp "$tempfile" "$cardfile"
     RELEASE_SLOCK "$cardfile"
-    REDIRECT "/cards/?o=${order}&f=${filter}#${card}"
+    REDIRECT "/cards/?o=${order}&f=${filter}#${card#/}"
     ;;
   cancel)
     RELEASE_SLOCK "$cardfile"
     [ -f "$cardfile" ] \
-    && REDIRECT "/cards/?o=${order}&f=${filter}#${card}" \
+    && REDIRECT "/cards/?o=${order}&f=${filter}#${card#/}" \
     || REDIRECT "/cards/?o=${order}&f=${filter}"
     ;;
   delete)
     rm "$cardfile"
     RELEASE_SLOCK "$cardfile"
-    if LOCK "$attfile"; then
-      grep -F "        ${card}" "$attfile" |while read course junk; do
-        touch "$_DATA/ical/${course}"
-      done
-      sed -i -E "/^.+  ${card}\$/d" "$attfile"
-      RELEASE "$attfile"
-    else
-      SET_COOKIE 0 message="COULD NOT UPDATE COURSE MAPPINGS"
-    fi
     REDIRECT "/cards/?o=${order}&f=${filter}"
     ;;
 esac
index c0c05946b1c594272d034a33081e351444873df9..9a71f198c4a9322ef6f465dba321290b5d6cc0f1 100755 (executable)
 # You should have received a copy of the GNU Affero General Public License
 # along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
 
-list_categories() {
-  grep -vxE '^[        ]*$' "${_DATA}/mappings/categories"
-}
-
-list_courses() {
-  local file name cachefile="${_DATA}/cache/courses.ui.cache"
-  if [ $cachefile -nt "${_DATA}/ical" ]; then
-    cat "$cachefile"
-  else
-    for file in "$_DATA/ical"/*.ics; do
-      name="$(pdi_value "$(pdi_load "$file")" SUMMARY |HTML)"
-      printf '%s       %s\n' "$file" "$name"
-    done \
-    | sort -k2 |tee "$cachefile"
-  fi
-}
-
 w_filter_item() {
 n=$3
 cat <<EOF
   [fieldset .item
     [legend $(l10n filter_item):]
 
-    $(for field in any name street zip TEL BDAY CATEGORIES course; do
-      printf '[input id="%s%i" type="radio" name="filter_type%i" value="%s" %s][label for="%s%i" %s ]' \
+    $(for field in any name street zip TEL BDAY; do
+      printf '[input id="%s%i" type="radio" name="filter_type%i" value="%s" %s]
+              [label for="%s%i" %s ]' \
               "$field" "$n" "$n" "$field" "$([ "$1" = "$field" ] && printf checked )" \
               "$field" "$n" "$(l10n filter_$field)"
     done)
-    [input type="text" name="filter_text$n" value="$([ "$1" = CATEGORIES -o "$1" = course ] || HTML "$2")" placeholder="$(l10n filter_placeholder)"]
-    [fieldset .categories
-      $(list_categories | while read cat; do
-          printf '[label [checkbox "filter_cat%i" "|%s" %s] %s ] ' \
-                 "$n" "$(HTML "$cat")" \
-                 "$(printf %s "$cat" |grep -qxEe "$2" && printf checked )" \
-                 "$(HTML "$cat")"
-      done)
-      [a href="/categories/" $(l10n edit_categories)]
-    ]
-    [fieldset .courses
-      $(list_courses | while read course coursename; do
-        printf '[label [checkbox "filter_course%i" "|%s" %s] %s ] ' \
-               "$n" "$(HTML "${course##*/}")" \
-               "$(printf %s "${course##*/}" |grep -qxEe "$2" && printf checked )" \
-               "$coursename"
-      done)
-    ]
+    [input type="text" name="filter_text$n" value="$([ "$1" = CATEGORIES ] || HTML "$2")" placeholder="$(l10n filter_placeholder)"]
   ]
 EOF
 }
@@ -82,8 +49,8 @@ w_filter_diag(){
     [button type="submit" name="choice" value="new_filter" $(l10n filter_more)]
     [fieldset class="order"
       [legend $(l10n filter_order):]
-      [label [radio "order" "firstname" $( [ "$order" = firstname ] && printf checked )] $(l10n filter_firstname)]
       [label [radio "order" "lastname"  $( [ "$order" = lastname  ] && printf checked )] $(l10n filter_lastname)]
+      [label [radio "order" "firstname" $( [ "$order" = firstname ] && printf checked )] $(l10n filter_firstname)]
       [label [radio "order" "bdate"     $( [ "$order" = bdate     ] && printf checked )] $(l10n filter_bdate)]
     ]
     [button type="submit" name="choice" value="filter" $(l10n filter_apply)]
@@ -93,21 +60,6 @@ w_filter_diag(){
 EOF
 }
 
-# listcards |grep ${edit:+-v} "$edit" \
-# | while read card; do
-#   "${_EXEC}"/cgilite/html-sh.sed <<-ENDCARD
-#      [div #${card} .card
-#        $(view_card "$card")[!--
-#        --][div .control
-#          [a "?action=edit_card&card=${card}" .item $(l10n edit)]
-#          [a "?action=export_vcard&card=${card}".item $(l10n vcf_export)]
-#          ${profile_medical:+[a "?action=new_prescription&client=${card}" .item $(l10n new_prescription)]}
-#      ]]
-#      ENDCARD
-# done
-
-#!/bin/sh
-
 card_item(){
   local card="$1"
   local item cnt c
@@ -167,10 +119,42 @@ card_item(){
                     "$(pdi_value "$card" TEL $c |unescape |HTML)"
         done
         ;;
+      X-HEALTH-INSURANCE)
+        [ $cnt -gt 0 ] && printf '[h3 %s]' "$(l10n X-HEALTH-INSURANCE)"
+        seq 1 $cnt |while read c; do
+          IFS=\; read -r hi_name hi_number hi_status <<-EOF
+               $(pdi_value "$card" X-HEALTH-INSURANCE $c)
+               EOF
+          printf '[span .item .hi_company . %s]
+                  [span .item .hi_number [label %s:] %s]
+                  [span .item .hi_status [label %s:] %s]
+                 ' "$(unescape "$hi_name" |HTML)" \
+                   "$(l10n hi_number)" "$(unescape "$hi_number" |HTML)" \
+                   "$(l10n hi_status)" "$(unescape "$hi_status" |HTML)"
+        done
+        ;;
+      therapies)
+        client="$(pdi_value "$card" UID)"
+        printf '[h3 %s]' "$(l10n therapies)"
+        (cd "$_DATA/therapies/"; printf '%s\n' "${client}".*.tpy) \
+        | while read tpyfile; do
+          [ "$tpyfile" = "${client}.*.tpy" ] \
+          && printf '[a .item .therapy href="/therapies/%s/new" . +]' "${client}" \
+          && break
+          tpy="${tpyfile%.tpy}";
+          tpydates="$(sed -En 's;^session[0-9]+_date:;;p;' "$_DATA/therapies/$tpyfile" \
+                      | sort \
+                      | sed -E ':X;N;$!bX; s;^[\n ]+;;; s;[\n ]+$;;; s;(\n.*\n|\n); - ;;'
+                     )"
+          printf '[a .item .therapy href="/therapies/%s" . %s] ' \
+                 "${tpy%.*}/${tpy#*.}" "$(HTML "${tpydates:--}")"
+        done |sort -n
+        ;;
       *)[ $cnt -gt 0 ] && printf '[h3 %s]' "$(l10n "$item")"
+        shy="$(printf '\302\255')"
         seq 1 $cnt |while read c; do
           printf '[span .item .%s . %s]' "$item" \
-                 "$(pdi_value "$card" "$item" $c |unescape |HTML)"
+                 "$(pdi_value "$card" "$item" $c |sed -r "s;(straße|weg|damm|allee|ufer);${shy}\1;g" |unescape |HTML)"
         done
         ;;
     esac
@@ -236,7 +220,7 @@ edit_item(){
           printf '[checkbox "%s_delete_%i" "true" .delete #%s_delete_%i][label for="%s_delete_%i" %s]' \
             "$item" $c "$item" $c "$item" $c "$(l10n delete)"
           printf '<textarea class="item %s" name="%s">%s</textarea>' \
-            "$item" "$item" "$(pdi_value "$card" "$item" $c |unescape |HTML)"
+            "$item" "$item" "$(pdi_value "$card" "$item" $c |pdi_unescape |HTML)"
         done
         printf '[button type="submit" name="action" value="addfield %s" %s ]' "$item" "$(l10n edit_addfield)"
         ;;
@@ -259,16 +243,43 @@ edit_item(){
                   "$([ "$teltype" = 'FAX'  ] && printf 'selected="selected"')" "$(l10n TYPE=FAX)"
 
           printf '[input .item .%s name="%s" value="%s" placeholder="%s"]' \
-            "$item" "$item" "$(pdi_value "$card" "$item" $c |unescape |HTML)" "$(l10n "$item")"
+            "$item" "$item" "$(pdi_value "$card" "$item" $c |pdi_unescape |HTML)" "$(l10n "$item")"
         done
         printf '[button type="submit" name="action" value="addfield %s" %s ]' "$item" "$(l10n edit_addfield)"
         ;;
+      X-HEALTH-INSURANCE)
+        printf '[h3 %s]' "$(l10n "$item")"
+        seq 1 $cnt |while read c; do
+          # printf '[checkbox "%s_delete_%i" "true" .delete #%s_delete_%i][label for="%s_delete_%i" %s]' \
+          #   "$item" $c "$item" $c "$item" $c "$(l10n delete)"
+          IFS=\; read -r hi_name hi_number hi_status <<-EOF
+               $(pdi_value "$card" X-HEALTH-INSURANCE $c)
+               EOF
+          cat <<-EOF
+               [input type="radio" name="$item" value="list" #hi_select_list checked]<!--
+               -->[label for="hi_select_list" $(l10n hi_from_list)]<!--
+               -->[input type="radio" name="$item" value="other" #hi_other checked]<!--
+               -->[label for="hi_other" $(l10n hi_other)]<!--
+               -->[select class="item" name="hi_company"
+                 [option value="" disabled="disabled" $(selected "${hi_name}" "") . $(l10n hi_company)]
+                 $(list_hi_companies |while read f; do
+                   printf '[option value="%s" %s . %s]' "$(pdi_unescape "$f" |HTML)" \
+                                                        "$(selected "$f" "$hi_name")" \
+                                                        "$(pdi_unescape "$f" |HTML)"
+                 done)
+               ]
+               [input type="text" name="hi_other" value="$hi_name" placeholder="$(l10n hi_company)"]
+               [input name="hi_number" value="$(pdi_unescape "$hi_number" |HTML)" placeholder="$(l10n hi_number)"]
+               [input name="hi_status" value="$(pdi_unescape "$hi_status" |HTML)" placeholder="$(l10n hi_status)"]
+               EOF
+        done
+        ;;
       *)printf '[h3 %s]' "$(l10n "$item")"
         seq 1 $cnt |while read c; do
           printf '[checkbox "%s_delete_%i" "true" .delete #%s_delete_%i][label for="%s_delete_%i" %s]' \
             "$item" $c "$item" $c "$item" $c "$(l10n delete)"
           printf '[input .item .%s name="%s" value="%s" placeholder="%s"]' \
-            "$item" "$item" "$(pdi_value "$card" "$item" $c |unescape |HTML)" "$(l10n "$item")"
+            "$item" "$item" "$(pdi_value "$card" "$item" $c |pdi_unescape |HTML)" "$(l10n "$item")"
         done
         printf '[button type="submit" name="action" value="addfield %s" %s ]' "$item" "$(l10n edit_addfield)"
         ;;
index ee0d6f7200900df4e43ba1a2347da90fca72006b..40db42b99eb53288fb2494aa7faac2947ee47acd 100755 (executable)
--- a/index.cgi
+++ b/index.cgi
@@ -23,6 +23,17 @@ debug() {
   fi
 }
 
+debug() {
+  local dbg=/dev/stderr
+  if [ ! "$DEBUG" ]; then
+    [ "$#" -gt 0 ] && : || cat;
+  elif [ "$#" -gt 0 ]; then
+    printf '%s\n' "$@" >>"$dbg"
+  else
+    tee -a "$dbg"
+  fi
+}
+
 . "$_EXEC/cgilite/cgilite.sh"
 . "$_EXEC/cgilite/session.sh"
 
@@ -50,7 +61,7 @@ yield_page() {
   printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
   { printf '
        [html [head
-          [title Confetti]
+          [title Lobster]
          [meta name="viewport" content="width=device-width"]
          [link rel="stylesheet" type="text/css" href="/style.css"]
     '
@@ -74,12 +85,12 @@ topdir="/${topdir%%/*}"
 case ${_PATH} in
   /) REDIRECT /cards/
     ;;
-  /export/*.pdf) . "$_EXEC/cgilite/file.sh"
-    FILE "${_DATA}/${_PATH}" "application/pdf"
-    ;;
-  /export/*) . "$_EXEC/cgilite/file.sh"
-    FILE "${_DATA}/${_PATH}"
-    ;;
+#  /export/*.pdf) . "$_EXEC/cgilite/file.sh"
+#    FILE "${_DATA}/${_PATH}" "application/pdf"
+#    ;;
+#  /export/*) . "$_EXEC/cgilite/file.sh"
+#    FILE "${_DATA}/${_PATH}"
+#    ;;
   *)
     if   [ -d "${_EXEC}/${_PATH}" -a -x "${_EXEC}/${_PATH}/index.cgi" ]; then
       . "${_EXEC}/${_PATH}/index.cgi"
index 08fbaec3fb373c2fbb6cdde7974caaa520b849e3..f547cb689c1857d4397e9d7565cedc4f3ba0000a 100755 (executable)
@@ -113,6 +113,33 @@ pdi_load() {
     p;' "$@"
 }
 
+pdi_escape(){
+  local in out=''
+  for in in "$@"; do
+    out="${out}${out:+;}"
+    while [ "$in" ]; do case $in in
+      \\*) out="${out}\\\\"; in="${in#\\}" ;;
+      ,*) out="${out}\\,"; in="${in#,}" ;;
+      \;*) out="${out}\\;"; in="${in#;}" ;;
+      "$BR"*) out="${out}\\n"; in="${in#${BR}}" ;;
+      *) out="${out}${in%%[\\,;${BR}]*}"; in="${in#"${in%%[\\,;${BR}]*}"}" ;;
+    esac; done
+  done
+  printf '%s\n' "$out"
+}
+
+pdi_unescape(){
+  local in out=''
+  [ $# -gt 0 ] && in="$*" || in="$(cat)"
+  while [ "$in" ]; do case $in in
+    \\\\*) out="${out}\\"; in="${in#\\\\}" ;;
+    \\n*) out="${out}${BR}"; in="${in#\\n}" ;;
+    \\*) in="${in#\\}" ;;
+    *) out="${out}${in%%\\*}"; in="${in#"${in%%\\*}"}" ;;
+  esac; done
+  printf '%s\n' "$out"
+}
+
 pdi_count(){
   local card="$1" name="$2" rc='' cnt=0
   while rc="${card#*${BR}${name};}"; do
diff --git a/therapies/autosave.js b/therapies/autosave.js
new file mode 100644 (file)
index 0000000..665a601
--- /dev/null
@@ -0,0 +1,50 @@
+var button = document.querySelector('#savebutton');
+var formdata_old = '';
+var formdata = '';
+
+function postsubmit(){
+  if ( this.status == 200 ) {
+    document.querySelector('#report input[name="tid"]').setAttribute('value', this.response);
+    console.log('successful auto submit of form data');
+    button.setAttribute('style', 'display: none;');
+  } else {
+    console.log('!!! Error response while auto submitting form data');
+    button.setAttribute('style', 'display: block;');
+  }
+}
+function failsubmit(){
+  console.log('!!! Timeout while auto submitting form data');
+  button.setAttribute('style', 'display: block;');
+}
+
+function formencode(fd){
+    var send;
+    send='autosubmit=true';
+    for (var tup of fd.entries()){
+      send += '&' + encodeURIComponent(tup[0]) + '=' + encodeURIComponent(tup[1]);
+    }
+    return send;
+}
+
+function formsend(){
+  var request = new XMLHttpRequest();
+  request.open('post', '/therapies/update_therapy.sh');
+  request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+  request.timeout = 5000;
+  request.onload = postsubmit;
+  request.ontimeout = failsubmit;
+  request.onerror = failsubmit;
+  request.onabort = failsubmit;
+
+  formdata = formencode(new FormData(document.querySelector('#report')));
+
+  if ( ! (formdata == formdata_old) ) {
+    console.log( 'send' );
+    request.send( formdata );
+    formdata_old = formdata;
+  }
+}
+
+formdata_old = formencode(new FormData(document.querySelector('#report')));
+button.setAttribute('style', 'display: none;');
+setInterval(formsend, 500);
diff --git a/therapies/index.cgi b/therapies/index.cgi
new file mode 100755 (executable)
index 0000000..515f2b0
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# Copyright 2016, 2020 Paul Hänsch
+#
+# This file is part of Lobster.
+# 
+# Lobster is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# Lobster is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with Lobster.  If not, see <http://www.gnu.org/licenses/>. 
+
+case "$_PATH" in
+  /therapies/therapy.css)
+    . $_EXEC/cgilite/file.sh
+    FILE $_EXEC/therapies/therapy.css
+    return 0
+    ;;
+  /therapies/*.*_session*.png)
+    if [ -r "$_DATA/$_PATH" ]; then
+      . $_EXEC/cgilite/file.sh
+      FILE "$_DATA/$_PATH"
+    fi
+    return 0
+    ;;
+  /therapies/*/new)
+    card="${_PATH#/therapies/}"
+    card="${card%/new}"
+    uid="$(timeid)$(randomid)"
+    if [ -f "${_DATA}/vcard/${card}.vcf" ]; then
+      touch "${_DATA}/therapies/${card}.${uid}.tpy"
+      rm -f "${_DATA}/cache/${card}.vcf.cache"
+      REDIRECT "/therapies/${card}/${uid}"
+    fi
+    return 0
+    ;;
+esac
+
+. $_EXEC/pdiread.sh
+. $_EXEC/therapies/l10n.sh
+
+id="${_PATH#/therapies/}"
+id="${id%/*}.${id#*/}"
+
+read junkx junky bg_dim junkz <<-E_READ
+       $(identify "$_EXEC/therapies/therapy_background.png")
+E_READ
+
+vcffile="${_DATA}/vcard/${id%.*}.vcf"
+mpxfile="${_DATA}/prescriptions/${id}.mpx"
+tpyfile="${_DATA}/therapies/${id}.tpy"
+
+vcf="$(pdi_load "$vcffile")"
+mpx="$([ -f "$mpxfile" ] && sed '1s;^;\n;; s/:/;:/' "$mpxfile")"
+tpy="$(sed '1s;^;\n;; s/:/;:/' "$tpyfile")"
+
+VCF(){ pdi_value "$vcf" "$@"; }
+MPX(){ pdi_value "$mpx" "$@"; }
+TPY(){ pdi_value "$tpy" "$@" >/dev/null && pdi_value "$tpy" "$@" |pdi_unescape; }
+
+. $_EXEC/therapies/page.sh \
+| yield_page therapy /therapies/therapy.css
diff --git a/therapies/l10n.sh b/therapies/l10n.sh
new file mode 100755 (executable)
index 0000000..167dc4d
--- /dev/null
@@ -0,0 +1,70 @@
+# Copyright 2016, 2020 Paul Hänsch
+#
+# This file is part of Confetti.
+# 
+# Confetti is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# Confetti is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
+
+#. $_EXEC/templates/text_prescriptions.sh
+l10n(){
+  local word
+  [ $# -eq 0 ] && read -r word || word="$1"
+  case $word in
+    therapy_prescription) printf '%s\n' "Heil&shy;mit&shy;tel&shy;ver&shy;ord&shy;nung";;
+    prescriptions_current) printf '%s\n' "Aktuelle Verordnungen";;
+    prescriptions_past) printf '%s\n' "Frühere Verordnungen";;
+    newprescription) printf '%s\n' "Neue Verordnung";;
+    date) printf '%s\n' "Datum";;
+    name) printf '%s\n' "Name d. Versicherten";;
+    bday) printf '%s\n' "geb. am";;
+    addcontrib) printf '%s\n' "Zuzahlung";;
+    contribconfirm) printf '%s\n' "Zuzahlung erfolgt am...";;
+    contribreceipt) printf '%s\n' "Quit&shy;tung heraus&shy;ge&shy;ge&shy;ben";;
+    prescreviewed) printf '%s\n' "Verordnung geprüft";;
+    prescreview) printf '%s\n' "Verordnung prüfen!";;
+    quantity) printf '%s\n' "Ver&shy;ord&shy;nungs&shy;men&shy;ge";;
+    remidy) printf '%s\n' "Heil&shy;mit&shy;tel nach Maß&shy;ga&shy;be des Ka&shy;ta&shy;lo&shy;ges";;
+    prescfirst) printf '%s\n' "Erst&shy;ver&shy;ord&shy;nung";;
+    prescfollow1) printf '%s\n' "1. Folge-&shy;VO";;
+    prescfollow2) printf '%s\n' "2. Folge-&shy;VO";;
+    prescother) printf '%s\n' "VO außer&shy;halb des Re&shy;gel&shy;falls";;
+    presccontinual) printf '%s\n' "Lang&shy;frist&shy;ver&shy;ord&shy;nung";;
+    grouptherapy) printf '%s\n' "Grup&shy;pen&shy;the&shy;ra&shy;pie";;
+    housecall) printf '%s\n' "Haus&shy;be&shy;such";;
+    report) printf '%s\n' "The&shy;ra&shy;pie&shy;be&shy;richt";;
+    indicator) printf '%s\n' "In&shy;di&shy;ka&shy;tions&shy;schlüssel";;
+    icd10) printf '%s\n' "ICD-10-Code";;
+    indicator_reading) printf '%s\n' "Befund Beschreibung";;
+    insurance) printf '%s\n' "Krankenkasse bzw. Kostenträger";;
+    prescription_by_catalogue) printf '%s\n' "Verordnung nach Maßgabe des Kataloges (Regelfall)";;
+    therapy_start) printf '%s\n' "Be&shy;hand&shy;lungs&shy;be&shy;ginn spä&shy;test. am";;
+    quantity_weekly) printf '%s\n' "An&shy;zahl pro Wo&shy;che";;
+    save) printf '%s\n' "Speichern";;
+    cancel) printf '%s\n' "Abbrechen";;
+    delete) printf '%s\n' "Löschen";;
+
+    therapy) printf '%s\n' "Therapie";;
+    therapies) printf '%s\n' "Therapien";;
+
+    prescriptionlist) printf '%s\n' "Zur Verordnungsliste";;
+    delete_session) printf '%s\n' "Therapiesitzung entfernen";;
+    therapist) printf '%s\n' "Therapeut";;
+    number) printf '%s\n' "Nr.";;
+    signature) printf '%s\n' "Un&shy;ter&shy;schrift";;
+    weekly) printf '%s\n' "p. Woche";;
+    notes) printf '%s\n' "Notizen";;
+    trailsave) printf '%s\n' "Speichern für weitere Felder";;
+
+    *) HTML "$word";;
+  esac
+}
diff --git a/therapies/page.sh b/therapies/page.sh
new file mode 100755 (executable)
index 0000000..a53bb92
--- /dev/null
@@ -0,0 +1,228 @@
+# Copyright 2016, 2017, 2020 Paul Hänsch
+#
+# This file is part of Lobster.
+# 
+# Confetti is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# Lobster is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with Lobster.  If not, see <http://www.gnu.org/licenses/>. 
+
+t_session_note(){
+  session_n="$1"
+  note_n="$2"
+  
+  color=session${session_n}_note${note_n}_color
+  
+  if [ "$note_n" -eq 1 -o "$(TPY "session${session_n}_note${note_n}")" ]; then
+    printf '[input type="checkbox" .trailbtn checked="checked"]'
+  else
+    printf '[input type="checkbox" .trailbtn]'
+  fi
+
+  check="$(TPY "$color" |grep -xE -m1 '#(888|00A|0A0|0AA|A00|A0A|AA0)' || printf '#FFF')"
+  cat <<-EOF
+       [fieldset .note .trailbox
+         [radio "$color" "#888" .color #${color}_000 $(checked "$check" '#888') ][label for=${color}_000]
+         [radio "$color" "#00A" .color #${color}_001 $(checked "$check" '#00A') ][label for=${color}_001]
+         [radio "$color" "#0A0" .color #${color}_010 $(checked "$check" '#0A0') ][label for=${color}_010]
+         [radio "$color" "#0AA" .color #${color}_011 $(checked "$check" '#0AA') ][label for=${color}_011]
+         [radio "$color" "#A00" .color #${color}_100 $(checked "$check" '#A00') ][label for=${color}_100]
+         [radio "$color" "#A0A" .color #${color}_101 $(checked "$check" '#A0A') ][label for=${color}_101]
+         [radio "$color" "#AA0" .color #${color}_110 $(checked "$check" '#AA0') ][label for=${color}_110]
+         [radio "$color" "#FFF" .color #${color}_111 $(checked "$check" '#FFF') ][label for=${color}_111]
+         [textarea name="session${session_n}_note${note_n}" . $(TPY "session${session_n}_note${note_n}" |HTML)]
+       ]
+       EOF
+}
+
+therapy_sessions(){
+  n=1; while [ "$(TPY session$n)" ]; do n=$((n + 1)); done
+
+  sid=session$n
+  cat <<-EOF
+       [fieldset .tab
+         [submit "new_session" "$sid" .no . +]
+         [input .date name="${sid}_date" value="" placeholder=$(l10n date)]
+         [input .therapist name="${sid}_therapist" value="" placeholder=$(l10n therapist)]
+         [span .signature]
+         [hidden "${sid}_note1" ""]
+       ]
+       EOF
+
+  for n in $(seq $((n - 1)) -1 1); do
+    session_n="$n"
+    sid=session${session_n}
+
+    cat <<-EOF
+       [hidden "$sid" "exists"]
+       [checkbox "${sid}_open" "checked" #${sid}_open .tab $(checked "$(TPY "${sid}_open")" checked)]
+       [label .tab for="${sid}_open"
+         [span .no ${session_n}.]
+         [span .date . $(TPY "${sid}_date" |HTML)]
+         [input .date name="${sid}_date" value="$(TPY "${sid}_date" |HTML)" placeholder="$(l10n date)"]
+         [span .therapist . $(TPY "${sid}_therapist" |HTML)]
+         [input .therapist name="${sid}_therapist" value="$(TPY "${sid}_therapist" |HTML)" placeholder="$(l10n therapist)"]
+         [span .signature [checkbox "${sid}_sigset" "pos" $(checked "$(TPY "${sid}_sigset")" "pos")]]
+       ]
+       [div .tab
+         [img .dotmark .ov src="/therapies/${id}_${sid}.png?${_DATE}" alt=""]
+         $(n=1; while TPY "session${session_n}_note${n}" >/dev/null; do
+             [ "$(TPY "session${session_n}_note${n}")" ] && x=$n
+             n=$(($n + 1))
+           done
+           for n in $(seq 1 $((${x:-0} + 3)) ); do
+             t_session_note $session_n $n
+           done
+         )
+         [button type="submit" .trailbtn $(l10n trailbtn)]
+         [button type="submit" name=delete_session value="$session_n" .delete $(l10n delete_session)]
+       ]
+       EOF
+  done
+}
+
+cat <<EOF
+[h1 $(l10n therapy)]
+
+[div .patient
+  [h2 . &#x2b05; $(VCF FN |HTML)]
+]
+
+[div .therapies
+  [h2 $(l10n therapies)]
+  $(
+  (cd "$_DATA/therapies/"; printf '%s\n' "${id%%.*}".*.tpy) \
+  | while read tpyfile; do
+    [ "$tpyfile" = "${id%%.*}.*.tpy" ] && break
+    tpy="${tpyfile%.tpy}";
+    tpydates="$(sed -En 's;^session[0-9]+_date:;;p;' "$_DATA/therapies/$tpyfile" \
+                | sort \
+                | sed -E ':X;N;$!bX; s;^[\n ]+;;; s;[\n ]+$;;; s;(\n.*\n|\n); - ;;'
+               )"
+    if [ "${tpy%.*}.${tpy#*.}" = "${id}" ]; then
+      printf '[a .item .therapy .current href="/therapies/%s" . %s] ' \
+             "${tpy%.*}/${tpy#*.}" "$(HTML "${tpydates:--}")"
+    else
+      printf '[a .item .therapy href="/therapies/%s" . %s] ' \
+             "${tpy%.*}/${tpy#*.}" "$(HTML "${tpydates:--}")"
+    fi
+  done |sort -n
+  )
+  [!-- a .item .therapy href="/therapies/${id%%.*}/new" . + --]
+]
+EOF
+
+if [ "$mpx" ]; then
+  printf '[div .prescription [h2 %s]' "$(l10n therapy_prescription)"
+  
+  printf '[ul'
+  for n in '' 0 1 2 3 4 5 6 7 8 9 10; do
+    remidy="$(MPX remidy$n)"
+    quantity="$(MPX quantity$n)"
+    quantity_weekly="$(MPX quantity_weekly$n)"
+  
+    if [ "$remidy" -a "$quantity_weekly" ]; then
+      printf '[li %s %s %s]' "$(HTML "$quantity")" "$(HTML "$remidy")" "$(HTML "$quantity_weekly") $(l10n weekly)"
+    elif [ "$remidy" ]; then
+      printf '[li %s %s]' "$(HTML "$quantity")" "$(HTML "$remidy")"
+    fi
+  done
+  printf ']'
+  
+  for field in indicator icd10; do
+    val="$(MPX "$field")"
+    [ "$val" ] && printf '[span .%s [label . %s:]%s]' "$field" "$(l10n "$field")" "$(HTML "$val")"
+  done
+  
+  if [ "$(MPX indicator_reading)" ]; then
+    printf '[h3 %s][p . %s]' \
+           "$(l10n indicator_reading)" "$(MPX indicator_reading |HTML)"
+  fi
+
+  printf ']'
+fi
+
+cat <<EOF
+[form #report method=POST action="/therapies/update_therapy.sh"
+  [hidden "id" "$id"][hidden "tid" "$(transid "$tpyfile")"]
+
+  [button #backbutton type=submit name="vcfreturn" value="true" &#x2b05; $(VCF FN |HTML)]
+
+  [input .stickynote type=checkbox name=c_stickynote #show_stickynote]
+  [fieldset .stickynote
+    [label for="show_stickynote" $(l10n notes)]
+    [h2 $(l10n notes)]
+    [textarea name=stickynote . $(TPY stickynote |HTML)]
+    [button type=submit $(l10n save)]
+  ]
+EOF
+
+# cat <<EOF
+#   [input .stickynote type=checkbox name=c_timesheet #show_timesheet]
+#   [fieldset .stickynote
+#     [label for="show_timesheet" $(l10n timesheet)]
+#     [h2 $(l10n timesheet)]
+#     [table [thead [tr
+#       [th $(l10n time_goal)][th $(l10n time_actual)][th $(l10n time_difference)]
+#     ]][tbody
+#       $(for n in '' 0 1 2 3 4 5 6 7 8 9 10; do
+#         tsgoal="$(TPY tsgoal$n |grep -m1 -xE '[0-9]+')"
+#         tsactual="$(TPY tsactual$n |grep -m1 -xE '[0-9]+')"
+#         printf '[tr [td [input type=number name=tsgoal value="%s"]][td [input type=number name=tsactual value="%s"]][td %s]]' \
+#                "$tsgoal" "$tsactual" "$(( ${tsgoal:-0} - ${tsactual:-0} ))"
+#       done)
+#     ]]
+#     [button type=submit $(l10n save)]
+#   ]
+# EOF
+
+cat <<EOF
+  [label .tab .heading
+    [span .no $(l10n number)][span .date $(l10n date)][span .therapist $(l10n therapist)][span .signature $(l10n signature)]
+  ]
+EOF
+
+therapy_sessions
+
+## ==== Drawing canvas ==== ##
+### ====================== ###
+
+penwidth="$(TPY penwidth |grep -xE -m1 '(4|12|36)' || printf '4')"
+color="$(TPY color |grep -xE -m1 '#(000|00A|0A0|0AA|A00|A0A|AA0|FFF)' || printf '#000')"
+cat <<EOF
+  [fieldset .penwidth
+    [radio "penwidth" "4"  #pw1 $(checked "$penwidth" 4) ][label for="pw2"]
+    [radio "penwidth" "12" #pw2 $(checked "$penwidth" 12)][label for="pw3"]
+    [radio "penwidth" "36" #pw3 $(checked "$penwidth" 36)][label for="pw1"]
+  ]
+  [fieldset .color
+    [radio "color" "#000" .color #c000 $(checked "$color" '#000') ][label for=c000 ]
+    [radio "color" "#00A" .color #c001 $(checked "$color" '#00A') ][label for=c001 ]
+    [radio "color" "#0A0" .color #c010 $(checked "$color" '#0A0') ][label for=c010 ]
+    [radio "color" "#0AA" .color #c011 $(checked "$color" '#0AA') ][label for=c011 ]
+    [radio "color" "#A00" .color #c100 $(checked "$color" '#A00') ][label for=c100 ]
+    [radio "color" "#A0A" .color #c101 $(checked "$color" '#A0A') ][label for=c101 ]
+    [radio "color" "#AA0" .color #c110 $(checked "$color" '#AA0') ][label for=c110 ]
+    [radio "color" "#FFF" .color #c111 $(checked "$color" '#FFF') ][label for=c111 ]
+  ]
+  [img .dotmark .bg src="/therapies/therapy_background.png" alt="WARNING: Missing background image!"]
+  [canvas #canvas .dotmark .ov width="${bg_dim%x*}" height="${bg_dim#*x}" ]
+  [input type=hidden #image_serialize name=imagedata value=""]
+
+  [input type=hidden name=formend value=formend]
+  [button #savebutton type=submit $(l10n save)]
+]
+
+[span #jsdebug style="display: none; position: fixed; right:0; bottom:0" Debug]
+
+[script type="text/javascript" src="/therapies/therapy_draw.js"]
+[!-- script type="text/javascript" src="/therapies/autosave.js" --]
+EOF
similarity index 90%
rename from therapy/therapy.css
rename to therapies/therapy.css
index b17497c98d8e5bb6bcbe28d7c898b4d0e932ce1c..90eb0270d14f8d996152c9c22fac64bd4efe5f2e 100644 (file)
@@ -35,6 +35,17 @@ form > button[type=submit]:hover {
   background-color: #FEE;
 }
 
+form > button#backbutton {
+  position: absolute;
+  top: 2em;
+  left: 2%;
+  background: transparent;
+  border: none;
+  padding: 0;
+  margin: 0;
+}
+
+
 input.tab { display: none; }
 input.tab + label.tab { display: block; }
 input.tab + label.tab::before { content: '\25b8 \00a0'; float: left;}
@@ -60,12 +71,35 @@ input.color[value="#AA0"] + label { background-color: #FF0;}
 input.color[value="#FFF"] + label { background-color: #FFF;}
 
 h1, label.tab, div.tab, fieldset.tab,
-div.patient, div.prescription {
+div.patient, div.prescription, div.therapies {
   display: block;
   width: 96%;
   margin: 0 2%;
 }
 
+div.patient a {
+  text-decoration: none; color: #000;
+}
+
+div.therapies > a {
+  display: inline-block;
+  text-decoration: none;
+  border: 1px solid black;
+  margin-top: .5em; padding: .25em .5em;
+  background-color: #DDF;
+  color: #000;
+}
+div.therapies > a.current {
+  background-color: #AAF;
+}
+
+div.prescription {
+  background-color: #CFF;
+}
+div.prescription h3 {
+  margin-top: .5em;
+}
+
 div.prescription span {
   display: inline-block;
   width: 50%;
@@ -81,7 +115,10 @@ div.prescription span.catalogue {
   padding: .5ex 1ex;
 }
 
-div.prescription ul {margin-top: 0;}
+div.prescription ul {
+  margin-top: .5em;
+  margin-left: 1.5em;
+}
 
 div.prescription label.checkbox,
 div.prescription label.radio {
@@ -138,28 +175,29 @@ input.stickynote + .stickynote:nth-of-type(2n) {
 }
 
 input.stickynote + .stickynote > * { display: none; }
+input.stickynote + .stickynote > textarea {
+  display: block;
+  position: absolute;
+  left; 0; right: 0; bottom: 0; top: 0;
+  width: 100%; height: 100%;
+  background-color: #FF8;
+  padding: 2em 1em;
+}
 input.stickynote + .stickynote > label {
   position: absolute;
-  top: 0; bottom: 0; right: .5ex;
+  top: 0; bottom: 0; right: .5ex; left: 0;
   display: block;
   text-align: right;
   font-weight: bold;
+  z-index: 1;
 }
 input.stickynote + .stickynote:hover {
-  left: -1ex;
+  width: auto; left: 0em; right: 2em;
 }
 input.stickynote:checked + .stickynote {
   width: auto; left: 1em; right: 1em;
 }
 input.stickynote:checked + .stickynote > * { display: block; }
-input.stickynote:checked + .stickynote > textarea {
-  display: block;
-  position: absolute;
-  left; 0; right: 0; bottom: 0; top: 0;
-  width: 100%; height: 100%;
-  background-color: #FF8;
-  padding: 2em 1em;
-}
 input.stickynote:checked + .stickynote > button[type="submit"] {
   display: block;
   position: absolute;
@@ -174,6 +212,7 @@ input.stickynote:checked + .stickynote > label {
 input.stickynote:checked + .stickynote > label:before {
   position: absolute;
   font-size: initial;
+  line-height: 1em;
   content: "x";
   top: .5ex; right: .5ex;
   padding: .125ex .75ex;
@@ -223,10 +262,11 @@ fieldset.color > input.color + label {
 
 @media(min-width: 800px){
   h1, label.tab, div.tab, fieldset.tab,
-  div.patient, div.prescription {
+  div.patient, div.prescription, div.therapies {
     width: 38%;
     margin-right: 0;
   }
+  input.stickynote + .stickynote:hover { right: calc(50% + 1em); }
   input.stickynote:checked + .stickynote { right: 50%; }
   fieldset.penwidth,
   fieldset.color { position: fixed; }
@@ -244,18 +284,19 @@ fieldset.color > input.color + label {
 
 h1 {display: none;}
 
-div.patient, div.prescription { margin-top: 1em; }
-div.prescription {
+div.patient, div.prescription, div.therapies { margin-top: .5em; }
+div.prescription, div.therapies {
   border: 1px solid black;
-  background-color: #EEE;
   padding: .125em 1.25ex .5em 1.25ex;
 }
 div > h2 { margin: 0; border-bottom: 1px solid black; }
+/*
 div:nth-child(n+2) > a:first-of-type {
   display: block;
   margin: .125em 0 .5em 0;
   text-decoration: none;
 }
+*/
 
 #report fieldset.tab,
 #report label.tab {
similarity index 87%
rename from therapy/therapy_draw.js
rename to therapies/therapy_draw.js
index 8a8e936c6873b443a0d7ba0799b491e7f5d50f7e..19542c8e2cca88cb5a91d0f582abec1d2076f5ca 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2016 Paul Hänsch
+// Copyright 2016, 2020 Paul Hänsch
 //
 // This file is part of Confetti.
 // 
 body = document.body
 dbg = document.getElementById("jsdebug")
 canvas = document.getElementById("canvas")
-data=document.getElementById("image_serialize")
+data = document.getElementById("image_serialize")
 
 image = canvas.getContext("2d")
 mouse = 0
 image_serialize=""
+image.lineJoin = "round"
+image.lineCap = "round"
+data.value += " stroke-linejoin round "
+data.value += " stroke-linecap round "
 
 // start and current coordinates of a draw
 // serves for tracking, whether path ends close to its beginning
@@ -77,16 +81,16 @@ function drawstart(x, y) {
   setstroke(document.querySelector('input[name="penwidth"]:checked').value);
   setcol(document.querySelector('input[name="color"]:checked').value);
 
-  image.beginPath()
-  draw(x, y)  // why must this not use relative Coords ???
+  image.beginPath();
+  draw(x, y);  // why must this not use relative Coords ???
 
-  image_serialize = " polyline"
+  image_serialize = " polyline " + stx + "," + sty;
 }
 
 function drawstop() {
  
   // if path ends close to beginning ( < 50 px); then close path and fill
-  if ( false && mouse == 1 && Math.sqrt( Math.pow(stx - cux, 2) + Math.pow(sty - cuy, 2)) <= 50 && c !== "#FFF" ){
+  if ( mouse == 1 && Math.sqrt( Math.pow(stx - cux, 2) + Math.pow(sty - cuy, 2)) <= 50 && c !== "#FFF" ){
     image.lineTo( stx, sty )
     image.stroke()
 
diff --git a/therapies/update_therapy.sh b/therapies/update_therapy.sh
new file mode 100755 (executable)
index 0000000..c72d040
--- /dev/null
@@ -0,0 +1,132 @@
+#!/bin/zsh
+
+# Copyright 2016, 2020 Paul Hänsch
+#
+# This file is part of Confetti.
+# 
+# Confetti is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# Confetti is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
+
+. "$_EXEC/pdiread.sh"
+tpy="$(POST id)"
+
+tpyfile="$_DATA/therapies/${tpy}.tpy"
+tempfile="$_DATA/temp/${tpy}.$$.tpy"
+
+if [ "$(POST tid)" != "$(transid "$tpyfile")" ]; then
+  if [ "$(POST autosubmit)" = "true" ]; then
+    printf 'Status: 409 Conflict\r\nContent-Length: 0\r\n\r\n'
+    exit 0
+  else
+    SET_COOKIE session message="TRANSACTION_CONFLICT"
+    REDIRECT "/therapies/${tpy%.*}/${tpy#*.}"
+  fi
+fi
+
+if [ "$(POST formend)" != "formend" ]; then
+  if [ "$(POST autosubmit)" = "true" ]; then
+    printf 'Status: 409 Conflict\r\nContent-Length: 0\r\n\r\n'
+    exit 0
+  else
+    SET_COOKIE session message="INCOMPLETE_SUBMIT"
+    REDIRECT "/therapies/${tpy%.*}/${tpy#*.}"
+  fi
+fi
+
+# serialize POST array into file
+for key in $(POST_KEYS); do
+  case "$key" in
+    imagedata|tid|formend) : ;;
+    session*_date)
+      value="$(POST "$key")"
+      y=0 mon=0 dom=0
+      case $value in
+        *.*.*) IFS=. read dom mon y <<-END
+               ${value}
+               END
+          ;;
+        *.*.) IFS=. read dom mon <<-END
+               ${value}
+               END
+          ;;
+        */*/*) IFS=/ read mon dom y <<-END
+               ${value}
+               END
+          ;;
+        */*) IFS=/ read mon dom <<-END
+               ${value}
+               END
+          ;;
+        *-*-*) IFS=- read y mon dom <<-END
+               ${value}
+               END
+          ;;
+      esac
+      [ ! "$y" ] && y="$(date +%Y)"
+      [ "$y" -gt 0 -a "$y" -lt 100 ] && y="$((y + 2000))"
+      date -d "${y}-${mon}-${dom}" + && printf %s:%s\\n "$key" "$(date -d "${y}-${mon}-${dom}" +%F)" \
+                                     || printf %s:\\n "$key"
+      ;;
+    *) printf %s:%s\\n "$key" "$(pdi_escape "$(POST "$key")")" ;;
+  esac
+done >"$tempfile" 2>&-
+
+if [ "$(POST delete_session)" ]; then
+  n="$(POST delete_session)"
+  sed -Ei '/^session'$n'[_:]/d' "$tempfile"
+  rm "${tpyfile%.tpy}_session${n}.png"
+
+  while grep -Eq '^session'$(($n + 1))'_' "$tempfile"; do
+    sed -Ei 's;^session'$(($n + 1))'(_|:);session'$n'\1;' "$tempfile"
+    mv "${tpyfile%.tpy}_session$(($n+1)).png" "${tpyfile%.tpy}_session${n}.png"
+    n=$(($n+1))
+  done
+
+elif [ "$(POST new_session)" ]; then
+  sid="$(POST new_session)"
+
+  read junkx junky dim junkz <<-E_READ
+       $(identify "$_EXEC/therapies/therapy_background.png")
+       E_READ
+
+  convert -size "$dim" xc:transparent "${tpyfile%.tpy}_${sid}.png"
+
+  printf '%s:exists\n' "$sid" >>"$tempfile"
+  printf '%s_open:checked\n' "$sid" >>"$tempfile"
+
+elif [ "$(POST imagedata)" ]; then
+  sid="$(sed -En 's;^(session[0-9]+)_open:checked$;\1;p' "$tempfile" \
+         | sort -n \
+         | tail -n1
+       )"
+
+  convert "${tpyfile%.tpy}_${sid}.png" \
+          -draw "$(POST imagedata)" -transparent white \
+          "${tpyfile%.tpy}_${sid}.png"
+  sync
+fi
+
+if ! diff -q "$tempfile" "$tpyfile" >/dev/null; then
+  mv "$tempfile" "$tpyfile"
+  rm -f -- "${_DATA}/cache/${tpy%%.*}.vcf.cache"
+fi
+
+if [ "$(POST autosubmit)" = "true" ]; then
+  msg="$(transid "$tpyfile")"
+  printf 'HTTP/1.1 200 OK\r\nContent-Length: %i\r\n\r\n%s' \
+         "${#msg}" "${msg}"
+elif [ "$(POST vcfreturn)" ]; then
+  REDIRECT "/cards/#${tpy%.*}.vcf"
+else
+  REDIRECT "/therapies/${tpy%.*}/${tpy#*.}"
+fi
diff --git a/therapy/text_therapy.sh b/therapy/text_therapy.sh
deleted file mode 100755 (executable)
index a2735b2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2016 Paul Hänsch
-#
-# This file is part of Confetti.
-# 
-# Confetti is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# Confetti is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
-
-. $_EXEC/templates/text_prescriptions.sh
-
-item_name[prescriptionlist]="Zur Verordnungsliste"
-item_name[delete_session]="Therapiesitzung entfernen"
-item_name[therapist]="Therapeut"
-item_name[number]="Nr."
-item_name[signature]="Un&shy;ter&shy;schrift"
-item_name[weekly]="p. Woche"
-item_name[notes]="Notizen"
-item_name[trailsave]="Speichern für weitere Felder"
diff --git a/therapy/therapy.html.sh b/therapy/therapy.html.sh
deleted file mode 100755 (executable)
index 1821c24..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-# Copyright 2016, 2017 Paul Hänsch
-#
-# This file is part of Confetti.
-# 
-# Confetti is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# Confetti is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
-
-t_session_note(){
-  session_n="$1"
-  note_n="$2"
-  
-  color=session${session_n}_note${note_n}_color
-  unset c0 c1 c2 c3 c4 c5 c6 c7
-  
-  if [ "$note_n" -eq 1 -o -n "${tpy[session${session_n}_note${note_n}]}" ]; then
-    printf '<input class="trailbtn" type="checkbox" checked="checked">'
-  else
-    printf '<input class="trailbtn" type="checkbox">'
-  fi
-
-  _checked="$(validate "$tpy[$color]" '#(888|00A|0A0|0AA|A00|A0A|AA0)' '#FFF')"
-       cat <<-EOF
-         <fieldset class="note trailbox">
-           <input class=color type=radio name="$color" value="#888" id=${color}_000 $(checked \#888)><label for=${color}_000></label>
-           <input class=color type=radio name="$color" value="#00A" id=${color}_001 $(checked \#00A)><label for=${color}_001></label>
-           <input class=color type=radio name="$color" value="#0A0" id=${color}_010 $(checked \#0A0)><label for=${color}_010></label>
-           <input class=color type=radio name="$color" value="#0AA" id=${color}_011 $(checked \#0AA)><label for=${color}_011></label>
-           <input class=color type=radio name="$color" value="#A00" id=${color}_100 $(checked \#A00)><label for=${color}_100></label>
-           <input class=color type=radio name="$color" value="#A0A" id=${color}_101 $(checked \#A0A)><label for=${color}_101></label>
-           <input class=color type=radio name="$color" value="#AA0" id=${color}_110 $(checked \#AA0)><label for=${color}_110></label>
-           <input class=color type=radio name="$color" value="#FFF" id=${color}_111 $(checked \#FFF)><label for=${color}_111></label>
-           <textarea name="session${session_n}_note${note_n}">${tpy[session${session_n}_note${note_n}]}</textarea>
-         </fieldset>
-       EOF
-}
-
-t_session(){
-  session_n="$1"
-
-  sid=session${session_n}
-
-  if [ "$tpy[${sid}_sigset]" = pos ]; then
-    sigcheck=checked
-  else
-    unset sigcheck
-  fi
-
-       cat <<-EOF
-         <input type=hidden name=$sid value=exists>
-         <input class="tab" type="checkbox" id=${sid}_open name="${sid}_open" value="checked" ${tpy[${sid}_open]}>
-         <label class="tab" for="${sid}_open">
-           <span class=no>${session_n}.</span><!--
-        --><span class=date>${tpy[${sid}_date]}</span><!--
-        --><input class="date" name="${sid}_date" value="${tpy[${sid}_date]}" placeholder="$(l10n date)"><!--
-        --><span class=therapist>${tpy[${sid}_therapist]}</span><!--
-        --><input class="therapist" name="${sid}_therapist" value="${tpy[${sid}_therapist]}" placeholder="$(l10n therapist)"><!--
-        --><span class=signature><input type="checkbox" name="${sid}_sigset" value="pos" $sigcheck></span>
-         </label>
-         <div class=tab>
-           <img class="dotmark ov" src="/therapies/${id%.tpy}_${sid}.png" alt="">
-           $(n=1;
-              while [ -n "${tpy[session${session_n}_note${n}]+x}" ]; do
-                if [ -n "${tpy[session${session_n}_note${n}]}" ]; then
-                  x=$n
-                fi
-                n=$(($n + 1))
-              done
-              for n in $(seq 1 $((${x:-0} + 3)) ); do t_session_note $session_n $n; done
-             )
-           <button class="trailbtn" type="submit">$(l10n trailsave)</button>
-           <button class=delete type=submit name=delete_session value=${session_n}>$(l10n delete_session)</button>
-         </div>
-       EOF
-}
-
-therapy_sessions(){
-  n=1; while [ -n "${tpy[session${n}]}" ]; do
-    t_session $n
-    n=$(($n+1))
-  done
-
-  sid=session$n
-
-       cat <<-EOF
-         <fieldset class="tab">
-           <button class=no type=submit name=new_session value=$sid>+</button><!--
-        --><input class=date name=${sid}_date value="" placeholder="$(l10n date)" /><!--
-        --><input class=therapist name=${sid}_therapist value="" placeholder="$(l10n therapist)" /><!--
-        --><span class=signature><span></span>
-           <input type=hidden name="${sid}_note1" value="">
-         </fieldset>
-       EOF
-}
-
-cat <<EOF
-<h1>$(l10n therapy)</h1>
-
-<div class="patient">
-  <h2>$client_name</h2>
-  <a href="?p=prescriptions&amp;client=${id%%.*}.vcf">&lt; $(l10n prescriptionlist)</a>
-</div>
-
-<div class="prescription">
-  <h2>$(l10n therapy_prescription)</h2>
-  <span class="insurance">${mpx[insurance]}</span>
-  <span class="date"><label>$(l10n date):</label>${mpx[date]}</span>
-
-  <label class="checkbox ${mpx[prescreviewed]:+checked}" for="prescreviewed">
-    $([ -n "${mpx[prescreviewed]}" ] && printf %s "$(l10n prescreviewed)" \
-                                     || printf %s "$(l10n prescreview)" )
-  </label>
-
-       ${mpx[prescno]:+<span class="prescno">$(l10n presc${mpx[prescno]})</span>}
-  ${mpx[grouptherapy]:+<span class="catalogue">$(l10n grouptherapy)</span>}
-     ${mpx[housecall]:+<span class="catalogue">$(l10n housecall)</span>}
-        ${mpx[report]:+<span class="catalogue">$(l10n report)</span>}
-
-  <ul>$(for n in '' {0..10}; do
-    [ -n "${mpx[remidy$n]}" ] && \
-    printf '<li>%s %s %s</li>' "${mpx[quantity$n]}" \
-                               "${mpx[remidy$n]}" \
-                               "${mpx[quantity_weekly$n]:+($mpx[quantity_weekly$n] $(l10n weekly))}"
-  done)</ul>
-
-  ${mpx[indicator]:+<span class="indicator"><label>$(l10n indicator):</label>${mpx[indicator]}</span>}
-      ${mpx[icd10]:+<span class="icd10">    <label>$(l10n icd10):</label>${mpx[icd10]}</span>}
-
-  ${mpx[addcontrib]:+
-  <label class='checkbox ${mpx[contribconfirm]:+checked}' for="addcontrib">
-    $([ -n "${mpx[contribconfirm]}" ] && printf %s "$(l10n contribconfirm)" ${mpx[contribconfirm]} \
-                                      || printf %s "$(l10n addcontrib)" )
-  </label>
-  }
-
-  <input class="tab" type="checkbox" id="indicator_reading">
-  <label class="tab" for="indicator_reading">$(l10n indicator_reading)</label>
-  <div class="tab">${mpx[indicator_reading]}</div>
-</div>
-
-<form id="report" method="POST" action="?action=update_therapy">
-  <input type="hidden" name="id" value="${id}">
-
-  <input class="stickynote" type="checkbox" name="c_stickynote" id="show_stickynote">
-  <fieldset class="stickynote">
-    <label for="show_stickynote">$(l10n notes)</label>
-    <h2>$(l10n notes)</h2>
-    <textarea name="stickynote">${tpy[stickynote]}</textarea>
-    <button type="submit">$(l10n save)</button>
-  </fieldset>
-
-  <input class="stickynote" type="checkbox" name="c_timesheet" id="show_timesheet">
-  <fieldset class="stickynote">
-    <label for="show_timesheet">$(l10n timesheet)</label>
-    <h2>$(l10n timesheet)</h2>
-    <table><thead>
-      <tr><th>$(l10n time_goal)</th><th>$(l10n time_actual)</th><th>$(l10n time_difference)</th></tr>
-    </thead><tbody>
-      $(for n in '' {0..10}; do
-        printf '<tr><td><input type="number" name="tsgoal" value="%s"/></td>
-                    <td><input type="number" name="tsactual" value="%s"/></td>
-                    <td>%s</td>
-                </tr>\n' \
-                "$mpx[tsgoal${n}]" "$mpx[tsactual${n}]" "$((${mpx[tsgoal${n}]:-0} - ${mpx[tsactual${n}]:-0}))"
-      done)
-    </tbody></table>
-    <button type="submit">$(l10n save)</button>
-  </fieldset>
-
-  <!--input class="tab" type="checkbox" id="lookout">
-  <label class="tab" for="lookout">$(l10n indicator_reading)</label>
-  <div class="tab"><textarea name="lookout">${mpx[lookout]}</textarea -->
-
-  <label class="tab heading">
-    <span class=no>$(l10n number)</span><!--
- --><span class=date>$(l10n date)</span><!--
- --><span class=therapist>$(l10n therapist)</span><!--
- --><span class=signature>$(l10n signature)</span>
-  </label>
-EOF
-
-therapy_sessions
-
-_checked="$(validate "$tpy[penwidth]" '(4|12|36)' '4')"
-cat <<EOF
-  <fieldset class="penwidth">
-    <input type="radio" name="penwidth" value="4"  id="pw1" $(checked  4)><label for="pw2"></label>
-    <input type="radio" name="penwidth" value="12" id="pw2" $(checked 12)><label for="pw3"></label>
-    <input type="radio" name="penwidth" value="36" id="pw3" $(checked 36)><label for="pw1"></label>
-  </fieldset>
-EOF
-
-_checked="$(validate "$tpy[color]" '#(0[0A]{2}|A00|A0A|AA0|FFF)' '#000')"
-cat <<EOF
-  <fieldset class="color">
-    <input class="color" type="radio" name="color" value="#000" id="c000" $(checked \#000)><label for="c000"></label>
-    <input class="color" type="radio" name="color" value="#00A" id="c001" $(checked \#00A)><label for="c001"></label>
-    <input class="color" type="radio" name="color" value="#0A0" id="c010" $(checked \#0A0)><label for="c010"></label>
-    <input class="color" type="radio" name="color" value="#0AA" id="c011" $(checked \#0AA)><label for="c011"></label>
-    <input class="color" type="radio" name="color" value="#A00" id="c100" $(checked \#A00)><label for="c100"></label>
-    <input class="color" type="radio" name="color" value="#A0A" id="c101" $(checked \#A0A)><label for="c101"></label>
-    <input class="color" type="radio" name="color" value="#AA0" id="c110" $(checked \#AA0)><label for="c110"></label>
-    <input class="color" type="radio" name="color" value="#FFF" id="c111" $(checked \#FFF)><label for="c111"></label>
-  </fieldset>
-  <img class="dotmark bg" src="?static=therapy_background.png" alt="WARNING: Background Image not available!">
-  <canvas id="canvas" class="dotmark ov" width="${bg_dim%x*}" height="${bg_dim#*x}"></canvas>
-
-  <input type=hidden id=image_serialize name=imagedata value="">
-
-  <button type="submit">$(l10n save)</button>
-</form>
-
-<span id="jsdebug" style="display: none; position: fixed; right:0; bottom:0">Debug</span>
-
-<script type="text/javascript" src="?static=therapy_draw.js"></script>
-EOF
-
-# vi:set filetype=html:
diff --git a/therapy/therapy.sh b/therapy/therapy.sh
deleted file mode 100755 (executable)
index 8885515..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/zsh
-
-# Copyright 2016 Paul Hänsch
-#
-# This file is part of Confetti.
-# 
-# Confetti is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# Confetti is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
-
-declare -A tpy
-declare -A mpx
-
-BR='
-'
-
-id="$_GET[id]"
-
-tpyfile="$_DATA/therapies/$id"
-mpxfile="$_DATA/prescriptions/${id%.tpy}.mpx"
-client="$_DATA/vcard/${id%%.*}.vcf"
-
-identify "$_EXEC/static/therapy_background.png" \
-| sed -r 's;^.* ([0-9]+x[0-9]+) .*$;\1;' \
-| read bg_dim
-
-card_N="$(sed -nr 's:^(N)(;[^"\:]+|;"[^"]+")*\:(.*)$:\3:gp' "$client")"
-card_FN="$(sed -nr 's:^(FN)(;[^"\:]+|;"[^"]+")*\:(.*)$:\3:gp' "$client")"
-card_NICK="$(sed -nr 's:^(NICKNAME)(;[^"\:]+|;"[^"]+")*\:(.*)$:\3:gp' "$client")"
-
-n=$(printf %s "$card_N" \
-    | sed -rn 's:^([^;]*)(\;[^;]*)(\;[^;]*)?(\;[^;]*)?(\;[^;]*)?$:\4 \2 \3 \1 \5:gp' \
-    | sed -r 's:,: :;s:\;: :g;s: +: :g;s:^ $::;'
-   )
-client_name="${n:-${card_FN:-${card_NICK}}}"
-
-mpx=()
-cat "$mpxfile" |while read -r line; do
-  val="${line#*:}"
-  mpx[${line%%:*}]="$(htmlsafe "${val//\\n/$BR}")"
-done
-
-tpy=()
-cat "$tpyfile" |while read -r line; do
-  val="${line#*:}"
-  tpy[${line%%:*}]="$(htmlsafe "${val//\\n/$BR}")"
-done
diff --git a/therapy/update_therapy.sh b/therapy/update_therapy.sh
deleted file mode 100755 (executable)
index 6ba06cb..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/zsh
-
-# Copyright 2016 Paul Hänsch
-#
-# This file is part of Confetti.
-# 
-# Confetti is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# Confetti is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
-
-BR='
-'
-tpy="${_POST[id]}"
-
-tpyfile="$_DATA/therapies/$tpy"
-tempfile="$_DATA/temp/$tpy"
-
-# serialize POST array into file
-for key in ${(k)_POST}; do
-  [ "$key" != imagedata ] && printf %s:%s\\n "$key" "${_POST[$key]//$BR/\\n}"
-done >"$tempfile"
-
-if [ -n "$_POST[delete_session]" ]; then
-  n="$_POST[delete_session]"
-  sed -i -r '/^session'$n'[_:]/d' "$tempfile"
-  rm "${tpyfile%.tpy}_session${n}.png"
-
-  while grep -Eq '^session'$(($n + 1))'_' "$tempfile"; do
-    sed -i -r 's;^session'$(($n + 1))'(_|:);session'$n'\1;' "$tempfile"
-    mv "${tpyfile%.tpy}_session$(($n+1)).png" "${tpyfile%.tpy}_session${n}.png"
-    n=$(($n+1))
-  done
-
-elif [ -n "$_POST[new_session]" ]; then
-  sid="$_POST[new_session]"
-
-  identify "$_EXEC/static/therapy_background.png" \
-  | sed -r 's;^.* ([0-9]+x[0-9]+) .*$;\1;' \
-  | read dim
-
-  convert -size "$dim" xc:transparent "${tpyfile%.tpy}_${sid}.png"
-
-  printf '%s:exists\n' "$sid" >>"$tempfile"
-  printf '%s_open:checked\n' "$sid" >>"$tempfile"
-
-elif [ -n "$_POST[imagedata]" ]; then
-  sed -rn 's;^(session[0-9]+)_open:checked$;\1;p' "$tempfile" \
-  | sort -n \
-  | tail -n1 \
-  | read sid
-
-  convert "${tpyfile%.tpy}_${sid}.png" \
-          -strokewidth 2 -fill '#00000000' \
-          -draw "${_POST[imagedata]}" -transparent white \
-          "${tpyfile%.tpy}_${sid}.png"
-  sync
-fi
-
-mv "$tempfile" "$tpyfile"
-
-redirect "?p=therapy&id=${tpy}"