diff --git a/app/apps/core/static/js/edit/components/base_panel.js b/app/apps/core/static/js/edit/components/base_panel.js
index 5aca4f5b68469f3a9dfbf532822b0e8b271281c4..cfc1ee8d1ee10ea52bed2e79360ef62adc9c51c7 100644
--- a/app/apps/core/static/js/edit/components/base_panel.js
+++ b/app/apps/core/static/js/edit/components/base_panel.js
@@ -6,8 +6,10 @@ const BasePanel = Vue.extend({
         };
     },
     watch: {
-        'ratio': function(n, o) {
-            if (this.part.loaded) this.refresh();
+        'part.loaded': function(n, o) {
+            if (this.part.loaded) {
+                this.refresh();
+            }
         }
     },
     methods: {
diff --git a/app/apps/core/static/js/edit/components/diplo_line.js b/app/apps/core/static/js/edit/components/diplo_line.js
index 0139e660e6b60a6ec49c3b43b06999fd68d8526a..64f167a70ea14b8c41265b99c19bc58e63e541c2 100644
--- a/app/apps/core/static/js/edit/components/diplo_line.js
+++ b/app/apps/core/static/js/edit/components/diplo_line.js
@@ -17,6 +17,7 @@ var diploLine = LineBase.extend({
     mounted() {
         Vue.nextTick(function() {
             this.$parent.appendLine();
+            if (this.line.currentTrans) this.setElContent(this.line.currentTrans.content);
         }.bind(this));
     },
     beforeDestroy() {
diff --git a/app/apps/core/static/js/edit/components/diplo_panel.js b/app/apps/core/static/js/edit/components/diplo_panel.js
index a2bbb04901bdc480bb6e691723c851efb040ec4d..cd64124d1991608f1976a4693d342652d3e47b6f 100644
--- a/app/apps/core/static/js/edit/components/diplo_panel.js
+++ b/app/apps/core/static/js/edit/components/diplo_panel.js
@@ -43,6 +43,7 @@ var DiploPanel = BasePanel.extend({
         this.editor = this.$el.querySelector('#diplomatic-lines');
         this.sortModeBtn = this.$el.querySelector('#sortMode');
         this.saveNotif = this.$el.querySelector('.tools #save-notif');
+        this.refresh();
     },
     methods: {
         empty() {
@@ -151,15 +152,18 @@ var DiploPanel = BasePanel.extend({
             this.bulkUpdate();
             this.bulkCreate();
         },
-        setHeight() {
-            this.$el.querySelector('.content-container').style.minHeight = Math.round(this.part.image.size[1] * this.ratio) + 'px';
-        },
         focusNextLine(sel, line) {
             if (line.nextSibling) {
                 let range = document.createRange();
                 range.setStart(line.nextSibling, 0);
                 range.collapse(false);
                 sel.removeAllRanges();
+
+                if (line.nextSibling.offsetTop >
+                    this.editor.parentNode.scrollTop + this.editor.parentNode.clientHeight) {
+                    line.nextSibling.scrollIntoView(false);
+                }
+
                 sel.addRange(range);
             }
         },
@@ -168,6 +172,12 @@ var DiploPanel = BasePanel.extend({
                 let range = document.createRange();
                 range.setStart(line.previousSibling, 0);
                 sel.removeAllRanges();
+
+                if (line.previousSibling.offsetTop - this.editor.parentNode.offsetTop <
+                    this.editor.parentNode.scrollTop) {
+                    line.previousSibling.scrollIntoView(true);
+                }
+
                 sel.addRange(range);
             }
         },
@@ -285,12 +295,11 @@ var DiploPanel = BasePanel.extend({
                 elt.version_updated_at = lt.version_updated_at;
             }
         },
+        setHeight() {
+            this.$el.querySelector('.content-container').style.minHeight = Math.round(this.part.image.size[1] * this.ratio) + 'px';
+        },
         updateView() {
-            /*
-               update the size of the panel
-             */
             this.setHeight();
         }
-    },
-
+    }
 });
diff --git a/app/apps/core/static/js/edit/components/visu_line.js b/app/apps/core/static/js/edit/components/visu_line.js
index 9bb6456cbc00e4cd71a154e41b16e442bdc8a190..ad2e1482d963ae00106a395b68ca15be1a5af379 100644
--- a/app/apps/core/static/js/edit/components/visu_line.js
+++ b/app/apps/core/static/js/edit/components/visu_line.js
@@ -29,7 +29,6 @@ const visuLine = LineBase.extend({
             this.textElement.style.fontSize =  lineHeight * (1/2) + 'px';
             return 10+'px';
         },
-
         computeTextLength() {
             if (!this.line.currentTrans) return;
             content = this.line.currentTrans.content;
@@ -61,7 +60,6 @@ const visuLine = LineBase.extend({
         textPathId() {
             return this.line ? 'textPath'+this.line.pk : '';
         },
-
         maskStrokeColor() {
             if (this.line.currentTrans && this.line.currentTrans.content) {
                 return 'none';
@@ -73,7 +71,6 @@ const visuLine = LineBase.extend({
             if (this.line == null || !this.line.mask) return '';
             return this.line.mask.map(pt => Math.round(pt[0]*this.ratio)+','+Math.round(pt[1]*this.ratio)).join(' ');
         },
-
         fakeBaseline() {
             // create a fake path based on the mask,
             var min = this.line.mask.reduce((minPt, curPt) => (curPt[0] < minPt[0]) ? curPt : minPt);
diff --git a/app/apps/core/static/js/edit/components/visu_panel.js b/app/apps/core/static/js/edit/components/visu_panel.js
index 01871e6719239515791d61e1cceceb544bfaecc5..16e2394ce5b3217def92c53bebb414302e24b934 100644
--- a/app/apps/core/static/js/edit/components/visu_panel.js
+++ b/app/apps/core/static/js/edit/components/visu_panel.js
@@ -30,14 +30,17 @@ const VisuPanel = BasePanel.extend({
                 this.editLine = this.part.lines[index - 1];
             }
         },
+        resetLines() {
+            if (this.part.lines.length) {
+                this.$refs.visulines.forEach(function(line) {
+                    line.reset();
+                });
+            }
+        },
         updateView() {
             this.$el.querySelector('svg').style.height = Math.round(this.part.image.size[1] * this.ratio) + 'px';
             Vue.nextTick(function() {
-                if (this.part.lines.length) {
-                    this.$refs.visulines.forEach(function(line) {
-                        line.reset();
-                    });
-                }
+                this.resetLines();
             }.bind(this));
         }
     }
diff --git a/app/apps/imports/forms.py b/app/apps/imports/forms.py
index 2989588a00942341f0b0eed1fbd52753ad44a7f3..a9f69100ef844e4ec9e34d44e1d25583a419012c 100644
--- a/app/apps/imports/forms.py
+++ b/app/apps/imports/forms.py
@@ -44,7 +44,6 @@ class ImportForm(BootstrapFormMixin, forms.Form):
 
     def clean_iiif_uri(self):
         uri = self.cleaned_data.get('iiif_uri')
-
         if uri:
             try:
                 resp = requests.get(uri)
@@ -83,7 +82,7 @@ class ImportForm(BootstrapFormMixin, forms.Form):
         cleaned_data = super().clean()
         if (not cleaned_data['resume_import']
             and not cleaned_data.get('upload_file')
-            and not cleaned_data['iiif_uri']):
+            and not cleaned_data.get('iiif_uri')):
             raise forms.ValidationError(_("Choose one type of import."))
 
         return cleaned_data
diff --git a/app/apps/imports/parsers.py b/app/apps/imports/parsers.py
index 8f5eb6ced4945c53548e6938101d00222287a49f..987f80dd02cdcccd765dc38b47f4f99d55214d21 100644
--- a/app/apps/imports/parsers.py
+++ b/app/apps/imports/parsers.py
@@ -70,7 +70,8 @@ class PdfParser(ParserDocument):
     def validate(self):
         try:
             self.doc = pyvips.Image.new_from_buffer(self.file.read(), "",
-                                                    dpi=300, n=-1, access="sequential")
+                                                    dpi=300, n=-1,
+                                                    access="sequential")
         except pyvips.error.Error as e:
             logger.exception(e)
             raise ParseError(_("Invalid pdf file."))
@@ -83,21 +84,22 @@ class PdfParser(ParserDocument):
             return 0
 
     def parse(self, start_at=0, override=False, user=None):
-        self.doc = pyvips.Image.new_from_buffer(self.file.read(), "",
-                                                dpi=300, n=-1, access="sequential")
+        buff = self.file.read()
+        doc = pyvips.Image.new_from_buffer(buff, "",
+                                           dpi=300, n=-1,
+                                           access="sequential")
+        n_pages = doc.get('n-pages')
         try:
-            self.doc.flatten(background=255)
-            n_pages = self.doc.get('n-pages')
-            page_width = self.doc.width
-            page_height = self.doc.height / n_pages
-
-            for i in range(0, n_pages):
-                page = self.doc.crop(0, i * page_height, page_width, page_height)
+            for page_nb in range(start_at, n_pages):
+                page = pyvips.Image.new_from_buffer(buff, "", dpi=300,
+                                                    access="sequential",
+                                                    page=page_nb)
                 part = DocumentPart(document=self.document)
-                part.image.save('%s_page_%d.png' % (self.file.name, i+1),
+                part.image.save('%s_page_%d.png' % (self.file.name, page_nb+1),
                                 ContentFile(page.write_to_buffer('.png')))
                 part.save()
                 yield part
+                page_nb = page_nb + 1
         except pyvips.error.Error as e:
             msg = _("Parse error in {filename}: {error}, skipping it.").format(
                 filename=self.file.name, error=e.args[0]
@@ -606,19 +608,19 @@ class IIIFManifestParser(ParserDocument):
     def manifest(self):
         try:
             return json.loads(self.file.read())
-        except (json.JSONDecodeError) as e:
-            raise ParseError(e)
+        except (json.JSONDecodeError, UnicodeDecodeError) as e:
+            raise ParseError(_("Couldn't decode invalid manifest ({error})").format(error=e))
 
     @cached_property
     def canvases(self):
         try:
             return self.manifest["sequences"][0]["canvases"]
-        except (KeyError, IndexError) as e:
-            raise ParseError(e)
+        except (KeyError, IndexError):
+            return 0
 
     def validate(self):
         if len(self.canvases) < 1:
-            raise ParseError(_("Empty manifesto."))
+            raise ParseError(_("Empty or invalid manifest, no images found."))
 
     @property
     def total(self):
@@ -633,13 +635,13 @@ class IIIFManifestParser(ParserDocument):
                     DocumentMetadata.objects.get_or_create(
                         document=self.document, key=md, value=metadata["value"][:512]
                     )
-        except KeyError as e:
+        except KeyError:
             pass
 
-        try:
-            for i, canvas in enumerate(self.canvases):
-                if i < start_at:
-                    continue
+        for i, canvas in enumerate(self.canvases):
+            if i < start_at:
+                continue
+            try:
                 resource = canvas["images"][0]["resource"]
                 url = resource["@id"]
                 uri_template = "{image}/{region}/{size}/{rotation}/{quality}.{format}"
@@ -664,8 +666,10 @@ class IIIFManifestParser(ParserDocument):
                 part.save()
                 yield part
                 time.sleep(0.1)  # avoid being throttled
-        except (KeyError, IndexError) as e:
-            raise ParseError(e)
+            except (KeyError, IndexError) as e:
+                if self.report:
+                    self.report.append(_('Error while fetching {filename}: {error}').format(
+                        filename=name, error=e))
 
 
 class TranskribusPageXmlParser(PagexmlParser):
diff --git a/app/apps/reporting/models.py b/app/apps/reporting/models.py
index f19f7c56fd67ce61337b3a96b7a9826a1fd51b2e..bf62987f56aa600b43801bf5ea4d80a8e1610c12 100644
--- a/app/apps/reporting/models.py
+++ b/app/apps/reporting/models.py
@@ -56,7 +56,7 @@ class TaskReport(models.Model):
         self.save()
 
         self.user.notify(_('%(task_label)s error!') % {'task_label': self.label},
-                         level='error',
+                         level='danger',
                          links=[{'text': 'Report', 'src': self.uri}])
 
     def end(self, extra_links=None):
diff --git a/app/escriptorium/static/css/escriptorium.css b/app/escriptorium/static/css/escriptorium.css
index 8c4d07e1387d8163cc2b391d9577e1fbd30d3803..2b060198e5fce09ff82f59fcf1d50cf55c9b3ac5 100644
--- a/app/escriptorium/static/css/escriptorium.css
+++ b/app/escriptorium/static/css/escriptorium.css
@@ -444,12 +444,12 @@ i.panel-icon {
 }
 
 .panel .content-container .js-wheelzoom-container {
-    min-height: calc(100vh - 190px);
+    min-height: calc(100vh - 200px);
 }
 
 .panel#diplo-panel .content-container {
     overflow-y: scroll;
-    max-height: calc(100vh - 190px);
+    max-height: calc(100vh - 200px);
 }
 
 .panel .panel-img {
@@ -648,4 +648,4 @@ i.panel-icon {
 }
 #reset-onboarding{
     margin-top: 5%;
-}
\ No newline at end of file
+}
diff --git a/app/escriptorium/templates/core/document_part_edit.html b/app/escriptorium/templates/core/document_part_edit.html
index f4aa6b5e57030fe228d5a46702b2a6f6b1ea42f8..f4f3802b92648e2ecd9c92c8e1185ffe159384b3 100644
--- a/app/escriptorium/templates/core/document_part_edit.html
+++ b/app/escriptorium/templates/core/document_part_edit.html
@@ -544,47 +544,48 @@
                 </TranscriptionModal>
             </div>
         </VisuPanel>
-  </keep-alive>
-  <keep-alive>
-      <DiploPanel id="diplo-panel"
-                  v-bind:part="part"
-                  v-if="show.diplomatic && part.loaded"
-                  ref="diploPanel"
-                  inline-template>
-          <div class="col panel">
-              <div class="tools">
-                  <i title="{% trans 'Text Panel' %}" class="panel-icon fas fa-list-ol"></i>
-                  <i id="save-notif" title="{% trans "There is content waiting to be saved (don't leave the page)" %}" class="notice fas fa-save hide"></i>
-                  <button id="sortMode"
-                          title="{% trans "Toggle sorting mode." %}"
-                          class="btn btn-sm ml-3 btn-info fas fa-sort"
-                          @click="toggleSort"
-                          autocomplete="off"></button>
-              </div>
-              <div class="content-container {{ document.read_direction }}">
-
-                  <diploline v-for="line in part.lines"
-                             v-bind:line="line"
-                             v-bind:ratio="ratio"
-                             v-bind:key="'DL' + line.pk">
-                  </diploline>
-
-                  <div id="diplomatic-lines"
-                       contenteditable="true"
-                       autocomplete="off"
-                       @keydown="onKeyPress"
-                       @keyup="constrainLineNumber"
-                       @input="changed"
-                       @focusin="startEdit"
-                       @focusout="stopEdit"
-                       @paste="onPaste"
-                       @mousemove="showOverlay"
-                       @mouseleave="hideOverlay">
-                  </div>
-              </div>
-          </div>
-      </DiploPanel>
-  </keep-alive>
+    </keep-alive>
+
+    <keep-alive>
+        <DiploPanel id="diplo-panel"
+                    v-bind:part="part"
+                    v-if="show.diplomatic && part.loaded"
+                    ref="diploPanel"
+                    inline-template>
+            <div class="col panel">
+                <div class="tools">
+                    <i title="{% trans 'Text Panel' %}" class="panel-icon fas fa-list-ol"></i>
+                    <i id="save-notif" title="{% trans "There is content waiting to be saved (don't leave the page)" %}" class="notice fas fa-save hide"></i>
+                    <button id="sortMode"
+                            title="{% trans "Toggle sorting mode." %}"
+                            class="btn btn-sm ml-3 btn-info fas fa-sort"
+                            @click="toggleSort"
+                            autocomplete="off"></button>
+                </div>
+                <div class="content-container {{ document.read_direction }}">
+
+                    <diploline v-for="line in part.lines"
+                               v-bind:line="line"
+                               v-bind:ratio="ratio"
+                               v-bind:key="'DL' + line.pk">
+                    </diploline>
+
+                    <div id="diplomatic-lines"
+                         contenteditable="true"
+                         autocomplete="off"
+                         @keydown="onKeyPress"
+                         @keyup="constrainLineNumber"
+                         @input="changed"
+                         @focusin="startEdit"
+                         @focusout="stopEdit"
+                         @paste="onPaste"
+                         @mousemove="showOverlay"
+                         @mouseleave="hideOverlay">
+                    </div>
+                </div>
+            </div>
+        </DiploPanel>
+    </keep-alive>
 
     <div class="col-sides">
         {% if document.read_direction == 'rtl' %}
diff --git a/app/requirements.txt b/app/requirements.txt
index 0961da92e174937e9d351cf021bcabc270fd667a..0c77e4a9742166bf645b8aa8e644a482e7557828 100644
--- a/app/requirements.txt
+++ b/app/requirements.txt
@@ -12,7 +12,7 @@ django-redis==4.10.0
 psycopg2-binary==2.7.6
 django-ordered-model==3.1.1
 easy-thumbnails==2.5
-git+https://github.com/mittagessen/kraken.git@3.0b16#egg=kraken
+git+https://github.com/mittagessen/kraken.git@3.0b17#egg=kraken
 django-cleanup==3.0.1
 djangorestframework==3.9.2
 drf-nested-routers==0.91