Can share survey results with a secret shared key
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
nemunaire 2022-12-02 11:48:10 +01:00
commit fff8b821c5
10 changed files with 367 additions and 7 deletions

View file

@ -7,7 +7,7 @@
export let question = null;
function refreshProposals() {
let req = question.getProposals();
let req = question.getProposals(secret);
req.then((proposals) => {
const proposal_idx = { };
@ -17,7 +17,7 @@
proposal_idx[proposal.id] = new String(data.labels.length - 1);
}
req_responses = question.getResponses();
req_responses = question.getResponses(secret);
req_responses.then((responses) => {
for (const res of responses) {
const rsplt = res.value.split(',');
@ -32,6 +32,7 @@
}
let req_proposals = null;
export let proposals = null;
export let secret = null;
let req_responses = null;
let mean = null;
@ -46,7 +47,7 @@
if (!proposals) {
if (question.kind && (question.kind == "int" || question.kind.startsWith("list"))) {
req_responses = question.getResponses();
req_responses = question.getResponses(secret);
req_responses.then((responses) => {
const values = [];
const proposal_idx = { };

View file

@ -62,8 +62,10 @@ export class Question {
this.kind = kind;
}
async getProposals() {
const res = await fetch(`api/questions/${this.id}/proposals`, {
async getProposals(secret) {
let url = `/questions/${this.id}/proposals`;
if (secret) url = `/s/surveys/${this.id_survey}` + url + `?secret=${secret}`;
const res = await fetch('api' + url, {
method: 'GET',
headers: {'Accept': 'application/json'},
});
@ -91,8 +93,10 @@ export class Question {
}
}
async getResponses() {
const res = await fetch(`api/surveys/${this.id_survey}/questions/${this.id}/responses`, {
async getResponses(secret) {
let url = `/surveys/${this.id_survey}/questions/${this.id}/responses`;
if (secret) url = `/s` + url + `?secret=${secret}`;
const res = await fetch('api' + url, {
method: 'GET',
headers: {'Accept': 'application/json'},
});
@ -161,3 +165,17 @@ export async function getQuestions(sid) {
throw new Error((await res.json()).errmsg);
}
}
export async function getSharedQuestions(sid, secret) {
const res = await fetch(`api/s/surveys/${sid}/questions?secret=${secret}`, {headers: {'Accept': 'application/json'}})
if (res.status == 200) {
const data = await res.json();
if (data === null) {
return [];
} else {
return (data).map((q) => new Question(q))
}
} else {
throw new Error((await res.json()).errmsg);
}
}

View file

@ -73,6 +73,18 @@ export class Survey {
}
}
async share() {
const res = await fetch(`api/surveys/${this.id}/shares`, {
method: 'POST',
headers: {'Accept': 'application/json'}
});
if (res.status == 200) {
return await res.json();
} else {
throw new Error((await res.json()).errmsg);
}
}
async save() {
const res = await fetch(this.id?`api/surveys/${this.id}`:'api/surveys', {
method: this.id?'PUT':'POST',
@ -190,3 +202,12 @@ export async function getSurvey(sid) {
throw new Error((await res.json()).errmsg);
}
}
export async function getSharedSurvey(sid, secret) {
const res = await fetch(`api/s/surveys/${sid}?secret=${secret}`, {headers: {'Accept': 'application/json'}})
if (res.status == 200) {
return new Survey(await res.json());
} else {
throw new Error((await res.json()).errmsg);
}
}

View file

@ -0,0 +1,61 @@
<script context="module">
export async function load({ url }) {
return {
props: {
secret: url.searchParams.get("secret"),
idsurvey: url.searchParams.get("survey"),
exportview_list: url.searchParams.get("graph_list")?false:true,
}
};
}
</script>
<script>
import { getSharedQuestions } from '$lib/questions';
import { getSharedSurvey } from '$lib/surveys';
import CorrectionPieChart from '$lib/components/CorrectionPieChart.svelte';
import SurveyBadge from '$lib/components/SurveyBadge.svelte';
export let secret;
export let idsurvey;
let surveyP = getSharedSurvey(idsurvey, secret);
export let exportview_list = true;
</script>
{#await surveyP then survey}
<div class="d-flex align-items-center">
<h2>
{survey.title}
<small class="text-muted">Réponses</small>
</h2>
<SurveyBadge class="ms-2" {survey} />
</div>
{#await getSharedQuestions(survey.id, secret)}
<div class="text-center">
<div class="spinner-border text-primary mx-3" role="status"></div>
<span>Chargement des questions &hellip;</span>
</div>
{:then questions}
{#each questions as question (question.id)}
<h3>{question.title}</h3>
{#if question.kind == "text" || (exportview_list && question.kind.indexOf("list") == 0)}
{#await question.getResponses(secret) then responses}
{#each responses as response (response.id)}
<div class="card mb-2">
<div class="card-body">
<p class="card-text" style:white-space="pre-line">
{response.value}
</p>
</div>
</div>
{/each}
{/await}
{:else}
<CorrectionPieChart {question} {secret} />
{/if}
<hr class="mb-3">
{/each}
{/await}
{/await}

View file

@ -30,6 +30,15 @@
let edit = false;
let exportview = false;
let exportview_list = false;
let sharing_link = null;
async function shareResults(survey) {
const res = await survey.share();
sharing_link = res;
const modal = new bootstrap.Modal(document.getElementById('shareModal'));
modal.show();
}
</script>
{#await surveyP then survey}
@ -40,6 +49,11 @@
class="ms-1 float-end"
on:update={() => goto(`surveys/${survey.id}/admin`)}
/>
<button
class="btn btn-outline-dark ms-1 float-end"
title="Partager les résultats"
on:click={() => shareResults(survey)}
><i class="bi bi-share-fill"></i></button>
<button
class="btn ms-1 float-end"
class:btn-dark={exportview}
@ -144,3 +158,20 @@
{/if}
{/await}
{/await}
<div class="modal fade" tabindex="-1" id="shareModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Partage de résultats</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>
Voici le lien de partage des résultats de ce sondage&nbsp;:
</p>
<pre>{sharing_link}</pre>
</div>
</div>
</div>
</div>