mirror of
https://github.com/ArenMg/aren.git
synced 2024-12-22 23:13:29 +00:00
FIrst version carto debat
This commit is contained in:
parent
bb0168d25d
commit
77f9c7a6a3
11 changed files with 713 additions and 593 deletions
|
@ -21,11 +21,11 @@ const router = new VueRouter({
|
|||
{path: '/votemajoritaire', component: vueLoader('views/votemajoritaire')},
|
||||
{path: '/createVoteMajoritaire', component: vueLoader('views/createVoteMajoritaire')},
|
||||
{path: '/votemajoritairedetails', component: vueLoader('views/votemajoritairedetails')},
|
||||
{path: '/carto', component: vueLoader('views/cartoTest')},
|
||||
{path: '/creation-debats-sur-cartes', component: vueLoader('views/createDebateSurCarte')},
|
||||
{path: '/documents-debats-sur-cartes', component: vueLoader('views/documentsDebatesSurCarte')},
|
||||
{path: '/documents-debats-sur-cartes/:id', component: vueLoader('views/documentDebatesSurCarte')},
|
||||
{path: '/debats-sur-cartes', component: vueLoader('views/debatesSurCarte')},
|
||||
{path: '/debats-sur-cartes/:id', component: vueLoader('views/debateSurCarte')},
|
||||
{path: '*', component: vueLoader('views/404')},
|
||||
]
|
||||
});
|
|
@ -120,11 +120,13 @@ function Entity(obj = {}) {
|
|||
|
||||
function Category(obj = {}) {
|
||||
Entity.call(this, obj);
|
||||
this.type = DebateType.BASIC;
|
||||
}
|
||||
Category.prototype.attrs = {
|
||||
id: Number,
|
||||
name: String,
|
||||
picture: String,
|
||||
type: String,
|
||||
debatesCount: Number,
|
||||
lastCommentDate: Date,
|
||||
};
|
||||
|
@ -134,10 +136,15 @@ Category.prototype.oneToMany = {
|
|||
Category.prototype.debates = function () {
|
||||
return this.documents.map((document) => document.debates).flat();
|
||||
};
|
||||
Category.prototype.is = function (type) {
|
||||
return DebateType._value[this.type] == DebateType._value[type];
|
||||
}
|
||||
|
||||
function Document(obj = {}) {
|
||||
Entity.call(this, obj);
|
||||
this.type = DebateType.BASIC;
|
||||
this.meshLine = 1;
|
||||
this.meshColumn = 1;
|
||||
}
|
||||
Document.prototype.attrs = {
|
||||
id: Number,
|
||||
|
|
|
@ -102,7 +102,7 @@ const messages = {
|
|||
guests: "Invité⋅e⋅s",
|
||||
debates: "Débats",
|
||||
new_debate: "Nouveau débat",
|
||||
new_map_debate: "Nouveau débat sur caarte",
|
||||
new_map_debate: "Nouveau débat sur carte",
|
||||
invite_in_debate: "Inviter au débat",
|
||||
SUPERADMIN: "Super administrateur⋅rice",
|
||||
SUPERADMIN: "Root",
|
||||
|
|
|
@ -1,569 +0,0 @@
|
|||
<template>
|
||||
<base-layout id="debate">
|
||||
<template v-slot:title>
|
||||
<h1>Debat sur carte</h1>
|
||||
</template>
|
||||
|
||||
<!-- ************************************************* -->
|
||||
|
||||
<div id="mainContainer">
|
||||
<div id="documentContainer">
|
||||
<div class="scroll-area" @scroll="hidePopup(); updateSpaghettis();" ref="documentContainer">
|
||||
<div class="wrap">
|
||||
<documented v-bind:value="$t('documentation.debate_document')">
|
||||
<div id="mapContainer">
|
||||
<img
|
||||
id="mapImg"
|
||||
src="assets/img/mapimg.png"
|
||||
alt="map image"
|
||||
/>
|
||||
<table id="myTable">
|
||||
<tr
|
||||
v-for="(_, indexOfLine) in nbOfLines"
|
||||
:key="indexOfLine"
|
||||
>
|
||||
<td
|
||||
v-for="(_, indexOfColumn) in nbOfColumns"
|
||||
:key="indexOfColumn"
|
||||
@click="select(indexOfLine, indexOfColumn)"
|
||||
:class="{
|
||||
selected: arrayData[indexOfLine][indexOfColumn],
|
||||
}"
|
||||
></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</documented>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="commentsContainer" v-bind:class="{ loading: mountedChildren < debate.commentsCount }"/>
|
||||
<div
|
||||
class="scroll-area"
|
||||
@scroll="
|
||||
hidePopup();
|
||||
updateSpaghettis();
|
||||
"
|
||||
ref="commentsContainer"
|
||||
>
|
||||
<comment-widget
|
||||
v-for="comment in filteredComments"
|
||||
v-show="displayableComments[comment.id]"
|
||||
v-bind:displayable-comments="displayableComments"
|
||||
v-bind:key="comment.id"
|
||||
v-bind:comment="comment"
|
||||
v-bind:search="search"
|
||||
v-bind:hide-on-scroll="true"
|
||||
@tag-edition="editTags($event)"
|
||||
@selection-end="selectionHandler($event)"
|
||||
@focus-me="selectComment($event); scrollToComment($event)"
|
||||
@select-me="selectComment($event)"
|
||||
@highlight-me="highlight($event)"
|
||||
@mounted="mountChild($event)"
|
||||
@report="reportComment($event)"
|
||||
@collapse="collapseComment($event)">
|
||||
</comment-widget>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-show="selectedRange"
|
||||
class="selection_popup z-depth-2"
|
||||
ref="arguePopup"
|
||||
v-bind:style="'top: ' + popup.y + 'px; left: ' + popup.x + 'px;'"
|
||||
@click="createComment()"
|
||||
@mousedown.stop=""
|
||||
@mouseup.stop=""
|
||||
>
|
||||
{{ $t("argue").toLowerCase() }}
|
||||
</div>
|
||||
|
||||
<template v-slot:addons>
|
||||
<comment-modal
|
||||
id="commentModal"
|
||||
ref="commentModal"
|
||||
v-bind:comment="newComment">
|
||||
</comment-modal>
|
||||
|
||||
<tags-modal ref="tagModal">
|
||||
</tags-modal>
|
||||
</template>
|
||||
</base-layout>
|
||||
</template>
|
||||
<style scoped>
|
||||
table,
|
||||
td,
|
||||
th {
|
||||
border: 1px solid black;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#mapContainer {
|
||||
position: relative;
|
||||
}
|
||||
#mapImg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.selected {
|
||||
background-color: rgb(0 0 0 / 26%);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
module.exports = {
|
||||
data() {
|
||||
return {
|
||||
nbOfLines: 5,
|
||||
nbOfColumns: 9,
|
||||
arrayData: false,
|
||||
// ********************************
|
||||
|
||||
debate: false,
|
||||
newComment: false,
|
||||
sortByPosition: false,
|
||||
popup: { x: -9999, y: -9999 },
|
||||
displayableComments: {},
|
||||
selectedRange: false,
|
||||
search: "",
|
||||
mountedChildren: 0,
|
||||
leftDisplay: "document",
|
||||
scrapsMagicNumber: 2,
|
||||
spaghettiOver: "",
|
||||
spaghettiCountDown: 0,
|
||||
scraps: [],
|
||||
themes: [],
|
||||
themeInput: "",
|
||||
themeHelper: false,
|
||||
|
||||
// ****************************************
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.initDataArray();
|
||||
this.fetchData();
|
||||
},
|
||||
computed: {
|
||||
filteredComments() {
|
||||
return this.debate.comments ? this.debate.comments.filter((comment) => !comment.parent) : []
|
||||
},
|
||||
documentAsDom() {
|
||||
let div = document.createElement("div");
|
||||
div.innerHTML = this.debate.document.content;
|
||||
return div;
|
||||
},
|
||||
spaghettiData() {
|
||||
if (this.leftDisplay === "theme") {
|
||||
return this.themes;
|
||||
} else {
|
||||
return this.scraps;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'$route'() {
|
||||
this.fetchData();
|
||||
if (this.$route.query.comment) {
|
||||
this.scrollToComment(this.$route.query.comment);
|
||||
}
|
||||
},
|
||||
debate() {
|
||||
this.displayableComments = {};
|
||||
//This is to make all the properties reactive
|
||||
this.debate.comments.forEach((comment) => Vue.set(this.displayableComments, comment.id, true));
|
||||
},
|
||||
leftDisplay(val) {
|
||||
if (val === 'scraps') {
|
||||
this.fetchScraps();
|
||||
}
|
||||
if (val !== 'document') {
|
||||
this.updateSpaghettis();
|
||||
}
|
||||
},
|
||||
// search(val) {
|
||||
// if (this.leftDisplay === 'scraps' || this.leftDisplay === 'theme') {
|
||||
// this.updateSpaghettis();
|
||||
// }
|
||||
// this.updateDisplayableComments();
|
||||
// },
|
||||
sortByPosition(val) {
|
||||
if (val) {
|
||||
this.debate.deepSortComments((a, b) => a.compareBoundaryPoints(Range.START_TO_START, b));
|
||||
} else {
|
||||
this.debate.deepSortComments((a, b) => (a.created > b.created) ? 1 : -1);
|
||||
}
|
||||
if (this.leftDisplay !== 'document') {
|
||||
// Sort by disply position
|
||||
this.$nextTick(() => {
|
||||
this.spaghettiData.forEach((s) => {
|
||||
s.comments.sort((a, b) => {
|
||||
let divA = document.getElementById("comment_" + a.id);
|
||||
let divB = document.getElementById("comment_" + b.id);
|
||||
return divA.offsetTop - divB.offsetTop
|
||||
});
|
||||
})
|
||||
});
|
||||
this.updateSpaghettis();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/******************* */
|
||||
fetchData() {
|
||||
ArenService.Debates.get({
|
||||
id: 3,
|
||||
onSuccess: (debate) => {
|
||||
this.debate = debate;
|
||||
},
|
||||
onError: () => {
|
||||
this.$router.push("/404");
|
||||
}
|
||||
});
|
||||
},
|
||||
fetchScraps() {
|
||||
ArenService.Debates.getScraps({
|
||||
id: this.debate.id,
|
||||
onSuccess: (result) => {
|
||||
if (result.length > 0) {
|
||||
let arrLength = result.map(r => r.comments.length).sort();
|
||||
let minLength = arrLength[arrLength.length - this.scrapsMagicNumber];
|
||||
result = result.filter(s => s.comments.length > 1 && s.comments.length >= minLength);
|
||||
result.forEach((s, i) => {
|
||||
s.id = i;
|
||||
s.comments = s.comments.map(cid => ArenService.Store.get(cid, Comment));
|
||||
let range = new Range();
|
||||
range.setPathStart(this.documentAsDom, s.startContainer, s.startOffset);
|
||||
range.setPathEnd(this.documentAsDom, s.endContainer, s.endOffset);
|
||||
s.selected = false;
|
||||
s.html = range.getHtml();
|
||||
s.spaghettis = [];
|
||||
s.comments.sort((a, b) => {
|
||||
let divA = document.getElementById("comment_" + a.id);
|
||||
let divB = document.getElementById("comment_" + b.id);
|
||||
return divA.offsetTop - divB.offsetTop
|
||||
});
|
||||
});
|
||||
this.scraps = result;
|
||||
this.updateSpaghettis();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
fetchTheme() {
|
||||
if (this.themes.findIndex((t) => t.html === this.themeInput) === -1) {
|
||||
ArenService.Debates.getTheme({
|
||||
id: this.debate.id,
|
||||
query: {theme: this.themeInput},
|
||||
onSuccess: (result) => {
|
||||
if (result.comments.length > 0) {
|
||||
result.comments = result.comments.map(cid => ArenService.Store.get(cid, Comment)).filter((c) => c !== -1);
|
||||
result.html = result.theme;
|
||||
result.spaghettis = [];
|
||||
result.selected = false;
|
||||
result.comments.sort((a, b) => {
|
||||
let divA = document.getElementById("comment_" + a.id);
|
||||
let divB = document.getElementById("comment_" + b.id);
|
||||
return divA.offsetTop - divB.offsetTop
|
||||
});
|
||||
this.themes.push(result);
|
||||
this.updateSpaghettis();
|
||||
this.themeInput = "";
|
||||
} else {
|
||||
this.themeHelper = this.$t('helper.theme_not_found');
|
||||
setTimeout(() => this.themeHelper = false, 3500);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.themeHelper = this.$t('helper.theme_already_set');
|
||||
setTimeout(() => this.themeHelper = false, 3500);
|
||||
}
|
||||
},
|
||||
updateDisplayableComments() {
|
||||
let selectedScrapComments = false;
|
||||
this.debate.comments.forEach((comment) => this.displayableComments[comment.id] = !selectedScrapComments || selectedScrapComments.includes(comment));
|
||||
},
|
||||
mountChild(comment) {
|
||||
this.mountedChildren++;
|
||||
console.table("Mounted Child", this.mountedChildren);
|
||||
// If there is a commentId in the url, scroll to its position
|
||||
if (this.$route.query.comment && this.mountedChildren >= this.debate.commentsCount) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollToComment(this.$route.query.comment);
|
||||
});
|
||||
}
|
||||
// When a new comment is created, scrool to its position
|
||||
if (this.newComment && comment.owner.id === this.$root.user.id) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollToComment(comment);
|
||||
this.newComment = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
hidePopup() {
|
||||
this.selectedRange = false;
|
||||
},
|
||||
clearSelection( ) {
|
||||
if (this.$route.query.comment) {
|
||||
this.$router.replace({'query': null});
|
||||
}
|
||||
clearSelection( );
|
||||
},
|
||||
editTags(comment) {
|
||||
this.$refs.tagModal.comment = comment;
|
||||
let copy = [...comment.proposedTags];
|
||||
this.$refs.tagModal.open((returnComment) => {
|
||||
if (returnComment) {
|
||||
ArenService.Comments.edit({
|
||||
data: returnComment,
|
||||
loading: false
|
||||
});
|
||||
} else {
|
||||
comment.proposedTags = copy;
|
||||
}
|
||||
});
|
||||
},
|
||||
mailleSelectionHandler(comment,text){
|
||||
if (this.newComment === false) {
|
||||
this.newComment = new Comment( );
|
||||
}
|
||||
if (!this.$refs.commentModal.isOpen()) {
|
||||
this.newComment.debate = this.debate;
|
||||
this.newComment.hypostases = [];
|
||||
this.newComment.tags = [];
|
||||
this.newComment.parent = comment;
|
||||
this.newComment.selection = text;
|
||||
this.newComment.startContainer = 0;
|
||||
this.newComment.endContainer = 0;
|
||||
this.newComment.startOffset = 0;
|
||||
this.newComment.endOffset = 0;
|
||||
} else {
|
||||
this.hidePopup();
|
||||
}
|
||||
this.createComment();
|
||||
},
|
||||
selectionHandler(comment) {
|
||||
let selection = getSelection( );
|
||||
let position = selection.anchorNode.compareDocumentPosition(selection.focusNode);
|
||||
let backward = false;
|
||||
if (!position && selection.anchorOffset > selection.focusOffset ||
|
||||
position === Node.DOCUMENT_POSITION_PRECEDING)
|
||||
backward = true;
|
||||
if (!selection.isCollapsed) {
|
||||
this.selectedRange = selection.getRangeAt(0);
|
||||
this.selectedRange.affineToWord();
|
||||
if (this.newComment === false) {
|
||||
this.newComment = new Comment( );
|
||||
}
|
||||
if (!this.$refs.commentModal.isOpen()) {
|
||||
this.newComment.debate = this.debate;
|
||||
this.newComment.hypostases = [];
|
||||
this.newComment.tags = [];
|
||||
this.newComment.parent = comment;
|
||||
this.newComment.selection = this.selectedRange.getHtml();
|
||||
let container = this.getCommentContainer(this.newComment);
|
||||
this.newComment.startContainer = container.getChildPathTo(this.selectedRange.startContainer);
|
||||
this.newComment.endContainer = container.getChildPathTo(this.selectedRange.endContainer);
|
||||
this.newComment.startOffset = this.selectedRange.startOffset;
|
||||
this.newComment.endOffset = this.selectedRange.endOffset;
|
||||
|
||||
this.popupPositionFromRange(backward);
|
||||
} else {
|
||||
this.hidePopup();
|
||||
}
|
||||
}
|
||||
},
|
||||
popupPositionFromRange(backward) {
|
||||
if (this.selectedRange) {
|
||||
backward = backward === undefined ? this.$refs.arguePopup.classList.contains('top') : backward;
|
||||
let top = mainContainer.offsetTop + 28;
|
||||
let bottom = mainContainer.offsetHeight - window.scrollY + top - 58;
|
||||
let rects = this.selectedRange.getClientRects( );
|
||||
let start = rects[0];
|
||||
let end = rects[rects.length - 1];
|
||||
if (backward && start.y > top || (end.y + end.height) > bottom) {
|
||||
this.popup.x = start.x + window.scrollX;
|
||||
this.popup.y = start.y + window.scrollY;
|
||||
this.$refs.arguePopup.classList.remove('bottom');
|
||||
this.$refs.arguePopup.classList.add('top');
|
||||
} else {
|
||||
this.popup.x = end.x + end.width + window.scrollX;
|
||||
this.popup.y = end.y + end.height + window.scrollY;
|
||||
this.$refs.arguePopup.classList.remove('top');
|
||||
this.$refs.arguePopup.classList.add('bottom');
|
||||
}
|
||||
}
|
||||
},
|
||||
getCommentContainer(comment) {
|
||||
return comment.parent
|
||||
? document.querySelector("#comment_" + comment.parent.id + " .argumentation")
|
||||
: this.$refs.documentDisplay;
|
||||
},
|
||||
createComment( ) {
|
||||
if (!this.$root.user.is('USER')) {
|
||||
this.$confirm({
|
||||
title: this.$t('not_connected'),
|
||||
message: this.$t('helper.not_connected'),
|
||||
isInfo: true
|
||||
});
|
||||
} else {
|
||||
this.$refs.commentModal.open((returnValue) => {
|
||||
if (returnValue) {
|
||||
ArenService.Debates.addComment({
|
||||
id: this.newComment.debate.id,
|
||||
data: this.newComment,
|
||||
loading: false
|
||||
});
|
||||
}
|
||||
});
|
||||
this.hidePopup( );
|
||||
// For the selected text to stay
|
||||
this.highlight(this.newComment);
|
||||
}
|
||||
},
|
||||
selectComment(comment) {
|
||||
let range = new Range( );
|
||||
let container = comment.parent
|
||||
? document.querySelector("#comment_" + comment.parent.id + " .argumentation")
|
||||
: this.$refs.documentDisplay;
|
||||
range.setPathStart(container, comment.startContainer, comment.startOffset);
|
||||
range.setPathEnd(container, comment.endContainer, comment.endOffset);
|
||||
clearSelection( );
|
||||
getSelection( ).addRange(range);
|
||||
return range;
|
||||
},
|
||||
highlight(comment) {
|
||||
if (!comment.parent) {
|
||||
let range = this.selectComment(comment);
|
||||
if (!inScrollView(this.$refs.documentContainer, range)) {
|
||||
scrollCenter(this.$refs.documentContainer, range);
|
||||
}
|
||||
} else {
|
||||
// Select after scroll is done because of lazy loading
|
||||
this.scrollToComment(comment.parent, false, () => {
|
||||
this.selectComment(comment);
|
||||
});
|
||||
}
|
||||
},
|
||||
scrollToComment(comment, focus = true, callback = () => {}) {
|
||||
let commentDiv = document.getElementById("comment_" + (comment.id ? comment.id : comment));
|
||||
let previousScroll = this.$refs.commentsContainer.scrollTop;
|
||||
if (focus) {
|
||||
commentDiv.querySelector(".focuser").focus( );
|
||||
}
|
||||
this.$refs.commentsContainer.scrollTop = previousScroll;
|
||||
if (!inScrollView(this.$refs.commentsContainer, commentDiv)) {
|
||||
scrollCenter(this.$refs.commentsContainer, commentDiv, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
scrollToScrap(scrapId, callback) {
|
||||
let scrapDiv = document.getElementById("scrap_" + scrapId);
|
||||
if (!inScrollView(this.$refs.documentContainer, scrapDiv)) {
|
||||
scrollCenter(this.$refs.documentContainer, scrapDiv, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
spaghetti(scrap, scrapIndex, comment, commentIndex) {
|
||||
let scrapId = "scrap_" + scrapIndex;
|
||||
let commentId = "comment_" + comment.id;
|
||||
let scrapDiv = document.getElementById(scrapId);
|
||||
let commentDiv = document.getElementById(commentId);
|
||||
// Check if a parent is collapsed, if so remove spaghettis
|
||||
let answersDiv = commentDiv.closest(".answers-container");
|
||||
while (answersDiv && commentDiv) {
|
||||
let commentParentDiv = answersDiv.previousElementSibling;
|
||||
if (commentDiv.offsetTop - commentParentDiv.offsetTop < (commentParentDiv.offsetHeight / 2)) {
|
||||
commentDiv = false;
|
||||
} else {
|
||||
answersDiv = answersDiv.parentElement.closest(".answers-container");
|
||||
}
|
||||
|
||||
}
|
||||
// Only if the div exists and is visible
|
||||
if (commentDiv && commentDiv.offsetParent !== null) {
|
||||
let offsetStart = this.$refs.documentContainer.scrollTop;
|
||||
let offsetEnd = this.$refs.commentsContainer.scrollTop;
|
||||
let heightStart = Math.min(scrapDiv.offsetHeight * 0.5, scrap.comments.length * 2);
|
||||
let deltaY = heightStart / scrap.comments.length;
|
||||
|
||||
return d3.linkHorizontal().x(d => d.x).y(d => d.y)({
|
||||
source: {
|
||||
x: (scrapDiv.offsetLeft + scrapDiv.offsetWidth),
|
||||
y: (scrapDiv.offsetTop + commentIndex * deltaY + (scrapDiv.offsetHeight - heightStart) / 2) - offsetStart
|
||||
},
|
||||
target: {
|
||||
x: commentDiv.offsetLeft,
|
||||
y: (commentDiv.offsetTop + commentDiv.offsetHeight / 2) - offsetEnd
|
||||
}
|
||||
});
|
||||
}
|
||||
return "";
|
||||
},
|
||||
updateSpaghettis() {
|
||||
if (this.leftDisplay !== 'document') {
|
||||
this.$nextTick(() => {
|
||||
this.spaghettiData.forEach((s, scrapIndex) => {
|
||||
s.spaghettis = s.comments.map((c, comIndex) => this.spaghetti(s, scrapIndex, c, comIndex));
|
||||
s.color = d3.interpolateRainbow(scrapIndex / this.spaghettiData.length);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
clickSpaghetti() {
|
||||
let arrIds = this.spaghettiOver.split('_');
|
||||
this.spaghettiCountDown = 2;
|
||||
this.scrollToScrap(arrIds[1], () => this.spaghettiCountDown--);
|
||||
this.scrollToComment(arrIds[2], true, () => this.spaghettiCountDown--);
|
||||
},
|
||||
collapseComment(duration) {
|
||||
let start = Date.now();
|
||||
duration = duration + 500;
|
||||
let interval = setInterval(() => {
|
||||
this.updateSpaghettis();
|
||||
if (Date.now() - start >= duration) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 1000 / 60);
|
||||
},
|
||||
reportComment(comment) {
|
||||
this.$confirm({
|
||||
title: this.$t('report'),
|
||||
message: this.$t('helper.report_details')
|
||||
});
|
||||
},
|
||||
/********************* */
|
||||
|
||||
initDataArray() {
|
||||
let arr = [];
|
||||
let col = Array(this.nbOfColumns).fill(false);
|
||||
for (let i = 0; i < this.nbOfLines; i++) {
|
||||
arr.push(col);
|
||||
}
|
||||
this.arrayData = arr;
|
||||
},
|
||||
select(l, c) {
|
||||
let row = this.arrayData[l].slice();
|
||||
row[c] = true;
|
||||
this.arrayData.splice(l, 1, row);
|
||||
this.mailleSelectionHandler(null,`Maille ligne ${l+1}, colonne ${c+1}`);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"tags-modal": vueLoader("components/modals/tagsModal"),
|
||||
"comment-modal": vueLoader("components/modals/commentModal"),
|
||||
|
||||
"comment-widget": vueLoader("components/widgets/comment"),
|
||||
"bullets-container": vueLoader("components/widgets/bulletsContainer"),
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -196,7 +196,7 @@
|
|||
data( ) {
|
||||
return {
|
||||
debate: new Debate( ),
|
||||
categories: ArenService.Store.Category,
|
||||
categories: ArenService.Store.Category.filter(cat=>cat.is('CARTO')),
|
||||
institution: new Institution( ),
|
||||
search: "",
|
||||
step: 0,
|
||||
|
|
651
src/main/webapp/assets/js/views/debateSurCarte.vue
Normal file
651
src/main/webapp/assets/js/views/debateSurCarte.vue
Normal file
|
@ -0,0 +1,651 @@
|
|||
<template>
|
||||
<base-layout id="debate">
|
||||
<template v-slot:title>
|
||||
<h1>Debat sur carte</h1>
|
||||
</template>
|
||||
|
||||
<!-- ************************************************* -->
|
||||
|
||||
<div id="mainContainer">
|
||||
<div id="documentContainer">
|
||||
<div
|
||||
class="scroll-area"
|
||||
@scroll="
|
||||
hidePopup();
|
||||
updateSpaghettis();
|
||||
"
|
||||
ref="documentContainer"
|
||||
>
|
||||
<div class="wrap">
|
||||
<documented v-bind:value="$t('documentation.debate_document')">
|
||||
<div id="mapContainer">
|
||||
<img
|
||||
id="mapImg"
|
||||
:src="debate.document.mapLink"
|
||||
alt="map image"
|
||||
/>
|
||||
<table id="myTable" v-if="debate">
|
||||
<tr
|
||||
v-for="(_, indexOfLine) in debate.document.meshLine"
|
||||
:key="indexOfLine"
|
||||
>
|
||||
<td
|
||||
v-for="(_, indexOfColumn) in debate.document.meshColumn"
|
||||
:key="indexOfColumn"
|
||||
@click="select(indexOfLine, indexOfColumn)"
|
||||
:class="{
|
||||
selected: arrayData[indexOfLine][indexOfColumn],
|
||||
}"
|
||||
></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</documented>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="commentsContainer"
|
||||
v-bind:class="{ loading: mountedChildren < debate.commentsCount }"
|
||||
>
|
||||
<div
|
||||
class="scroll-area"
|
||||
@scroll="
|
||||
hidePopup();
|
||||
updateSpaghettis();
|
||||
"
|
||||
ref="commentsContainer"
|
||||
>
|
||||
<comment-widget
|
||||
v-for="comment in filteredComments"
|
||||
v-show="displayableComments[comment.id]"
|
||||
v-bind:displayable-comments="displayableComments"
|
||||
v-bind:key="comment.id"
|
||||
v-bind:comment="comment"
|
||||
v-bind:search="search"
|
||||
v-bind:hide-on-scroll="true"
|
||||
@tag-edition="editTags($event)"
|
||||
@selection-end="selectionHandler($event)"
|
||||
@focus-me="
|
||||
selectComment($event);
|
||||
scrollToComment($event);
|
||||
"
|
||||
@select-me="selectComment($event)"
|
||||
@highlight-me="highlight($event)"
|
||||
@mounted="mountChild($event)"
|
||||
@report="reportComment($event)"
|
||||
@collapse="collapseComment($event)"
|
||||
>
|
||||
</comment-widget>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-show="selectedRange"
|
||||
class="selection_popup z-depth-2"
|
||||
ref="arguePopup"
|
||||
v-bind:style="'top: ' + popup.y + 'px; left: ' + popup.x + 'px;'"
|
||||
@click="createComment()"
|
||||
@mousedown.stop=""
|
||||
@mouseup.stop=""
|
||||
>
|
||||
{{ $t("argue").toLowerCase() }}
|
||||
</div>
|
||||
|
||||
<template v-slot:addons>
|
||||
<comment-modal
|
||||
id="commentModal"
|
||||
ref="commentModal"
|
||||
v-bind:comment="newComment"
|
||||
>
|
||||
</comment-modal>
|
||||
|
||||
<tags-modal ref="tagModal"> </tags-modal>
|
||||
</template>
|
||||
</base-layout>
|
||||
</template>
|
||||
<style scoped>
|
||||
table,
|
||||
td,
|
||||
th {
|
||||
border: 1px solid black;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#mapContainer {
|
||||
position: relative;
|
||||
}
|
||||
#mapImg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.selected {
|
||||
background-color: rgb(0 0 0 / 26%);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
module.exports = {
|
||||
data() {
|
||||
return {
|
||||
//nbOfLines: 5,
|
||||
//nbOfColumns: 9,
|
||||
arrayData: false,
|
||||
// ********************************
|
||||
|
||||
debate: false,
|
||||
newComment: false,
|
||||
sortByPosition: false,
|
||||
popup: { x: -9999, y: -9999 },
|
||||
displayableComments: {},
|
||||
selectedRange: false,
|
||||
search: "",
|
||||
mountedChildren: 0,
|
||||
leftDisplay: "document",
|
||||
scrapsMagicNumber: 2,
|
||||
spaghettiOver: "",
|
||||
spaghettiCountDown: 0,
|
||||
scraps: [],
|
||||
themes: [],
|
||||
themeInput: "",
|
||||
themeHelper: false,
|
||||
|
||||
// ****************************************
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.fetchData();
|
||||
ArenService.CommentListener.listen({
|
||||
id: this.$route.params.id,
|
||||
onMessage: (comment) => {
|
||||
Vue.set(this.displayableComments, comment.id, true);
|
||||
},
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
filteredComments() {
|
||||
return this.debate.comments
|
||||
? this.debate.comments.filter((comment) => !comment.parent)
|
||||
: [];
|
||||
},
|
||||
documentAsDom() {
|
||||
let div = document.createElement("div");
|
||||
div.innerHTML = this.debate.document.content;
|
||||
return div;
|
||||
},
|
||||
spaghettiData() {
|
||||
if (this.leftDisplay === "theme") {
|
||||
return this.themes;
|
||||
} else {
|
||||
return this.scraps;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.fetchData();
|
||||
if (this.$route.query.comment) {
|
||||
this.scrollToComment(this.$route.query.comment);
|
||||
}
|
||||
},
|
||||
debate() {
|
||||
this.displayableComments = {};
|
||||
//This is to make all the properties reactive
|
||||
this.debate.comments.forEach((comment) =>
|
||||
Vue.set(this.displayableComments, comment.id, true)
|
||||
);
|
||||
},
|
||||
leftDisplay(val) {
|
||||
if (val === "scraps") {
|
||||
this.fetchScraps();
|
||||
}
|
||||
if (val !== "document") {
|
||||
this.updateSpaghettis();
|
||||
}
|
||||
},
|
||||
// search(val) {
|
||||
// if (this.leftDisplay === 'scraps' || this.leftDisplay === 'theme') {
|
||||
// this.updateSpaghettis();
|
||||
// }
|
||||
// this.updateDisplayableComments();
|
||||
// },
|
||||
sortByPosition(val) {
|
||||
if (val) {
|
||||
this.debate.deepSortComments((a, b) =>
|
||||
a.compareBoundaryPoints(Range.START_TO_START, b)
|
||||
);
|
||||
} else {
|
||||
this.debate.deepSortComments((a, b) =>
|
||||
a.created > b.created ? 1 : -1
|
||||
);
|
||||
}
|
||||
if (this.leftDisplay !== "document") {
|
||||
// Sort by disply position
|
||||
this.$nextTick(() => {
|
||||
this.spaghettiData.forEach((s) => {
|
||||
s.comments.sort((a, b) => {
|
||||
let divA = document.getElementById("comment_" + a.id);
|
||||
let divB = document.getElementById("comment_" + b.id);
|
||||
return divA.offsetTop - divB.offsetTop;
|
||||
});
|
||||
});
|
||||
});
|
||||
this.updateSpaghettis();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/******************* */
|
||||
fetchData() {
|
||||
ArenService.Debates.get({
|
||||
id: this.$route.params.id,
|
||||
onSuccess: (debate) => {
|
||||
this.debate = debate;
|
||||
let arr = [];
|
||||
let col = Array(debate.document.meshColumn).fill(false);
|
||||
for (let i = 0; i < debate.document.meshLine; i++) {
|
||||
arr.push(col);
|
||||
}
|
||||
this.arrayData = arr;
|
||||
},
|
||||
onError: () => {
|
||||
this.$router.push("/404");
|
||||
},
|
||||
});
|
||||
},
|
||||
fetchScraps() {
|
||||
ArenService.Debates.getScraps({
|
||||
id: this.debate.id,
|
||||
onSuccess: (result) => {
|
||||
if (result.length > 0) {
|
||||
let arrLength = result.map((r) => r.comments.length).sort();
|
||||
let minLength =
|
||||
arrLength[arrLength.length - this.scrapsMagicNumber];
|
||||
result = result.filter(
|
||||
(s) => s.comments.length > 1 && s.comments.length >= minLength
|
||||
);
|
||||
result.forEach((s, i) => {
|
||||
s.id = i;
|
||||
s.comments = s.comments.map((cid) =>
|
||||
ArenService.Store.get(cid, Comment)
|
||||
);
|
||||
let range = new Range();
|
||||
range.setPathStart(
|
||||
this.documentAsDom,
|
||||
s.startContainer,
|
||||
s.startOffset
|
||||
);
|
||||
range.setPathEnd(this.documentAsDom, s.endContainer, s.endOffset);
|
||||
s.selected = false;
|
||||
s.html = range.getHtml();
|
||||
s.spaghettis = [];
|
||||
s.comments.sort((a, b) => {
|
||||
let divA = document.getElementById("comment_" + a.id);
|
||||
let divB = document.getElementById("comment_" + b.id);
|
||||
return divA.offsetTop - divB.offsetTop;
|
||||
});
|
||||
});
|
||||
this.scraps = result;
|
||||
this.updateSpaghettis();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
fetchTheme() {
|
||||
if (this.themes.findIndex((t) => t.html === this.themeInput) === -1) {
|
||||
ArenService.Debates.getTheme({
|
||||
id: this.debate.id,
|
||||
query: { theme: this.themeInput },
|
||||
onSuccess: (result) => {
|
||||
if (result.comments.length > 0) {
|
||||
result.comments = result.comments
|
||||
.map((cid) => ArenService.Store.get(cid, Comment))
|
||||
.filter((c) => c !== -1);
|
||||
result.html = result.theme;
|
||||
result.spaghettis = [];
|
||||
result.selected = false;
|
||||
result.comments.sort((a, b) => {
|
||||
let divA = document.getElementById("comment_" + a.id);
|
||||
let divB = document.getElementById("comment_" + b.id);
|
||||
return divA.offsetTop - divB.offsetTop;
|
||||
});
|
||||
this.themes.push(result);
|
||||
this.updateSpaghettis();
|
||||
this.themeInput = "";
|
||||
} else {
|
||||
this.themeHelper = this.$t("helper.theme_not_found");
|
||||
setTimeout(() => (this.themeHelper = false), 3500);
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.themeHelper = this.$t("helper.theme_already_set");
|
||||
setTimeout(() => (this.themeHelper = false), 3500);
|
||||
}
|
||||
},
|
||||
updateDisplayableComments() {
|
||||
let selectedScrapComments = false;
|
||||
this.debate.comments.forEach(
|
||||
(comment) =>
|
||||
(this.displayableComments[comment.id] =
|
||||
!selectedScrapComments || selectedScrapComments.includes(comment))
|
||||
);
|
||||
},
|
||||
mountChild(comment) {
|
||||
this.mountedChildren++;
|
||||
console.table("Mounted Child", this.mountedChildren);
|
||||
// If there is a commentId in the url, scroll to its position
|
||||
if (
|
||||
this.$route.query.comment &&
|
||||
this.mountedChildren >= this.debate.commentsCount
|
||||
) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollToComment(this.$route.query.comment);
|
||||
});
|
||||
}
|
||||
// When a new comment is created, scrool to its position
|
||||
if (this.newComment && comment.owner.id === this.$root.user.id) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollToComment(comment);
|
||||
this.newComment = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
hidePopup() {
|
||||
this.selectedRange = false;
|
||||
},
|
||||
clearSelection() {
|
||||
if (this.$route.query.comment) {
|
||||
this.$router.replace({ query: null });
|
||||
}
|
||||
clearSelection();
|
||||
},
|
||||
editTags(comment) {
|
||||
this.$refs.tagModal.comment = comment;
|
||||
let copy = [...comment.proposedTags];
|
||||
this.$refs.tagModal.open((returnComment) => {
|
||||
if (returnComment) {
|
||||
ArenService.Comments.edit({
|
||||
data: returnComment,
|
||||
loading: false,
|
||||
});
|
||||
} else {
|
||||
comment.proposedTags = copy;
|
||||
}
|
||||
});
|
||||
},
|
||||
mailleSelectionHandler(comment, text) {
|
||||
if (this.newComment === false) {
|
||||
this.newComment = new Comment();
|
||||
}
|
||||
if (!this.$refs.commentModal.isOpen()) {
|
||||
this.newComment.debate = this.debate;
|
||||
this.newComment.hypostases = [];
|
||||
this.newComment.tags = [];
|
||||
this.newComment.parent = comment;
|
||||
this.newComment.selection = text;
|
||||
this.newComment.startContainer = 0;
|
||||
this.newComment.endContainer = 0;
|
||||
this.newComment.startOffset = 0;
|
||||
this.newComment.endOffset = 0;
|
||||
} else {
|
||||
this.hidePopup();
|
||||
}
|
||||
this.createComment();
|
||||
},
|
||||
selectionHandler(comment) {
|
||||
let selection = getSelection();
|
||||
let position = selection.anchorNode.compareDocumentPosition(
|
||||
selection.focusNode
|
||||
);
|
||||
let backward = false;
|
||||
if (
|
||||
(!position && selection.anchorOffset > selection.focusOffset) ||
|
||||
position === Node.DOCUMENT_POSITION_PRECEDING
|
||||
)
|
||||
backward = true;
|
||||
if (!selection.isCollapsed) {
|
||||
this.selectedRange = selection.getRangeAt(0);
|
||||
this.selectedRange.affineToWord();
|
||||
if (this.newComment === false) {
|
||||
this.newComment = new Comment();
|
||||
}
|
||||
if (!this.$refs.commentModal.isOpen()) {
|
||||
this.newComment.debate = this.debate;
|
||||
this.newComment.hypostases = [];
|
||||
this.newComment.tags = [];
|
||||
this.newComment.parent = comment;
|
||||
this.newComment.selection = this.selectedRange.getHtml();
|
||||
let container = this.getCommentContainer(this.newComment);
|
||||
this.newComment.startContainer = container.getChildPathTo(
|
||||
this.selectedRange.startContainer
|
||||
);
|
||||
this.newComment.endContainer = container.getChildPathTo(
|
||||
this.selectedRange.endContainer
|
||||
);
|
||||
this.newComment.startOffset = this.selectedRange.startOffset;
|
||||
this.newComment.endOffset = this.selectedRange.endOffset;
|
||||
|
||||
this.popupPositionFromRange(backward);
|
||||
} else {
|
||||
this.hidePopup();
|
||||
}
|
||||
}
|
||||
},
|
||||
popupPositionFromRange(backward) {
|
||||
if (this.selectedRange) {
|
||||
backward =
|
||||
backward === undefined
|
||||
? this.$refs.arguePopup.classList.contains("top")
|
||||
: backward;
|
||||
let top = mainContainer.offsetTop + 28;
|
||||
let bottom = mainContainer.offsetHeight - window.scrollY + top - 58;
|
||||
let rects = this.selectedRange.getClientRects();
|
||||
let start = rects[0];
|
||||
let end = rects[rects.length - 1];
|
||||
if ((backward && start.y > top) || end.y + end.height > bottom) {
|
||||
this.popup.x = start.x + window.scrollX;
|
||||
this.popup.y = start.y + window.scrollY;
|
||||
this.$refs.arguePopup.classList.remove("bottom");
|
||||
this.$refs.arguePopup.classList.add("top");
|
||||
} else {
|
||||
this.popup.x = end.x + end.width + window.scrollX;
|
||||
this.popup.y = end.y + end.height + window.scrollY;
|
||||
this.$refs.arguePopup.classList.remove("top");
|
||||
this.$refs.arguePopup.classList.add("bottom");
|
||||
}
|
||||
}
|
||||
},
|
||||
getCommentContainer(comment) {
|
||||
return comment.parent
|
||||
? document.querySelector(
|
||||
"#comment_" + comment.parent.id + " .argumentation"
|
||||
)
|
||||
: this.$refs.documentDisplay;
|
||||
},
|
||||
createComment() {
|
||||
if (!this.$root.user.is("USER")) {
|
||||
this.$confirm({
|
||||
title: this.$t("not_connected"),
|
||||
message: this.$t("helper.not_connected"),
|
||||
isInfo: true,
|
||||
});
|
||||
} else {
|
||||
this.$refs.commentModal.open((returnValue) => {
|
||||
if (returnValue) {
|
||||
ArenService.Debates.addComment({
|
||||
id: this.newComment.debate.id,
|
||||
data: this.newComment,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.hidePopup();
|
||||
// For the selected text to stay
|
||||
this.highlight(this.newComment);
|
||||
}
|
||||
},
|
||||
selectComment(comment) {
|
||||
let range = new Range();
|
||||
let container = comment.parent
|
||||
? document.querySelector(
|
||||
"#comment_" + comment.parent.id + " .argumentation"
|
||||
)
|
||||
: this.$refs.documentDisplay;
|
||||
range.setPathStart(
|
||||
container,
|
||||
comment.startContainer,
|
||||
comment.startOffset
|
||||
);
|
||||
range.setPathEnd(container, comment.endContainer, comment.endOffset);
|
||||
clearSelection();
|
||||
getSelection().addRange(range);
|
||||
return range;
|
||||
},
|
||||
highlight(comment) {
|
||||
if (!comment.parent) {
|
||||
let range = this.selectComment(comment);
|
||||
if (!inScrollView(this.$refs.documentContainer, range)) {
|
||||
scrollCenter(this.$refs.documentContainer, range);
|
||||
}
|
||||
} else {
|
||||
// Select after scroll is done because of lazy loading
|
||||
this.scrollToComment(comment.parent, false, () => {
|
||||
this.selectComment(comment);
|
||||
});
|
||||
}
|
||||
},
|
||||
scrollToComment(comment, focus = true, callback = () => {}) {
|
||||
let commentDiv = document.getElementById(
|
||||
"comment_" + (comment.id ? comment.id : comment)
|
||||
);
|
||||
let previousScroll = this.$refs.commentsContainer.scrollTop;
|
||||
if (focus) {
|
||||
commentDiv.querySelector(".focuser").focus();
|
||||
}
|
||||
this.$refs.commentsContainer.scrollTop = previousScroll;
|
||||
if (!inScrollView(this.$refs.commentsContainer, commentDiv)) {
|
||||
scrollCenter(this.$refs.commentsContainer, commentDiv, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
scrollToScrap(scrapId, callback) {
|
||||
let scrapDiv = document.getElementById("scrap_" + scrapId);
|
||||
if (!inScrollView(this.$refs.documentContainer, scrapDiv)) {
|
||||
scrollCenter(this.$refs.documentContainer, scrapDiv, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
spaghetti(scrap, scrapIndex, comment, commentIndex) {
|
||||
let scrapId = "scrap_" + scrapIndex;
|
||||
let commentId = "comment_" + comment.id;
|
||||
let scrapDiv = document.getElementById(scrapId);
|
||||
let commentDiv = document.getElementById(commentId);
|
||||
// Check if a parent is collapsed, if so remove spaghettis
|
||||
let answersDiv = commentDiv.closest(".answers-container");
|
||||
while (answersDiv && commentDiv) {
|
||||
let commentParentDiv = answersDiv.previousElementSibling;
|
||||
if (
|
||||
commentDiv.offsetTop - commentParentDiv.offsetTop <
|
||||
commentParentDiv.offsetHeight / 2
|
||||
) {
|
||||
commentDiv = false;
|
||||
} else {
|
||||
answersDiv = answersDiv.parentElement.closest(".answers-container");
|
||||
}
|
||||
}
|
||||
// Only if the div exists and is visible
|
||||
if (commentDiv && commentDiv.offsetParent !== null) {
|
||||
let offsetStart = this.$refs.documentContainer.scrollTop;
|
||||
let offsetEnd = this.$refs.commentsContainer.scrollTop;
|
||||
let heightStart = Math.min(
|
||||
scrapDiv.offsetHeight * 0.5,
|
||||
scrap.comments.length * 2
|
||||
);
|
||||
let deltaY = heightStart / scrap.comments.length;
|
||||
|
||||
return d3
|
||||
.linkHorizontal()
|
||||
.x((d) => d.x)
|
||||
.y((d) => d.y)({
|
||||
source: {
|
||||
x: scrapDiv.offsetLeft + scrapDiv.offsetWidth,
|
||||
y:
|
||||
scrapDiv.offsetTop +
|
||||
commentIndex * deltaY +
|
||||
(scrapDiv.offsetHeight - heightStart) / 2 -
|
||||
offsetStart,
|
||||
},
|
||||
target: {
|
||||
x: commentDiv.offsetLeft,
|
||||
y: commentDiv.offsetTop + commentDiv.offsetHeight / 2 - offsetEnd,
|
||||
},
|
||||
});
|
||||
}
|
||||
return "";
|
||||
},
|
||||
updateSpaghettis() {
|
||||
if (this.leftDisplay !== "document") {
|
||||
this.$nextTick(() => {
|
||||
this.spaghettiData.forEach((s, scrapIndex) => {
|
||||
s.spaghettis = s.comments.map((c, comIndex) =>
|
||||
this.spaghetti(s, scrapIndex, c, comIndex)
|
||||
);
|
||||
s.color = d3.interpolateRainbow(
|
||||
scrapIndex / this.spaghettiData.length
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
clickSpaghetti() {
|
||||
let arrIds = this.spaghettiOver.split("_");
|
||||
this.spaghettiCountDown = 2;
|
||||
this.scrollToScrap(arrIds[1], () => this.spaghettiCountDown--);
|
||||
this.scrollToComment(arrIds[2], true, () => this.spaghettiCountDown--);
|
||||
},
|
||||
collapseComment(duration) {
|
||||
let start = Date.now();
|
||||
duration = duration + 500;
|
||||
let interval = setInterval(() => {
|
||||
this.updateSpaghettis();
|
||||
if (Date.now() - start >= duration) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 1000 / 60);
|
||||
},
|
||||
reportComment(comment) {
|
||||
this.$confirm({
|
||||
title: this.$t("report"),
|
||||
message: this.$t("helper.report_details"),
|
||||
});
|
||||
},
|
||||
/********************* */
|
||||
select(l, c) {
|
||||
let row = this.arrayData[l].slice();
|
||||
row[c] = true;
|
||||
this.arrayData.splice(l, 1, row);
|
||||
this.mailleSelectionHandler(
|
||||
null,
|
||||
`Maille ligne ${l + 1}, colonne ${c + 1}`
|
||||
);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
"tags-modal": vueLoader("components/modals/tagsModal"),
|
||||
"comment-modal": vueLoader("components/modals/commentModal"),
|
||||
|
||||
"comment-widget": vueLoader("components/widgets/comment"),
|
||||
"bullets-container": vueLoader("components/widgets/bulletsContainer"),
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -60,7 +60,9 @@
|
|||
query: categoryId ? {category: categoryId, overview: true} : {overview: true},
|
||||
onSuccess: debates => debates.forEach(d => {
|
||||
if (!this.categories.includes(d.document.category)) {
|
||||
this.categories.push(d.document.category)
|
||||
if(d.document.category.is("CARTO")){
|
||||
this.categories.push(d.document.category);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
<template v-slot:right>
|
||||
<span
|
||||
:disabled="document.mapLink.length<=0"
|
||||
v-if="editionMode"
|
||||
class="waves-effect waves-light btn"
|
||||
@click="saveDocument()"
|
||||
|
@ -45,13 +46,12 @@
|
|||
class="waves-effect waves-light btn"
|
||||
@click="
|
||||
fetchData();
|
||||
editionMode = true;
|
||||
"
|
||||
editionMode = true;"
|
||||
>
|
||||
{{ $t("modify") }}
|
||||
</span>
|
||||
</template>
|
||||
<div id="cartoDetails">
|
||||
<div id="cartoDetails" v-if="editionMode">
|
||||
<div>
|
||||
<label for="loadCarto" class="btn">Charger la carte</label>
|
||||
<input
|
||||
|
@ -64,21 +64,21 @@
|
|||
<div class="cartoInformation-bloc">
|
||||
<div class="mailleInfo">
|
||||
<label>Nombre de ligne </label>
|
||||
<input type="text" maxlength="2" v-model.number="nbOfLines" />
|
||||
<input type="text" maxlength="2" v-model.number="document.meshLine" />
|
||||
</div>
|
||||
<div class="mailleInfo">
|
||||
<label>Nombre de colonne </label>
|
||||
<input type="text" maxlength="2" v-model.number="nbOfColumns" />
|
||||
<input type="text" maxlength="2" v-model.number="document.meshColumn" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="mapContainer" v-if="imgUrl">
|
||||
<img id="mapImg" :src="imgUrl" alt="map image" />
|
||||
<table>
|
||||
<tr v-for="(_, indexOfLine) in nbOfLines" :key="indexOfLine">
|
||||
<tr v-for="(_, indexOfLine) in document.meshLine" :key="indexOfLine">
|
||||
<td
|
||||
v-for="(_, indexOfColumn) in nbOfColumns"
|
||||
v-for="(_, indexOfColumn) in document.meshColumn"
|
||||
:key="indexOfColumn"
|
||||
></td>
|
||||
</tr>
|
||||
|
@ -142,8 +142,8 @@ module.exports = {
|
|||
editionMode: false,
|
||||
selectedCarto: null,
|
||||
imgUrl: null,
|
||||
nbOfLines: 0,
|
||||
nbOfColumns: 0,
|
||||
// nbOfLines: 0,
|
||||
// nbOfColumns: 0,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
@ -163,12 +163,16 @@ module.exports = {
|
|||
onSuccess: (document) => {
|
||||
this.document = document;
|
||||
this.copyDocument(this.document, this.unmodifiedDocument);
|
||||
this.imgUrl = document.mapLink;
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.document = new Document();
|
||||
this.document.type = "CARTO";
|
||||
this.document.mapLink="";
|
||||
this.document.category = new Category();
|
||||
this.document.category.id = this.$route.query.category;
|
||||
this.document.category.type = "CARTO";
|
||||
this.editionMode = true;
|
||||
}
|
||||
},
|
||||
|
@ -181,6 +185,7 @@ module.exports = {
|
|||
},
|
||||
saveDocument() {
|
||||
this.editionMode = false;
|
||||
//this.document.mapLink = this.getBase64Image();
|
||||
ArenService.Documents.createOrUpdate({
|
||||
data: this.document,
|
||||
onSuccess: (document) => {
|
||||
|
@ -199,7 +204,28 @@ module.exports = {
|
|||
const file = event.target.files[0];
|
||||
this.selectedCarto = file;
|
||||
this.imgUrl = URL.createObjectURL(file);
|
||||
this.document.mapLink = this.getBase64Image();
|
||||
},
|
||||
getBase64Image() {
|
||||
// Create an empty canvas element
|
||||
let img = document.getElementById("mapImg");
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
|
||||
// Copy the image contents to the canvas
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
// Get the data-URL formatted image
|
||||
// Firefox supports PNG and JPEG. You could check img.src to
|
||||
// guess the original format, but be aware the using "image/jpg"
|
||||
// will re-encode the image.
|
||||
var dataURL = canvas.toDataURL("image/png");
|
||||
//let dt = dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
|
||||
console.log(dataURL);
|
||||
return dataURL;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"wysiwyg-editor": vueLoader("components/widgets/wysiwygEditor"),
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
module.exports = {
|
||||
data( ) {
|
||||
return {
|
||||
categories: ArenService.Store.Category
|
||||
categories: ArenService.Store.Category.filter(cat=>!cat.is('CARTO'))
|
||||
};
|
||||
},
|
||||
created( ) {
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
module.exports = {
|
||||
data( ) {
|
||||
return {
|
||||
categories: ArenService.Store.Category
|
||||
categories: ArenService.Store.Category.filter(cat=>cat.is('CARTO'))
|
||||
};
|
||||
},
|
||||
created( ) {
|
||||
|
@ -84,14 +84,17 @@
|
|||
name: document.name + " - copie",
|
||||
author: document.author,
|
||||
content: document.content,
|
||||
category: {id: document.category.id}
|
||||
category: {id: document.category.id, type: "CARTO"}
|
||||
});
|
||||
ArenService.Documents.duplicate({
|
||||
id: document.id
|
||||
});
|
||||
},
|
||||
createOrUpdateCategory(category = {}) {
|
||||
this.$refs.categoryModal.category = new Category(category);
|
||||
let catg = new Category(category);
|
||||
catg.type = "CARTO"
|
||||
this.$refs.categoryModal.category = catg;
|
||||
console.log(this.$refs.categoryModal.category);
|
||||
this.$refs.categoryModal.open((updatedCat) => {
|
||||
if (updatedCat) {
|
||||
ArenService.Categories.createOrUpdate({
|
||||
|
|
|
@ -111,14 +111,14 @@
|
|||
<li v-if="user.is('USER')">
|
||||
<router-link to="/votemajoritaire" v-bind:class="{ active: $route.path === '/votemajoritaire' || $route.path === '/createVoteMajoritaire' || $route.path === '/votemajoritairedetails'}">Votes majoritaires</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/creation-debats-sur-cartes" v-bind:class="{ active: $route.path === '/creation-debats-sur-cartes' }">Ouvrir un débat sur carte</router-link>
|
||||
<li v-if="user.is('USER')">
|
||||
<router-link to="/creation-debats-sur-cartes" v-bind:class="{ active: $route.path === '/creation-debats-sur-cartes' }">Ouvrir dc</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/documents-debats-sur-cartes" v-bind:class="{ active: $route.path === '/documents-debats-sur-cartes' }">Mes documents de débat sur carte</router-link>
|
||||
<li v-if="user.is('USER')">
|
||||
<router-link to="/documents-debats-sur-cartes" v-bind:class="{ active: $route.path === '/documents-debats-sur-cartes' }">Mes documents dc</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/debats-sur-cartes" v-bind:class="{ active: $route.path === '/debats-sur-cartes' }">Mes débats sur carte</router-link>
|
||||
<li v-if="user.is('USER')">
|
||||
<router-link to="/debats-sur-cartes" v-bind:class="{ active: $route.path === '/debats-sur-cartes' }">Débats sur carte</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="right">
|
||||
|
|
Loading…
Reference in a new issue