diff --git a/CHANGELOG b/CHANGELOG
index 6707d1902f3d4402110a4e97fc6bcb1ce8e34e4f..d5a2e4e9525f171a6ab6748f503dcc4fc2469a56 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,22 @@ smasch (1.1.0~alpha.0-1) unstable; urgency=low
 
  -- Piotr Gawron <piotr.gawron@uni.lu>  Thu, 25 Feb 2021 17:00:00 +0200
 
+smasch (1.0.1-1) stable; urgency=low
+
+  * bug fix: gunicorn request length extended so dynamic table allows for more
+    columns (#381)
+  * bug fix: unfinish visit button was always disabled (#386)
+  * bug fix: generating documents for templates did not work for subjects
+    created before custom field was added to the study (#388)
+  * bug fix: readonly custom Date Field was improperly persisted in forms
+    (#383)
+  * bug fix: worker initials were not visible after changing appointments
+    calendar view from month to week (#377)
+  * bug fix: statics and npm files were not served properly when accessing by
+    docker
+
+ -- Piotr Gawron <piotr.gawron@uni.lu>  Wed, 17 Mar 2021 10:00:00 +0200
+
 smasch (1.0.0-1) stable; urgency=low
 
   * backward incompatible: smasch is using python3 (#337)
diff --git a/Dockerfile b/Dockerfile
index 0b52e1a3990087a573d328adcf7ee6df58872505..d2ffe2cafd779475d2650a20d88e6747a9fce3d8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,7 +8,18 @@ RUN pip install -r requirements.txt --default-timeout=180 -i https://pypi.lcsb.u
 ADD . /code/
 RUN cp local_settings_ci.py smash/smash/local_settings.py
 WORKDIR /code/smash
+ENV NODE_VERSION=12.6.0
+RUN apt install -y curl
+RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
+ENV NVM_DIR=/root/.nvm
+RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
+RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
+RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
+ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"
+RUN node --version
+RUN npm --version
+RUN npm install
 
 ENTRYPOINT [ "/bin/sh" ]
-CMD [ "manage.py runserver 0.0.0.0:8002" ]
-EXPOSE 8002
+CMD [ "manage.py runserver 0.0.0.0:8888" ]
+EXPOSE 8888
diff --git a/debian-files/smasch.service b/debian-files/smasch.service
index 03183749e4330c1d69b7517116f558278df61d09..20e9c9e58024619f4a98646e03054e7c4b3cb023 100644
--- a/debian-files/smasch.service
+++ b/debian-files/smasch.service
@@ -8,7 +8,7 @@ User=smasch
 Group=smasch
 WorkingDirectory=/usr/lib/smasch
 
-ExecStart=/usr/lib/smasch/env/bin/gunicorn -b :8888 --pid /run/smasch/pid smash.wsgi --error-logfile /var/log/smasch/gunicorn.log --log-level DEBUG --capture-output --limit-request-line 8192
+ExecStart=/usr/lib/smasch/env/bin/gunicorn -b :8888 --pid /run/smasch/pid smash.wsgi --error-logfile /var/log/smasch/gunicorn.log --log-level DEBUG --capture-output --limit-request-line 16384
 ExecReload=/bin/kill -s HUP $MAINPID
 ExecStop=/bin/kill -s TERM $MAINPID
 PrivateTmp=true
diff --git a/docker-compose.yml b/docker-compose.yml
index 537c9fa7e5cc498806b4cf1641568764f1940a72..69626143ef79e033c97b29df520078d225859c31 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -13,21 +13,21 @@ services:
     web:
         build: .
         expose: 
-            - '8002'
+            - '8888'
         entrypoint: bash -c "sleep 5
                           && python manage.py makemigrations web 
                           && python manage.py migrate
                           && python manage.py migrate sessions
                           && python manage.py collectstatic --noinput
                           && echo && echo && echo 'The server will start now...'
-                          && gunicorn -b 0.0.0.0:8002 smash.wsgi:application --access-logfile access.log --error-logfile error.log"
+                          && gunicorn -b 0.0.0.0:8888 smash.wsgi:application --access-logfile access.log --error-logfile error.log"
                           ### To run the server through manage.py, use:
-                          #  && python manage.py runserver 0.0.0.0:8002"
+                          #  && python manage.py runserver 0.0.0.0:8888"
                           ### To run the verbose tests, uncomment:
                           # python manage.py test -v3"
         command: ""
         ports:
-            - "8002:8002"
+            - "8888:8888"
         volumes:
             - static_files:/tmp/static/
         depends_on:
diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf
index c1364344cbe114ca549cff0c6c3f7f5130952124..037089367fc17f6069e74cdd7afe8ff5d317068e 100644
--- a/docker/nginx/nginx.conf
+++ b/docker/nginx/nginx.conf
@@ -43,7 +43,7 @@ http {
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header Host $http_host;
             proxy_redirect off;
-            proxy_pass http://web:8002;
+            proxy_pass http://web:8888;
         }
     }
 }
diff --git a/docker/nginx/smasch.conf b/docker/nginx/smasch.conf
index cf6558156860ff7ed87e2e6cd7f19b7d8a4ce7f0..628208b16bf5f2f043ca508cc5e814c5f1922d1e 100644
--- a/docker/nginx/smasch.conf
+++ b/docker/nginx/smasch.conf
@@ -46,6 +46,6 @@ server {
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header Host $http_host;
             proxy_redirect off;
-            proxy_pass http://web:8002;
+            proxy_pass http://web:8888;
     }
 }
diff --git a/local_settings_ci.py b/local_settings_ci.py
index 7838de32e0637fdcf67aeeb5f8a6f80905794659..d4a43d46adad89e6967812967b38389451d1a3a3 100644
--- a/local_settings_ci.py
+++ b/local_settings_ci.py
@@ -4,6 +4,8 @@ SECRET_KEY = 'Paste long random string here'  # Insert long random string
 # SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True
 
+SERVE_STATIC = True
+
 # Database
 # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
 
diff --git a/smash/web/docx_helper.py b/smash/web/docx_helper.py
index d8d52829af625780328cb76f61e09d3fa8e306bc..e833eb1f80c401ab18835b6015c2f89e5525242a 100644
--- a/smash/web/docx_helper.py
+++ b/smash/web/docx_helper.py
@@ -26,23 +26,27 @@ def process_file(path_to_docx, path_to_new_docx, changes_to_apply):
 
     doc.save(path_to_new_docx)
 
+
 def merge_files(files, path_to_new_docx):
-    '''
-    When combining templates into a new Document object, python-docx does not properly copy the information of the images, then Word is not able to locate the original content referred by the XML tag in the document. To fix this problem (see #234 ) the first file is loaded and the rest of templates are concatenated to this. This way, the original image content and rId match and the images are shown adequately.
+    """
+    When combining templates into a new Document object, python-docx does not properly copy the information of the
+    images, then Word is not able to locate the original content referred by the XML tag in the document. To fix this
+    problem (see #234 ) the first file is loaded and the rest of templates are concatenated to this. This way, the
+    original image content and rId match and the images are shown adequately.
     See issue #235
-    '''
+    """
     first_file = files[0]
     files = files[1:]
-    merged_document = Document(first_file) #first file
+    merged_document = Document(first_file)  # first file
 
     if len(files) > 0:
         merged_document.add_page_break()
 
-    for index, file in enumerate(files): #rest of files if any
+    for index, file in enumerate(files):  # rest of files if any
         sub_doc = Document(file)
         if index < len(files) - 1:
             sub_doc.add_page_break()
         for element in sub_doc.element.body:
             merged_document.element.body.append(element)
-       
-    merged_document.save(path_to_new_docx)
\ No newline at end of file
+
+    merged_document.save(path_to_new_docx)
diff --git a/smash/web/forms/study_subject_forms.py b/smash/web/forms/study_subject_forms.py
index be2ba5dedb835fee7fc27126af0a3ecc9678f57d..f31538f74b64ef3972d834d120db1eb0eb807813 100644
--- a/smash/web/forms/study_subject_forms.py
+++ b/smash/web/forms/study_subject_forms.py
@@ -158,8 +158,9 @@ class StudySubjectAddForm(StudySubjectForm):
         instance = super(StudySubjectAddForm, self).save(commit)
         # we can add custom values only after object exists in the database
         for field_type in CustomStudySubjectField.objects.filter(study=self.study):
-            self.instance.set_custom_data_value(field_type, get_study_subject_field_value(field_type, self[
-                get_study_subject_field_id(field_type)]))
+            if not field_type.readonly:
+                self.instance.set_custom_data_value(field_type, get_study_subject_field_value(field_type, self[
+                    get_study_subject_field_id(field_type)]))
         return instance
 
     def build_screening_number(self, cleaned_data):
@@ -289,8 +290,9 @@ class StudySubjectEditForm(StudySubjectForm):
 
     def save(self, commit=True) -> StudySubject:
         for field_type in CustomStudySubjectField.objects.filter(study=self.study):
-            self.instance.set_custom_data_value(field_type, get_study_subject_field_value(field_type, self[
-                get_study_subject_field_id(field_type)]))
+            if not field_type.readonly:
+                self.instance.set_custom_data_value(field_type, get_study_subject_field_value(field_type, self[
+                    get_study_subject_field_id(field_type)]))
         return super(StudySubjectForm, self).save(commit)
 
     class Meta:
diff --git a/smash/web/models/mail_template.py b/smash/web/models/mail_template.py
index 417405e99937b776a34038b7c44347ad9c685909..d4d8581c803c5c2583d369550f3b0a9837ba6494 100644
--- a/smash/web/models/mail_template.py
+++ b/smash/web/models/mail_template.py
@@ -338,13 +338,13 @@ class MailTemplate(models.Model):
                 "##S_ADDRESS##": study_subject.subject.address,
                 "##S_CITY##": study_subject.subject.city,
                 "##S_COUNTRY##": str(study_subject.subject.country),
-                "##S_DIAGNOSIS_YEAR##": study_subject.get_custom_field_value('Year of diagnosis'),
+                "##S_DIAGNOSIS_YEAR##": str(study_subject.get_custom_field_value('Year of diagnosis')),
                 "##S_DATE_ADDED##": date_to_str(study_subject.date_added, DATE_FORMAT_SHORT),
                 "##S_DATE_BORN##": date_born,
-                "##S_DIAGNOSIS##": study_subject.get_custom_field_value('Diagnosis'),
+                "##S_DIAGNOSIS##": str(study_subject.get_custom_field_value('Diagnosis')),
                 "##S_EMAIL##": str(study_subject.subject.email),
                 "##S_SEX##": study_subject.subject.get_sex_display(),
-                "##S_MPOWER_ID##": study_subject.get_custom_field_value('MPower ID'),
+                "##S_MPOWER_ID##": str(study_subject.get_custom_field_value('MPower ID')),
                 "##S_ND_NUMBER##": study_subject.nd_number,
                 "##S_PHONE_NUMBER##": str(study_subject.subject.phone_number),
                 "##S_PHONE_NUMBER_2##": str(study_subject.subject.phone_number_2),
diff --git a/smash/web/templates/appointments/index.html b/smash/web/templates/appointments/index.html
index 00d02560abe885d845f98205250a3d218a970452..5f8a5b14fba9f0aaee2afd9b65528fc5a34719af 100644
--- a/smash/web/templates/appointments/index.html
+++ b/smash/web/templates/appointments/index.html
@@ -117,7 +117,10 @@
                 startParam: "start_date",
                 endParam: "end_date",
                 dayRender: function (date, cell) {
-                    var element = document.createElement("div");
+                    var element = dayHeaders[$(cell[0]).attr("data-date")];
+                    if (element === undefined) {
+                        element = document.createElement("div");
+                    }
                     cell[0].appendChild(element);
                     dayHeaders[$(cell[0]).attr("data-date")] = element;
                 },
@@ -146,7 +149,7 @@
                     if (event.status) {
                         content += '<li>Status: ' + event.status + '</li>'
                     }
-                    
+
                     content += "</ul>";
                     $(element).popover({
                         title: event.title,
diff --git a/smash/web/templates/visits/details.html b/smash/web/templates/visits/details.html
index 027c822de313c192d28351ef22ca0abf897c7943..aee569b23da83962e05c86bcbfd8a8a78fcc53dd 100644
--- a/smash/web/templates/visits/details.html
+++ b/smash/web/templates/visits/details.html
@@ -70,7 +70,7 @@
                     <div class="col-md-6 form-group">
                         <label class="col-sm-4 control-label">
                             {% if visFinished %}
-                                <i title="Only visits with one inmediate future visit (without appointments) can be unfinished." class="fa fa-info-circle"></i> 
+                                <i title="Only visits with one immediate future visit (without appointments) can be unfinished." class="fa fa-info-circle"></i>
                             {% endif %}
                             Visit finished
                         </label>
@@ -95,7 +95,7 @@
 
                         {% if visFinished %}
                         <div class="col-sm-1">
-                            {% if "unfinish_visit" not in permissions %}
+                            {% if "delete_visit" not in permissions %}
                                 <div title="You don't have permissions to unfinish visits." class="btn btn-block btn-warning disabled">
                                     <i class="fa fa-undo"></i>
                                 </div>
diff --git a/smash/web/tests/models/test_mail_template.py b/smash/web/tests/models/test_mail_template.py
index 906e32757e7d2cb8c4ce567e5c05332363702af7..c78bdf1214b477559bf89ff1785915651bcce72b 100644
--- a/smash/web/tests/models/test_mail_template.py
+++ b/smash/web/tests/models/test_mail_template.py
@@ -4,13 +4,14 @@ import io
 from django.test import TestCase
 from docx import Document
 
-from web.models import MailTemplate
+from web.models import MailTemplate, StudySubject, Language
 from web.models.constants import MAIL_TEMPLATE_CONTEXT_APPOINTMENT, MAIL_TEMPLATE_CONTEXT_VISIT, \
-    MAIL_TEMPLATE_CONTEXT_SUBJECT, MAIL_TEMPLATE_CONTEXT_VOUCHER
+    MAIL_TEMPLATE_CONTEXT_SUBJECT, MAIL_TEMPLATE_CONTEXT_VOUCHER, CUSTOM_FIELD_TYPE_TEXT
+from web.models.custom_data import CustomStudySubjectField
 from web.models.mail_template import DATE_FORMAT_SHORT
 from web.tests.functions import create_language, get_resource_path, create_appointment, create_user, \
     create_study_subject, \
-    create_visit, create_voucher, create_worker, create_flying_team
+    create_visit, create_voucher, create_worker, create_flying_team, get_test_study
 
 
 class MailTemplateModelTests(TestCase):
@@ -100,19 +101,32 @@ class MailTemplateModelTests(TestCase):
         self.check_doc_contains(doc, [flying_team_name])
 
     def test_apply_subject(self):
-        template_name_french = "test_fr"
         subject = create_study_subject()
-        subject_template_french = MailTemplate(name=template_name_french, language=self.french_language,
-                                               context=MAIL_TEMPLATE_CONTEXT_SUBJECT,
-                                               template_file=self.template_file)
-        stream = io.BytesIO()
-        subject_template_french.apply(subject, self.user, stream)
-        doc = Document(stream)
+        doc = self.create_doc_for_subject(subject, self.french_language, MAIL_TEMPLATE_CONTEXT_SUBJECT)
+        worker_name = str(self.user.worker)
+
+        self.check_doc_contains(doc, [worker_name, str(subject), str(subject.subject.country), subject.nd_number,
+                                      subject.get_type_display()])
+
+    def test_apply_subject_with_non_existing_custom_field(self):
+        subject = create_study_subject()
+        field = CustomStudySubjectField.objects.create(name="Diagnosis", type=CUSTOM_FIELD_TYPE_TEXT,
+                                                       study=get_test_study(), unique=True)
+        doc = self.create_doc_for_subject(subject, self.french_language, MAIL_TEMPLATE_CONTEXT_SUBJECT)
         worker_name = str(self.user.worker)
 
         self.check_doc_contains(doc, [worker_name, str(subject), str(subject.subject.country), subject.nd_number,
                                       subject.type.name])
 
+    def create_doc_for_subject(self, subject: StudySubject, language: Language, context: str):
+        subject_template_french = MailTemplate(name="test_fr", language=language,
+                                               context=context,
+                                               template_file=self.template_file)
+        stream = io.BytesIO()
+        subject_template_french.apply(subject, self.user, stream)
+        doc = Document(stream)
+        return doc
+
     def test_apply_voucher(self):
         template_name_french = "test_without_language"
         subject = create_study_subject()