Improve wording and explainers

This commit is contained in:
Kuba Orlik 2022-07-07 19:59:16 +02:00
parent 592122a7da
commit 052eb5eb89
7 changed files with 59 additions and 28 deletions

View File

@ -1,4 +1,6 @@
export type ExplainerKey = 'cookies_are_pii';
// various explainers that could be related to multiple problems. They are gathered here and added at the end of the email to avoid pasting them multiple times
export type ExplainerKey = 'cookies_are_pii' | 'responsibility_for_third_parties';
export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => JSX.Element> = {
cookies_are_pii: () => (
@ -11,4 +13,18 @@ export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => J
</p>
</>
),
responsibility_for_third_parties: () => (
<>
<h2>Administrator strony ponosi odpowiedzialność za skrypty podmiotów trzecich</h2>
<p>
W wypadku, gdy ujawnienie czy dostęp do danych osobowych zostało dokonane przez
skrypty podmiotów trzecich (np. Google, Facebook, itp), których autorem nie jest
Administrator strony, Administrator wciąż jest odpowiedzialny za procesy
przetwarzania danych osobowych, jakie realizują te skrypty&mdash;w myśl treści{' '}
<a href="https://curia.europa.eu/juris/document/document.jsf?text=&docid=216555&pageIndex=0&doclang=PL&mode=lst&dir=&occ=first&part=1&cid=1254905">
wyroku TSUE w sprawie C-40/17
</a>
</p>
</>
),
};

View File

@ -1,26 +1,37 @@
import { RequestCluster } from '../../request-cluster';
function generateHostPage(
host: string,
cluster: RequestCluster,
index: number,
all_hosts: string[]
): { title: string; elements: any[]; visibleIf: string } {
function f(name: string, h = host) {
return `${h.replace(/\./g, '_')}|${name}`;
all_clusters: RequestCluster[]
): { title: string; elements: any[]; visibleIf?: string } {
function f(name: string, c = cluster) {
return `${c.id.replace(/\./g, '_')}|${name}`;
}
const previous_host: string | null = index > 0 ? all_hosts[index - 1] : null;
const previous_cluster: RequestCluster | null = index > 0 ? all_clusters[index - 1] : null;
function defaultValue(name: string) {
if (!previous_host) {
if (!previous_cluster) {
return {};
}
return { defaultValueExpression: `{${f(name, previous_host)}}` };
return { defaultValueExpression: `{${f(name, previous_cluster)}}` };
}
const domain = cluster.id;
let types_of_data: string[] = [];
if (cluster.exposesOrigin()) {
types_of_data.push('część Twojej historii przeglądania');
}
if (cluster.hasMarkedCookies()) {
types_of_data.push('unikalne ID z cookies');
}
const danych = types_of_data.join(', ');
return {
title: host,
title: cluster.id,
elements: [
{
type: 'radiogroup',
name: f('present'),
isRequired: true,
title: `Cel ujawnienia danych właścicielowi domeny ${host}`,
title: `Cel ujawnienia danych (${danych}) właścicielowi domeny ${domain}`,
...defaultValue('present'),
visibleIf: '{popup_type} != "none"',
choices: [
@ -76,7 +87,7 @@ function generateHostPage(
choices: [
{
value: 'claims_consent_but_sends_before_consent',
text: `Strona wysłała {moje} dane do ${host} zanim {wyraziłem} na to zgodę`,
text: `Strona wysłała {moje} dane do ${domain} zanim {wyraziłem} na to zgodę`,
},
{
value: 'claims_consent_but_there_was_no_easy_refuse',
@ -111,18 +122,18 @@ function generateHostPage(
},
{
type: 'text',
title: `Jak administrator opisał to, na czym polega uzasadniony interes w kontekście ${host}?`,
title: `Jak administrator opisał to, na czym polega uzasadniony interes w kontekście ${domain}?`,
name: f('legitimate_interest_description'),
visibleIf: `{${f('legitimate_interest_activity_specified')}} = 'vague'`,
placeholder: 'marketing',
defaultValueExpression:
index == 0
? 'marketing'
: `{${f('legitimate_interest_description', previous_host)}}`,
: `{${f('legitimate_interest_description', previous_cluster)}}`,
},
{
type: 'radiogroup',
title: `Czy domena ${host} należy do podmiotu spoza Europy (np. Google, Facebook)?`,
title: `Czy domena ${domain} należy do podmiotu spoza Europy (np. Google, Facebook)?`,
name: f('outside_eu'),
...defaultValue('outside_eu'),
visibleIf: `{${f('legitimate_interest_activity_specified')}} = "precise" or {${f(
@ -137,7 +148,7 @@ function generateHostPage(
},
{
type: 'radiogroup',
title: `Czy w {Twojej} ocenie wysłanie {Twoich} danych do właściciela domeny ${host} było konieczne do świadczenia zażądanej przez {Ciebie} usługi drogą elektroniczną?`,
title: `Czy w {Twojej} ocenie ujawnienie {Twoich} danych (${danych}) właścicielowi domeny ${domain} było konieczne do świadczenia zażądanej przez {Ciebie} usługi drogą elektroniczną?`,
name: f('was_processing_necessary'),
isRequired: true,
...defaultValue('was_processing_necessary'),
@ -154,7 +165,7 @@ function generateHostPage(
};
}
export default function generateSurveyQuestions(hosts: string[]) {
export default function generateSurveyQuestions(clusters: RequestCluster[]) {
return {
showQuestionNumbers: 'off',
showProgressBar: 'top',
@ -393,7 +404,7 @@ export default function generateSurveyQuestions(hosts: string[]) {
},
],
},
...hosts.map(generateHostPage),
...clusters.map(generateHostPage),
],
};
}

View File

@ -39,6 +39,7 @@ export default class NoInformationAtAllProblem extends Problem {
})
) {
explainers.push('cookies_are_pii');
explainers.push('responsibility_for_third_parties');
}
return explainers;
}

View File

@ -7,7 +7,7 @@ import { Problem } from './problem';
export class UnlawfulCookieAccess extends Problem {
getNecessaryExplainers(): ExplainerKey[] {
return [];
return ['cookies_are_pii', 'responsibility_for_third_parties'];
}
static qualifies(answers: ParsedAnswers, clusters: RequestCluster[]): boolean {
@ -76,7 +76,8 @@ export class UnlawfulCookieAccess extends Problem {
<li>
Użytkownik wyraził zgodę na takie przetwarzanie danych <em>po</em> tym, jak
został poinformowany bezpośrednio o celu uzyskania dostępu do tej
informacji;
informacji. Zgodnie z Art. 174 ustawy Prawo Telekomunikacyjne, taka zgoda
musiałaby spełniać warunki zgody ustalone przez RODO;
</li>
<li>
Dostęp do treści plików cookies jest konieczny do dostarczania usługi

View File

@ -1,15 +1,16 @@
import * as Survey from 'survey-react';
import { RequestCluster } from '../../request-cluster';
import RawAnswers from './raw-answers';
import useSurvey from './use-survey';
export default function Questions({
hosts,
clusters,
onComplete,
}: {
hosts: string[];
clusters: RequestCluster[];
onComplete: (data: RawAnswers) => void;
}) {
const survey = useSurvey(hosts, {
const survey = useSurvey(clusters, {
onComplete: (sender) => onComplete(sender.data),
});
if (!survey) {

View File

@ -35,9 +35,9 @@ function Report() {
<div {...{ 'data-version': counter }}>
{mode === 'survey' ? (
<Questions
hosts={Object.values(clusters)
.filter((cluster) => cluster.getMarkedRequests().length > 0)
.map((cluster) => cluster.id)}
clusters={Object.values(clusters).filter(
(cluster) => cluster.getMarkedRequests().length > 0
)}
onComplete={(answers) => {
setAnswers(parseAnswers(answers));
setMode('screenshots');

View File

@ -1,16 +1,17 @@
import * as React from 'react';
import * as Survey from 'survey-react';
import { RequestCluster } from '../../request-cluster';
import generateSurveyQuestions from './generate-survey-questions';
import RawAnswers from './raw-answers';
import verbs, { v } from './verbs';
export default function useSurvey(
hosts: string[],
clusters: RequestCluster[],
{ onComplete }: { onComplete: (sender: { data: RawAnswers }) => void }
): Survey.ReactSurveyModel {
const [survey, setSurvey] = React.useState<Survey.Model>(null);
React.useEffect(() => {
const model = generateSurveyQuestions(hosts);
const model = generateSurveyQuestions(clusters);
console.log(model);
const survey = new Survey.Model(model);
survey.onProcessTextValue.add(function (