Merge pull request #1321 from PicPeak/fix/1317-usage-portal-copy
feat(usage): plain link to the public usage portal, German opt-in copy
This commit is contained in:
@@ -317,3 +317,30 @@ it('states in the consent dialog that the connection only runs outwards', async
|
|||||||
await screen.findByText('productUsage.sectionOneWay');
|
await screen.findByText('productUsage.sectionOneWay');
|
||||||
await screen.findByText('productUsage.oneWay');
|
await screen.findByText('productUsage.oneWay');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The portal is public. Reaching it must not depend on having joined or on
|
||||||
|
// the 15-minute voting session that `connect` creates — an operator deciding
|
||||||
|
// whether to participate should be able to look at it first.
|
||||||
|
describe('the plain usage portal link', () => {
|
||||||
|
it('opens the collector in a new tab before participation, without a session', async () => {
|
||||||
|
mount();
|
||||||
|
const link = await screen.findByRole('link', { name: 'productUsage.openUsagePortal' });
|
||||||
|
expect(link).toHaveAttribute('href', 'https://usage.picpeak.app');
|
||||||
|
expect(link).toHaveAttribute('target', '_blank');
|
||||||
|
expect(link).toHaveAttribute('rel', 'noopener noreferrer');
|
||||||
|
expect(service.portalSession).not.toHaveBeenCalled();
|
||||||
|
// The session-bound link is a different thing and stays behind `connect`.
|
||||||
|
expect(screen.queryByText('productUsage.openPortal')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is not offered when the collector URL is unusable', async () => {
|
||||||
|
vi.mocked(service.status).mockResolvedValue({
|
||||||
|
...status,
|
||||||
|
collector_url: null,
|
||||||
|
collector_error: 'INVALID_COLLECTOR_URL'
|
||||||
|
});
|
||||||
|
mount();
|
||||||
|
await screen.findByText('productUsage.invalidCollectorUrl');
|
||||||
|
expect(screen.queryByRole('link', { name: 'productUsage.openUsagePortal' })).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from '../../../services/productUsage.service';
|
} from '../../../services/productUsage.service';
|
||||||
import {
|
import {
|
||||||
ArrowUpFromLine,
|
ArrowUpFromLine,
|
||||||
|
ExternalLink,
|
||||||
Globe,
|
Globe,
|
||||||
ListChecks,
|
ListChecks,
|
||||||
MessageSquare,
|
MessageSquare,
|
||||||
@@ -377,14 +378,29 @@ export default function ProductUsageTab() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{data.collector_url && (
|
{data.collector_url && (
|
||||||
<a
|
<>
|
||||||
className="text-sm text-primary-600 dark:text-primary-400 hover:underline self-center"
|
{/* The public portal itself, not the session-bound link below:
|
||||||
href={`${data.collector_url}/transparency`}
|
it needs neither participation nor a voting session, so an
|
||||||
target="_blank"
|
operator can look at the portal before deciding to join.
|
||||||
rel="noreferrer"
|
Styled as a button so it reads as an action, not a footnote. */}
|
||||||
>
|
<a
|
||||||
{t('productUsage.transparency')}
|
className="btn btn-outline btn-md"
|
||||||
</a>
|
href={data.collector_url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{t('productUsage.openUsagePortal')}
|
||||||
|
<ExternalLink className="ml-2 h-4 w-4" aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
className="text-sm text-primary-600 dark:text-primary-400 hover:underline self-center"
|
||||||
|
href={`${data.collector_url}/transparency`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{t('productUsage.transparency')}
|
||||||
|
</a>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -435,7 +435,7 @@
|
|||||||
"notice": "Optionale Nutzungsberichte zeigen, welche Funktionen für die Community wichtig sind. Die Übermittlung ist aus, bis Sie sich aktiv dafür entscheiden.",
|
"notice": "Optionale Nutzungsberichte zeigen, welche Funktionen für die Community wichtig sind. Die Übermittlung ist aus, bis Sie sich aktiv dafür entscheiden.",
|
||||||
"ignore": "Ignorieren",
|
"ignore": "Ignorieren",
|
||||||
"ignoreHint": "Wenn Sie ignorieren, erscheint dieser Hinweis nicht erneut — Sie können weiterhin unter Einstellungen → Produktnutzung teilnehmen.",
|
"ignoreHint": "Wenn Sie ignorieren, erscheint dieser Hinweis nicht erneut — Sie können weiterhin unter Einstellungen → Produktnutzung teilnehmen.",
|
||||||
"review": "Teilnahme prüfen",
|
"review": "Details ansehen",
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"loading": "Teilnahmeeinstellungen werden geladen…",
|
"loading": "Teilnahmeeinstellungen werden geladen…",
|
||||||
"failed": "Der Vorgang konnte nicht abgeschlossen werden. Prüfen Sie den Status und versuchen Sie es erneut.",
|
"failed": "Der Vorgang konnte nicht abgeschlossen werden. Prüfen Sie den Status und versuchen Sie es erneut.",
|
||||||
@@ -458,6 +458,7 @@
|
|||||||
"enable": "Produktnutzung aktivieren",
|
"enable": "Produktnutzung aktivieren",
|
||||||
"disable": "Deaktivieren & Daten löschen",
|
"disable": "Deaktivieren & Daten löschen",
|
||||||
"retry": "Erneut versuchen / fälligen Bericht senden",
|
"retry": "Erneut versuchen / fälligen Bericht senden",
|
||||||
|
"openUsagePortal": "Nutzungsportal öffnen",
|
||||||
"transparency": "Öffentliches Schema & Datenschutzhinweise",
|
"transparency": "Öffentliches Schema & Datenschutzhinweise",
|
||||||
"linkCollector": "Wohin Berichte gesendet werden",
|
"linkCollector": "Wohin Berichte gesendet werden",
|
||||||
"hash": "Ihr vertraulicher Abfrage-Hash",
|
"hash": "Ihr vertraulicher Abfrage-Hash",
|
||||||
|
|||||||
@@ -458,6 +458,7 @@
|
|||||||
"enable": "Enable product usage",
|
"enable": "Enable product usage",
|
||||||
"disable": "Disable & delete my data",
|
"disable": "Disable & delete my data",
|
||||||
"retry": "Retry / send if due",
|
"retry": "Retry / send if due",
|
||||||
|
"openUsagePortal": "Open usage portal",
|
||||||
"transparency": "Read the public schema & privacy details",
|
"transparency": "Read the public schema & privacy details",
|
||||||
"linkCollector": "Where reports are sent",
|
"linkCollector": "Where reports are sent",
|
||||||
"hash": "Your private lookup hash",
|
"hash": "Your private lookup hash",
|
||||||
|
|||||||
Reference in New Issue
Block a user