Commit e2146f06 authored by Robin Tissot's avatar Robin Tissot
Browse files

Merge branch 'develop'

parents a4c557e3 05aa042b
from django.conf import settings
def enable_cookie_consent(request):
return {'ENABLE_COOKIE_CONSENT': getattr(settings,
'ENABLE_COOKIE_CONSENT',
True)}
......@@ -95,6 +95,7 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'escriptorium.context_processors.enable_cookie_consent'
],
},
},
......@@ -302,6 +303,9 @@ THUMBNAIL_ALIASES = {
# 'jpeg': '/usr/bin/jpegoptim -S200 {filename}'
# }
ENABLE_COOKIE_CONSENT = os.getenv('ENABLE_COOKIE_CONSENT', True)
VERSIONING_DEFAULT_SOURCE = 'eScriptorium'
VERSION_DATE = os.getenv('VERSION_DATE', '<development>')
......
......@@ -97,7 +97,7 @@
{% block scripts %}
<script src="{% static 'main.js' %}" type="text/javascript"></script>
<script type="text/javascript">
const DEBUG = {% if debug %}true{% else %}false{% endif %};
const DEBUG = {% if debug %}true{% else %}false{% endif %};
</script>
{% if user.is_authenticated %} {# no need to open a socket for anonymous users, bots etc #}
<script type="text/javascript">
......@@ -108,7 +108,12 @@
{% include 'includes/messages.html' %}
{% if user.onboarding %}
<script type="text/javascript">
bootOnboarding();
bootOnboarding();
</script>
{% endif %}
{% if ENABLE_COOKIE_CONSENT %}
<script type="text/javascript">
userProfile.getCookieConsent();
</script>
{% endif %}
{% endif %}
......
django-debug-toolbar==3.2
django-extensions==3.1.0
......@@ -45,9 +45,13 @@ services:
## if need be to correspond to the volume below
### and uncomment this block and the port 443
# volumes:
# - ${PWD}/nginx/ssl.conf:/etc/nginx/conf.d/nginx.conf
# - ${PWD}/nginx/ssl_certificates.conf:/etc/nginx/conf.d/ssl_certificates.conf
# - ${PWD}/nginx/certs/:/etc/certs/
# - type: bind
# source: $PWD/nginx/ssl.conf
# target: /etc/nginx/conf.d/nginx.conf
# - type: bind
# source: $PWD/nginx/ssl_certificates.conf
# target: /etc/nginx/conf.d/ssl_certificates.conf
# - $PWD/nginx/certs/:/etc/certs/
flower:
restart: always
......
......@@ -40,7 +40,9 @@ services:
environment:
- SERVERNAME=${DOMAIN:-localhost}
volumes:
- ${PWD}/nginx/nginx.conf:/etc/nginx/conf.d/nginx.conf
- type: bind
source: $PWD/nginx/nginx.conf
target: /etc/nginx/conf.d/nginx.conf
- static:/usr/src/app/static
- media:/usr/src/app/media
ports:
......@@ -67,6 +69,8 @@ services:
celery-main:
<<: *app
environment:
- OMP_NUM_THREADS=1
command: "celery worker -l INFO -E -A escriptorium -Ofair --prefetch-multiplier 1 -Q default -c ${CELERY_MAIN_CONC:-10} --max-tasks-per-child=10"
celery-low-priority:
......
......@@ -828,9 +828,9 @@
"dev": true
},
"intro.js": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/intro.js/-/intro.js-0.6.0.tgz",
"integrity": "sha1-D82p9DZOIBiX4RKJ4A3S5S4col8="
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/intro.js/-/intro.js-3.3.1.tgz",
"integrity": "sha512-Y+iMbIzVQou9PDRP5miKa7NNQeUkSA6XFp+atnGiTarEi2jghthSLK+9JUvdM6QvQ9G+bpOEfKd+DNtWJlGb9w=="
},
"is-core-module": {
"version": "2.2.0",
......
......@@ -16,7 +16,7 @@
"diff": "^4.0.1",
"dropzone": "^5.5.1",
"file-loader": "^6.2.0",
"intro.js": "^0.6.0",
"intro.js": "^3.3.1",
"jquery": "^3.3.1",
"jquery-ui-dist": "^1.12.1",
"js-cookie": "^2.2.0",
......
......@@ -181,7 +181,8 @@ class SegmenterLine {
}
this.tooltipText = this.type;
this.segmenter.attachTooltip(this, this.baselinePath);
let tooltipTarget = this.baseline !== null ? this.baselinePath : this.maskPath;
this.segmenter.attachTooltip(this, tooltipTarget);
this.refresh();
}
......@@ -874,8 +875,6 @@ export class Segmenter {
// this.raster.position = view.center;
// this.img.style.display = 'hidden';
tool.onMouseDown = this.onMouseDown.bind(this);
// hide the tooltip on leaving the area
this.canvas.addEventListener('mouseleave', function() {
this.tooltip.style.display = 'none';
......@@ -883,6 +882,8 @@ export class Segmenter {
this.tool = tool;
this.tool.activate();
this.resetToolEvents();
this.loaded = true;
}
......@@ -958,14 +959,32 @@ export class Segmenter {
bindRegionEvents(region) {
region.polygonPath.onMouseDown = function(event) {
if (event.event.ctrlKey ||
this.selecting ||
this.spliting ||
// this.selecting ||
isRightClick(event.event) ||
this.mode != 'regions') return;
this.selecting = region;
// if what we are clicking on is already selected,
// check there isn't something below
if (region.selected) {
let hit;
for (let i=0; i<this.regions.length; i++) {
if (this.regions[i] != region) {
hit = this.regions[i].polygonPath.hitTest(event.point);
if (hit) {
this.selecting = this.regions[i];
break;
}
}
}
if (!hit) this.selecting = region;
} else {
this.selecting = region;
}
var dragging = region.polygonPath.getNearestLocation(event.point).segment;
this.tool.onMouseDrag = function(event) {
this.selecting = false;
this.selecting = region;
if (!event.event.shiftKey) {
this.movePointInView(dragging.point, event.delta);
}
......@@ -984,6 +1003,7 @@ export class Segmenter {
}
}
this.tool.onMouseUp = function(event) {
this.onMouseUp(event);
this.resetToolEvents();
this.updateRegionsFromCanvas();
}.bind(this);
......@@ -1001,10 +1021,12 @@ export class Segmenter {
if (line.baselinePath) {
line.baselinePath.onMouseDown = function(event) {
if (event.event.ctrlKey ||
this.spliting ||
isRightClick(event.event) ||
this.mode != 'lines' ||
this.selecting) return;
this.selecting = line;
var hit = line.baselinePath.hitTest(event.point, {
segments: true,
tolerance: 20
......@@ -1028,6 +1050,7 @@ export class Segmenter {
}.bind(this);
this.tool.onMouseUp = function(event) {
this.onMouseUp(event);
this.resetToolEvents();
line.updateDataFromCanvas();
}.bind(this);
......@@ -1069,6 +1092,7 @@ export class Segmenter {
if (line.maskPath) {
line.maskPath.onMouseDown = function(event) {
if (event.event.ctrlKey ||
this.spliting ||
isRightClick(event.event) ||
this.selecting ||
this.mode != 'lines') return;
......@@ -1095,6 +1119,7 @@ export class Segmenter {
}.bind(this);
this.tool.onMouseUp = function(event) {
this.onMouseUp(event);
this.resetToolEvents();
line.updateDataFromCanvas();
}.bind(this);
......@@ -1116,9 +1141,9 @@ export class Segmenter {
resetToolEvents() {
this.tool.onMouseDown = this.onMouseDown.bind(this);
this.tool.onMouseUp = null; //this.onMouseUp.bind(this);
this.tool.onMouseDrag = this.onMouseDrag.bind(this);
this.tool.onMouseMove = null;
this.tool.onMouseUp = null;
}
attachTooltip(obj, target) {
......@@ -1201,39 +1226,14 @@ export class Segmenter {
onMouseDown(event) {
if (isRightClick(event.event)) return;
if (this.selecting) {
if (this.mode == 'regions') {
// if what we are selecting is already selected, check there isn't something below
for (let i=0; i<this.regions.length; i++) {
if (this.selecting.selected && this.regions[i] != this.selecting) {
let hit = this.regions[i].polygonPath.hitTest(event.point);
if (hit) {
this.selecting = this.regions[i];
break;
}
}
}
}
// selection
if (event.event.shiftKey) {
this.selecting.toggleSelect();
this.startLassoSelection(event);
} else {
this.selecting.select();
this.purgeSelection(this.selecting);
}
this.trigger('baseline-editor:selection', {target: this.selecting, selection: this.selection});
this.selecting = null;
} else {
if (!this.selecting) {
if (event.event.ctrlKey) return;
if (this.spliting) {
this.startCuter(event);
} else if (event.event.shiftKey) {
// lasso selection tool
this.startLassoSelection(event);
} else if (this.hasSelection()) {
this.purgeSelection();
} else if (this.mode == 'regions') {
} else if (this.mode == 'regions') {
this.startNewRegion(event);
} else { // mode = 'lines'
// create a new line
......@@ -1242,6 +1242,23 @@ export class Segmenter {
}
}
onMouseUp(event) {
if (this.selecting) {
// selection
if (event.event.shiftKey) {
this.selecting.toggleSelect();
this.startLassoSelection(event);
} else {
this.selecting.select();
this.purgeSelection(this.selecting);
}
this.trigger('baseline-editor:selection', {target: this.selecting, selection: this.selection});
this.selecting = null;
} else if (this.hasSelection()) {
this.purgeSelection();
}
}
getRegionsAt(pt) {
// returns all the regions that contains the given point pt
return this.regions.filter(r => r.polygonPath.contains(pt));
......@@ -2048,7 +2065,7 @@ export class Segmenter {
}
} else {
let newMask = null;
// calculate the normals before splitting
// calculate the normals before spliting
let normal1 = line.baselinePath.getNormalAt(intersections[i].offset);
let normal2 = line.baselinePath.getNormalAt(intersections[i+1].offset);
let split = line.baselinePath.splitAt(intersections[i+1]);
......
......@@ -96,7 +96,14 @@ export const mutations = {
if (index < 0) return
state.all[index] = {
...state.all[index],
currentTrans: { ...state.all[index].currentTrans, pk: lineTrans.pk }
currentTrans: { ...state.all[index].currentTrans, pk: lineTrans.pk },
transcriptions: {
...state.all[index].transcriptions,
[lineTrans.transcription]: {
...state.all[index].transcriptions[lineTrans.transcription],
pk: lineTrans.pk
}
}
}
}
// Force reference update on the whole array
......
......@@ -83,13 +83,13 @@ export const actions = {
// then fetch all content page by page
let fetchPage = async function(page) {
const resp = await api.retrievePage(rootState.document.id, rootState.parts.pk, transcription, page)
let data = resp.data
for (var i=0; i<data.results.length; i++) {
let line = rootState.lines.all.find(l=>l.pk == data.results[i].line)
commit('lines/setTranscriptions', { pk: line.pk, transcription: data.results[i] }, {root: true})
}
if (data.next) fetchPage(page+1)
if (data.next) await fetchPage(page+1)
}
await fetchPage(1)
},
......@@ -162,4 +162,4 @@ export default {
state: initialState(),
mutations,
actions
}
\ No newline at end of file
}
......@@ -14,10 +14,12 @@ export class Alert {
if (this.links !== undefined) {
for (let i=0; i<this.links.length; i++) {
let link = $('<div>').html('<a href="'+this.links[i].src+'" >'+this.links[i].text+'</a>');
if (this.links[i].cssClass) $('a', link).addClass(this.links[i].cssClass);
$('.additional', $new).append(link).css('display', 'block');
}
}
this.$element = $new;
this.htmlElement = this.$element.get(0);
$('#alerts-container').append($new);
$new.show();
......@@ -33,6 +35,7 @@ export class Alert {
} else {
alerts[id_].incrementCounter();
}
return alerts[id_];
}
incrementCounter() {
......
......@@ -4,24 +4,29 @@ Just set ONBOARDING_PAGE in the page before the scripts block.super eg:
const ONBOARDING_PAGE = 'onboarding_document_form';
*/
export function bootOnboarding() {
if (typeof ONBOARDING_PAGE !== 'undefined') {
var onboarding_page_done = userProfile.get(ONBOARDING_PAGE) || false;
if (!onboarding_page_done) {
var intro = introJs().setOptions({'skipLabel': "Skip"});
intro.oncomplete(function() {
userProfile.set(ONBOARDING_PAGE, true);
})
intro.onexit(function(aa) {
if (!userProfile.get(ONBOARDING_PAGE, true)) {
if (confirm("Are you sure you want to avoid further help?")) {
exitOnboarding();
intro.onbeforeexit(function(aa) {
if (intro._currentStep<intro._introItems.length-1) {
if (!userProfile.get(ONBOARDING_PAGE, true)) {
if (confirm("Are you sure you want to avoid further help?")) {
exitOnboarding();
} else {
return false;
}
}
} else {
userProfile.set(ONBOARDING_PAGE, true);
}
});
//document_form
if (ONBOARDING_PAGE == 'onboarding_document_form') {
intro.setOptions({
......@@ -48,7 +53,7 @@ export function bootOnboarding() {
},
]
});
} else if (ONBOARDING_PAGE == 'onboarding_images') {
intro.setOptions({
steps: [
......@@ -89,7 +94,7 @@ export function bootOnboarding() {
}
]
});
} else if (ONBOARDING_PAGE == 'onboarding_edit') {
intro.setOptions({
steps: [
......@@ -125,7 +130,7 @@ export function bootOnboarding() {
}]
});
}
document.addEventListener('DOMContentLoaded', function() {
intro.start();
});
......
......@@ -22,6 +22,20 @@ class Profile {
get(key) {
return this.settings[key];
}
getCookieConsent() {
// get cookie consent.
if (!this.get('cookie-consent')) {
let alert = Alert.add('cookie-consent',
"eScriptorium uses cookies to store the user session and local storage to save user interface preferences.",
"warning",
[{src: '', text:'Accept', cssClass: 'btn btn-outline-dark btn-sm mt-2'}]);
alert.htmlElement.querySelector('.additional a').addEventListener('click', function(ev) {
this.set('cookie-consent', true);
return false;
}.bind(this));
}
}
}
export var userProfile = new Profile();
......@@ -21,7 +21,7 @@ window.Dropzone = require('dropzone/dist/dropzone');
// Intro.js needs to be explicitly set on window, as it's used at boot time
// by onboarding.js
window.introJs = require('intro.js/intro').introJs;
window.introJs = require('intro.js');
// moment needs to be explicitly set on window, as it's used at boot time
// by trans_modal.js
......
......@@ -270,6 +270,7 @@ export default Vue.extend({
}
}
this.$refs.saveNotif.classList.remove('hide');
this.constrainLineNumber();
e.preventDefault();
},
......@@ -339,4 +340,4 @@ export default Vue.extend({
</script>
<style scoped>
</style>
\ No newline at end of file
</style>
......@@ -202,7 +202,13 @@ export default Vue.extend({
return moment.tz(this.line.currentTrans.version_updated_at, this.timeZone);
},
modalImgSrc() {
return this.$store.state.parts.image.uri;
if (this.$store.state.parts.image.uri.endsWith('.tif') ||
this.$store.state.parts.image.uri.endsWith('.tiff')) {
// can't display tifs so fallback to large thumbnail
return this.$store.state.parts.image.thumbnails.large;
} else {
return this.$store.state.parts.image.uri;
}
},
otherTranscriptions() {
let a = Object
......@@ -250,8 +256,16 @@ export default Vue.extend({
},
getLineAngle() {
let p1 = this.line.baseline[0];
let p2 = this.line.baseline[this.line.baseline.length-1];
let p1, p2;
if (this.line.baseline) {
p1 = this.line.baseline[0];
p2 = this.line.baseline[this.line.baseline.length-1];
} else {
// fake baseline from left most to right most points in mask
p1 = this.line.mask.reduce((minPt, curPt) => (curPt[0] < minPt[0]) ? curPt : minPt);
p2 = this.line.mask.reduce((maxPt, curPt) => (curPt[0] > maxPt[0]) ? curPt : maxPt);
}
return Math.atan2(p2[1] - p1[1], p2[0] - p1[0]) * 180 / Math.PI;
},
......
DOMAIN=localhost
SECRET_KEY=changeme
REDIS_HOST=redis
# REDIS_PORT=6379
SQL_HOST=db
SQL_PORT=5432
# SQL_PORT=5432
# POSTGRES_USER=postgres
# POSTGRES_PASSWORD=postgres
# POSTGRES_DB=escriptorium
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment