fix
@@ -313,15 +313,15 @@ const GAPS = {
|
||||
pl: "Członkowie zarządzają produktami i feedami. Administratorzy mogą też zapraszać współpracowników i zmieniać ustawienia firmy.",
|
||||
ja: "メンバーは商品とフィードを管理します。管理者は同僚の招待と会社設定の変更もできます。"
|
||||
},
|
||||
"Demo sandbox is empty — switch to A1 or connect a feed to see real catalog stats.": {
|
||||
es: "La zona de pruebas demo está vacía — cambia a A1 o conecta un feed para ver estadísticas reales del catálogo.",
|
||||
fr: "Le bac à sable démo est vide — basculez vers A1 ou connectez un flux pour voir de vraies stats catalogue.",
|
||||
de: "Demo-Sandbox ist leer — wechseln Sie zu A1 oder verbinden Sie einen Feed, um echte Katalogstatistiken zu sehen.",
|
||||
it: "La sandbox demo è vuota — passa ad A1 o collega un feed per vedere statistiche reali del catalogo.",
|
||||
pt: "A sandbox de demonstração está vazia — mude para A1 ou ligue um feed para ver estatísticas reais do catálogo.",
|
||||
nl: "Demo-sandbox is leeg — schakel over naar A1 of koppel een feed om echte catalogusstatistieken te zien.",
|
||||
pl: "Piaskownica demo jest pusta — przełącz na A1 lub podłącz feed, aby zobaczyć realne statystyki katalogu.",
|
||||
ja: "デモサンドボックスは空です — A1に切り替えるかフィードを接続して実際のカタログ統計を表示します。"
|
||||
"Demo sandbox is empty — connect a feed to see catalog stats.": {
|
||||
es: "La zona de pruebas demo está vacía — conecta un feed para ver estadísticas reales del catálogo.",
|
||||
fr: "Le bac à sable démo est vide — connectez un flux pour voir de vraies stats catalogue.",
|
||||
de: "Demo-Sandbox ist leer — verbinden Sie einen Feed, um echte Katalogstatistiken zu sehen.",
|
||||
it: "La sandbox demo è vuota — collega un feed per vedere statistiche reali del catalogo.",
|
||||
pt: "A sandbox de demonstração está vazia — ligue um feed para ver estatísticas reais do catálogo.",
|
||||
nl: "Demo-sandbox is leeg — koppel een feed om echte catalogusstatistieken te zien.",
|
||||
pl: "Piaskownica demo jest pusta — podłącz feed, aby zobaczyć realne statystyki katalogu.",
|
||||
ja: "デモサンドボックスは空です — フィードを接続して実際のカタログ統計を表示します。"
|
||||
},
|
||||
"Add a feed or upload a CSV to populate this workspace.": {
|
||||
es: "Añade un feed o sube un CSV para poblar este espacio de trabajo.",
|
||||
@@ -353,15 +353,15 @@ const GAPS = {
|
||||
pl: "Importuj → wzbogacaj → publikuj. Przejdź do następnego kroku dla {name}.",
|
||||
ja: "インポート → 強化 → 公開。{name} の次のステップへ。"
|
||||
},
|
||||
"Switch to A1 (or another seeded company) in the header, or connect a feed here to populate this sandbox.": {
|
||||
es: "Cambia a A1 (u otra empresa con datos) en el encabezado, o conecta un feed aquí para poblar esta zona de pruebas.",
|
||||
fr: "Basculez vers A1 (ou une autre entreprise seedée) dans l'en-tête, ou connectez un flux ici pour remplir ce bac à sable.",
|
||||
de: "Wechseln Sie in der Kopfzeile zu A1 (oder einem anderen Seed-Unternehmen) oder verbinden Sie hier einen Feed, um diese Sandbox zu füllen.",
|
||||
it: "Passa ad A1 (o un'altra azienda con dati) nell'intestazione, oppure collega un feed qui per popolare questa sandbox.",
|
||||
pt: "Mude para A1 (ou outra empresa com dados) no cabeçalho, ou ligue um feed aqui para preencher esta sandbox.",
|
||||
nl: "Schakel in de header over naar A1 (of een ander geseeded bedrijf), of koppel hier een feed om deze sandbox te vullen.",
|
||||
pl: "Przełącz na A1 (lub inną firmę z danymi) w nagłówku albo podłącz tu feed, aby wypełnić tę piaskownicę.",
|
||||
ja: "ヘッダーでA1(または別のシード済み会社)に切り替えるか、ここでフィードを接続してサンドボックスにデータを入れます。"
|
||||
"Connect a feed here to populate this sandbox, or switch to another company in the header.": {
|
||||
es: "Conecta un feed aquí para poblar esta zona de pruebas, o cambia a otra empresa en el encabezado.",
|
||||
fr: "Connectez un flux ici pour remplir ce bac à sable, ou basculez vers une autre entreprise dans l'en-tête.",
|
||||
de: "Verbinden Sie hier einen Feed, um diese Sandbox zu füllen, oder wechseln Sie in der Kopfzeile zu einem anderen Unternehmen.",
|
||||
it: "Collega un feed qui per popolare questa sandbox, oppure passa a un'altra azienda nell'intestazione.",
|
||||
pt: "Ligue um feed aqui para preencher esta sandbox, ou mude para outra empresa no cabeçalho.",
|
||||
nl: "Koppel hier een feed om deze sandbox te vullen, of schakel in de header over naar een ander bedrijf.",
|
||||
pl: "Podłącz tu feed, aby wypełnić tę piaskownicę, albo przełącz na inną firmę w nagłówku.",
|
||||
ja: "ここでフィードを接続してサンドボックスにデータを入れるか、ヘッダーで別の会社に切り替えます。"
|
||||
},
|
||||
"Connect a feed or upload a CSV to start building your catalog.": {
|
||||
es: "Conecta un feed o sube un CSV para empezar a crear tu catálogo.",
|
||||
|
||||
@@ -172,11 +172,11 @@ export const EXTRA = {
|
||||
"Los miembros gestionan productos y feeds. Los administradores también pueden invitar compañeros y cambiar la configuración de la empresa.",
|
||||
"settings.sendInvite": "Enviar invitación",
|
||||
"dashboard.demoEmptyHint":
|
||||
"La zona de pruebas demo está vacía — cambia a A1 o conecta un feed para ver estadísticas reales del catálogo.",
|
||||
"La zona de pruebas demo está vacía — conecta un feed para ver estadísticas reales del catálogo.",
|
||||
"dashboard.workflowHint": "Importar → enriquecer → publicar. Salta al siguiente paso para {name}.",
|
||||
"dashboard.overviewHint": "Totales en vivo para {name}",
|
||||
"dashboard.demoEmptyMessage":
|
||||
"Cambia a A1 (u otra empresa con datos) en el encabezado, o conecta un feed aquí para poblar esta zona de pruebas.",
|
||||
"Conecta un feed aquí para poblar esta zona de pruebas, o cambia a otra empresa en el encabezado.",
|
||||
"dashboard.emptyTitle": "Aún no hay datos de catálogo",
|
||||
"dashboard.emptyMessage": "Conecta un feed o sube un CSV para empezar a crear tu catálogo.",
|
||||
"dashboard.connectFeedAnyway": "Conectar feed de todos modos",
|
||||
|
||||
@@ -142,10 +142,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "Rol",
|
||||
"settings.inviteRoleHint": "Los miembros gestionan productos y feeds. Los administradores también pueden invitar compañeros y cambiar la configuración de la empresa.",
|
||||
"settings.sendInvite": "Enviar invitación",
|
||||
"dashboard.demoEmptyHint": "La zona de pruebas demo está vacía — cambia a A1 o conecta un feed para ver estadísticas reales del catálogo.",
|
||||
"dashboard.demoEmptyHint": "La zona de pruebas demo está vacía — conecta un feed para ver estadísticas reales del catálogo.",
|
||||
"dashboard.workflowHint": "Importar → enriquecer → publicar. Salta al siguiente paso para {name}.",
|
||||
"dashboard.overviewHint": "Totales en vivo para {name}",
|
||||
"dashboard.demoEmptyMessage": "Cambia a A1 (u otra empresa con datos) en el encabezado, o conecta un feed aquí para poblar esta zona de pruebas.",
|
||||
"dashboard.demoEmptyMessage": "Conecta un feed aquí para poblar esta zona de pruebas, o cambia a otra empresa en el encabezado.",
|
||||
"dashboard.emptyTitle": "Aún no hay datos de catálogo",
|
||||
"dashboard.emptyMessage": "Conecta un feed o sube un CSV para empezar a crear tu catálogo.",
|
||||
"dashboard.connectFeedAnyway": "Conectar feed de todos modos",
|
||||
@@ -375,10 +375,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "Rôle",
|
||||
"settings.inviteRoleHint": "Les membres gèrent les produits et les flux. Les administrateurs peuvent aussi inviter des coéquipiers et modifier les paramètres de l'entreprise.",
|
||||
"settings.sendInvite": "Envoyer l'invitation",
|
||||
"dashboard.demoEmptyHint": "Le bac à sable démo est vide — basculez vers A1 ou connectez un flux pour voir de vraies stats catalogue.",
|
||||
"dashboard.demoEmptyHint": "Le bac à sable démo est vide — connectez un flux pour voir de vraies stats catalogue.",
|
||||
"dashboard.workflowHint": "Importer → enrichir → publier. Passez à l'étape suivante pour {name}.",
|
||||
"dashboard.overviewHint": "Totaux en direct pour {name}",
|
||||
"dashboard.demoEmptyMessage": "Basculez vers A1 (ou une autre entreprise seedée) dans l'en-tête, ou connectez un flux ici pour remplir ce bac à sable.",
|
||||
"dashboard.demoEmptyMessage": "Connectez un flux ici pour remplir ce bac à sable, ou basculez vers une autre entreprise dans l'en-tête.",
|
||||
"dashboard.emptyTitle": "Pas encore de données catalogue",
|
||||
"dashboard.emptyMessage": "Connectez un flux ou téléversez un CSV pour commencer à construire votre catalogue.",
|
||||
"dashboard.connectFeedAnyway": "Connecter un flux quand même",
|
||||
@@ -606,10 +606,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "Rolle",
|
||||
"settings.inviteRoleHint": "Mitglieder verwalten Produkte und Feeds. Admins können auch Teammitglieder einladen und Unternehmenseinstellungen ändern.",
|
||||
"settings.sendInvite": "Einladung senden",
|
||||
"dashboard.demoEmptyHint": "Demo-Sandbox ist leer — wechseln Sie zu A1 oder verbinden Sie einen Feed, um echte Katalogstatistiken zu sehen.",
|
||||
"dashboard.demoEmptyHint": "Demo-Sandbox ist leer — verbinden Sie einen Feed, um echte Katalogstatistiken zu sehen.",
|
||||
"dashboard.workflowHint": "Importieren → anreichern → veröffentlichen. Zum nächsten Schritt für {name}.",
|
||||
"dashboard.overviewHint": "Live-Summen für {name}",
|
||||
"dashboard.demoEmptyMessage": "Wechseln Sie in der Kopfzeile zu A1 (oder einem anderen Seed-Unternehmen) oder verbinden Sie hier einen Feed, um diese Sandbox zu füllen.",
|
||||
"dashboard.demoEmptyMessage": "Verbinden Sie hier einen Feed, um diese Sandbox zu füllen, oder wechseln Sie in der Kopfzeile zu einem anderen Unternehmen.",
|
||||
"dashboard.emptyTitle": "Noch keine Katalogdaten",
|
||||
"dashboard.emptyMessage": "Verbinden Sie einen Feed oder laden Sie eine CSV hoch, um Ihren Katalog aufzubauen.",
|
||||
"dashboard.connectFeedAnyway": "Feed trotzdem verbinden",
|
||||
@@ -837,10 +837,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "Ruolo",
|
||||
"settings.inviteRoleHint": "I membri gestiscono prodotti e feed. Gli amministratori possono anche invitare colleghi e modificare le impostazioni dell'azienda.",
|
||||
"settings.sendInvite": "Invia invito",
|
||||
"dashboard.demoEmptyHint": "La sandbox demo è vuota — passa ad A1 o collega un feed per vedere statistiche reali del catalogo.",
|
||||
"dashboard.demoEmptyHint": "La sandbox demo è vuota — collega un feed per vedere statistiche reali del catalogo.",
|
||||
"dashboard.workflowHint": "Importa → arricchisci → pubblica. Vai al passo successivo per {name}.",
|
||||
"dashboard.overviewHint": "Totali in tempo reale per {name}",
|
||||
"dashboard.demoEmptyMessage": "Passa ad A1 (o un'altra azienda con dati) nell'intestazione, oppure collega un feed qui per popolare questa sandbox.",
|
||||
"dashboard.demoEmptyMessage": "Collega un feed qui per popolare questa sandbox, oppure passa a un'altra azienda nell'intestazione.",
|
||||
"dashboard.emptyTitle": "Ancora nessun dato di catalogo",
|
||||
"dashboard.emptyMessage": "Collega un feed o carica un CSV per iniziare a costruire il catalogo.",
|
||||
"dashboard.connectFeedAnyway": "Collega comunque un feed",
|
||||
@@ -1068,10 +1068,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "Papel",
|
||||
"settings.inviteRoleHint": "Os membros gerem produtos e feeds. Os administradores também podem convidar colegas e alterar as definições da empresa.",
|
||||
"settings.sendInvite": "Enviar convite",
|
||||
"dashboard.demoEmptyHint": "A sandbox de demonstração está vazia — mude para A1 ou ligue um feed para ver estatísticas reais do catálogo.",
|
||||
"dashboard.demoEmptyHint": "A sandbox de demonstração está vazia — ligue um feed para ver estatísticas reais do catálogo.",
|
||||
"dashboard.workflowHint": "Importar → enriquecer → publicar. Salte para o passo seguinte para {name}.",
|
||||
"dashboard.overviewHint": "Totais em direto para {name}",
|
||||
"dashboard.demoEmptyMessage": "Mude para A1 (ou outra empresa com dados) no cabeçalho, ou ligue um feed aqui para preencher esta sandbox.",
|
||||
"dashboard.demoEmptyMessage": "Ligue um feed aqui para preencher esta sandbox, ou mude para outra empresa no cabeçalho.",
|
||||
"dashboard.emptyTitle": "Ainda sem dados de catálogo",
|
||||
"dashboard.emptyMessage": "Ligue um feed ou carregue um CSV para começar a criar o seu catálogo.",
|
||||
"dashboard.connectFeedAnyway": "Ligar feed mesmo assim",
|
||||
@@ -1299,10 +1299,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "Rol",
|
||||
"settings.inviteRoleHint": "Leden beheren producten en feeds. Beheerders kunnen ook teamleden uitnodigen en bedrijfsinstellingen wijzigen.",
|
||||
"settings.sendInvite": "Uitnodiging verzenden",
|
||||
"dashboard.demoEmptyHint": "Demo-sandbox is leeg — schakel over naar A1 of koppel een feed om echte catalogusstatistieken te zien.",
|
||||
"dashboard.demoEmptyHint": "Demo-sandbox is leeg — koppel een feed om echte catalogusstatistieken te zien.",
|
||||
"dashboard.workflowHint": "Importeren → verrijken → publiceren. Ga naar de volgende stap voor {name}.",
|
||||
"dashboard.overviewHint": "Live totalen voor {name}",
|
||||
"dashboard.demoEmptyMessage": "Schakel in de header over naar A1 (of een ander geseeded bedrijf), of koppel hier een feed om deze sandbox te vullen.",
|
||||
"dashboard.demoEmptyMessage": "Koppel hier een feed om deze sandbox te vullen, of schakel in de header over naar een ander bedrijf.",
|
||||
"dashboard.emptyTitle": "Nog geen catalogusgegevens",
|
||||
"dashboard.emptyMessage": "Koppel een feed of upload een CSV om uw catalogus op te bouwen.",
|
||||
"dashboard.connectFeedAnyway": "Feed toch koppelen",
|
||||
@@ -1530,10 +1530,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "Rola",
|
||||
"settings.inviteRoleHint": "Członkowie zarządzają produktami i feedami. Administratorzy mogą też zapraszać współpracowników i zmieniać ustawienia firmy.",
|
||||
"settings.sendInvite": "Wyślij zaproszenie",
|
||||
"dashboard.demoEmptyHint": "Piaskownica demo jest pusta — przełącz na A1 lub podłącz feed, aby zobaczyć realne statystyki katalogu.",
|
||||
"dashboard.demoEmptyHint": "Piaskownica demo jest pusta — podłącz feed, aby zobaczyć realne statystyki katalogu.",
|
||||
"dashboard.workflowHint": "Importuj → wzbogacaj → publikuj. Przejdź do następnego kroku dla {name}.",
|
||||
"dashboard.overviewHint": "Bieżące sumy dla {name}",
|
||||
"dashboard.demoEmptyMessage": "Przełącz na A1 (lub inną firmę z danymi) w nagłówku albo podłącz tu feed, aby wypełnić tę piaskownicę.",
|
||||
"dashboard.demoEmptyMessage": "Podłącz tu feed, aby wypełnić tę piaskownicę, albo przełącz na inną firmę w nagłówku.",
|
||||
"dashboard.emptyTitle": "Brak jeszcze danych katalogu",
|
||||
"dashboard.emptyMessage": "Podłącz feed lub prześlij CSV, aby zacząć budować katalog.",
|
||||
"dashboard.connectFeedAnyway": "Podłącz feed mimo to",
|
||||
@@ -1761,10 +1761,10 @@ export const EXTRA = {
|
||||
"settings.inviteRole": "ロール",
|
||||
"settings.inviteRoleHint": "メンバーは商品とフィードを管理します。管理者は同僚の招待と会社設定の変更もできます。",
|
||||
"settings.sendInvite": "招待を送信",
|
||||
"dashboard.demoEmptyHint": "デモサンドボックスは空です — A1に切り替えるかフィードを接続して実際のカタログ統計を表示します。",
|
||||
"dashboard.demoEmptyHint": "デモサンドボックスは空です — フィードを接続して実際のカタログ統計を表示します。",
|
||||
"dashboard.workflowHint": "インポート → 強化 → 公開。{name} の次のステップへ。",
|
||||
"dashboard.overviewHint": "{name} のリアルタイム合計",
|
||||
"dashboard.demoEmptyMessage": "ヘッダーでA1(または別のシード済み会社)に切り替えるか、ここでフィードを接続してサンドボックスにデータを入れます。",
|
||||
"dashboard.demoEmptyMessage": "ここでフィードを接続してサンドボックスにデータを入れるか、ヘッダーで別の会社に切り替えます。",
|
||||
"dashboard.emptyTitle": "まだカタログデータがありません",
|
||||
"dashboard.emptyMessage": "フィードを接続するかCSVをアップロードして、カタログの構築を開始します。",
|
||||
"dashboard.connectFeedAnyway": "それでもフィードを接続",
|
||||
|
||||
@@ -219,15 +219,15 @@
|
||||
"pl": "Najpierw ustaw hasło:",
|
||||
"ja": "先にパスワードを設定:"
|
||||
},
|
||||
"use the invite link from your email. If the link went to an old address (email drift), ask a company admin to re-issue a set-password invite to {email}.": {
|
||||
"es": "usa el enlace de invitación de tu correo. Si el enlace fue a una dirección antigua (cambio de correo), pide a un administrador de la empresa que emita una nueva invitación para establecer contraseña a {email}.",
|
||||
"fr": "utilisez le lien d'invitation de votre e-mail. Si le lien a été envoyé à une ancienne adresse (dérive d'e-mail), demandez à un administrateur de l'entreprise de renvoyer une invitation de définition de mot de passe à {email}.",
|
||||
"de": "nutzen Sie den Einladungslink aus Ihrer E-Mail. Wenn der Link an eine alte Adresse ging (E-Mail-Drift), bitten Sie einen Unternehmens-Admin, eine neue Passwort-Einladung an {email} auszustellen.",
|
||||
"it": "usa il link di invito dalla tua email. Se il link è andato a un indirizzo vecchio (deriva email), chiedi a un amministratore dell'azienda di riemettere un invito per impostare la password a {email}.",
|
||||
"pt": "utilize o link do convite do seu e-mail. Se o link foi para um endereço antigo (desvio de e-mail), peça a um administrador da empresa para emitir um novo convite de definição de palavra-passe para {email}.",
|
||||
"nl": "gebruik de uitnodigingslink uit uw e-mail. Als de link naar een oud adres ging (e-maildrift), vraag dan een bedrijfsbeheerder om een nieuwe set-wachtwoorduitnodiging naar {email} te sturen.",
|
||||
"pl": "użyj linku zaproszenia z e-maila. Jeśli link poszedł na stary adres (dryf e-mail), poproś administratora firmy o ponowne wystawienie zaproszenia do ustawienia hasła na {email}.",
|
||||
"ja": "メールの招待リンクを使用してください。リンクが古いアドレスに送られた場合(メール変更)、会社の管理者に {email} 向けのパスワード設定招待の再発行を依頼してください。"
|
||||
"use the invite link from your email. If you need a new link, ask a company admin to re-issue a set-password link to {email}.": {
|
||||
"es": "usa el enlace de invitación de tu correo. Si necesitas un enlace nuevo, pide a un administrador de la empresa que reemita un enlace para establecer contraseña a {email}.",
|
||||
"fr": "utilisez le lien d'invitation de votre e-mail. Si vous avez besoin d'un nouveau lien, demandez à un administrateur de l'entreprise de réémettre un lien de définition de mot de passe à {email}.",
|
||||
"de": "nutzen Sie den Einladungslink aus Ihrer E-Mail. Wenn Sie einen neuen Link brauchen, bitten Sie einen Unternehmens-Admin, einen Link zum Festlegen des Passworts an {email} auszustellen.",
|
||||
"it": "usa il link di invito dalla tua email. Se ti serve un nuovo link, chiedi a un amministratore dell'azienda di riemettere un link per impostare la password a {email}.",
|
||||
"pt": "utilize o link do convite do seu e-mail. Se precisar de um novo link, peça a um administrador da empresa para reemitir um link de definição de palavra-passe para {email}.",
|
||||
"nl": "gebruik de uitnodigingslink uit uw e-mail. Als u een nieuwe link nodig hebt, vraag dan een bedrijfsbeheerder om een set-wachtwoordlink opnieuw uit te geven naar {email}.",
|
||||
"pl": "użyj linku zaproszenia z e-maila. Jeśli potrzebujesz nowego linku, poproś administratora firmy o ponowne wystawienie linku do ustawienia hasła na {email}.",
|
||||
"ja": "メールの招待リンクを使用してください。新しいリンクが必要な場合は、会社の管理者に {email} 向けのパスワード設定リンクの再発行を依頼してください。"
|
||||
},
|
||||
"your email": {
|
||||
"es": "tu correo",
|
||||
@@ -549,15 +549,15 @@
|
||||
"pl": "To zaproszenie jest nieprawidłowe lub wygasło. Poproś administratora firmy o nowe zaproszenie, a następnie otwórz nowy link (lub wklej nowy token poniżej).",
|
||||
"ja": "この招待は無効または期限切れです。会社の管理者に新しい招待の送信を依頼し、新しいリンクを開くか(下に新しいトークンを貼り付けてください)。"
|
||||
},
|
||||
"This set-password link is invalid or expired. Ask a company or platform admin to re-issue it, then open the new link (or paste the new token below).": {
|
||||
"es": "Este enlace para establecer contraseña no es válido o ha caducado. Pide a un administrador de la empresa o de la plataforma que lo reemita y abre el nuevo enlace (o pega el nuevo token abajo).",
|
||||
"fr": "Ce lien de définition de mot de passe est invalide ou expiré. Demandez à un administrateur de l'entreprise ou de la plateforme de le réémettre, puis ouvrez le nouveau lien (ou collez le nouveau jeton ci-dessous).",
|
||||
"de": "Dieser Passwort-Link ist ungültig oder abgelaufen. Bitten Sie einen Unternehmens- oder Plattform-Admin um Neuausstellung und öffnen Sie den neuen Link (oder fügen Sie das neue Token unten ein).",
|
||||
"it": "Questo link per impostare la password non è valido o è scaduto. Chiedi a un amministratore dell'azienda o della piattaforma di riemetterlo, poi apri il nuovo link (o incolla il nuovo token qui sotto).",
|
||||
"pt": "Este link de definição de palavra-passe é inválido ou expirou. Peça a um administrador da empresa ou da plataforma para o reemitir e abra o novo link (ou cole o novo token abaixo).",
|
||||
"nl": "Deze set-wachtwoordlink is ongeldig of verlopen. Vraag een bedrijfs- of platformbeheerder om hem opnieuw uit te geven en open de nieuwe link (of plak het nieuwe token hieronder).",
|
||||
"pl": "Ten link do ustawienia hasła jest nieprawidłowy lub wygasł. Poproś administratora firmy lub platformy o ponowne wystawienie, a następnie otwórz nowy link (lub wklej nowy token poniżej).",
|
||||
"ja": "このパスワード設定リンクは無効または期限切れです。会社またはプラットフォームの管理者に再発行を依頼し、新しいリンクを開くか(下に新しいトークンを貼り付けてください)。"
|
||||
"This set-password link is invalid or expired. Ask a company admin to re-issue a set-password link to this email, then open the new link (or paste the new token below).": {
|
||||
"es": "Este enlace para establecer contraseña no es válido o ha caducado. Pide a un administrador de la empresa que reemita un enlace para establecer contraseña a este correo y abre el nuevo enlace (o pega el nuevo token abajo).",
|
||||
"fr": "Ce lien de définition de mot de passe est invalide ou expiré. Demandez à un administrateur de l'entreprise de réémettre un lien de définition de mot de passe vers cet e-mail, puis ouvrez le nouveau lien (ou collez le nouveau jeton ci-dessous).",
|
||||
"de": "Dieser Passwort-Link ist ungültig oder abgelaufen. Bitten Sie einen Unternehmens-Admin, einen Link zum Festlegen des Passworts an diese E-Mail auszustellen, und öffnen Sie den neuen Link (oder fügen Sie das neue Token unten ein).",
|
||||
"it": "Questo link per impostare la password non è valido o è scaduto. Chiedi a un amministratore dell'azienda di riemettere un link per impostare la password a questa email, poi apri il nuovo link (o incolla il nuovo token qui sotto).",
|
||||
"pt": "Este link de definição de palavra-passe é inválido ou expirou. Peça a um administrador da empresa para reemitir um link de definição de palavra-passe para este e-mail e abra o novo link (ou cole o novo token abaixo).",
|
||||
"nl": "Deze set-wachtwoordlink is ongeldig of verlopen. Vraag een bedrijfsbeheerder om een set-wachtwoordlink opnieuw uit te geven naar dit e-mailadres en open de nieuwe link (of plak het nieuwe token hieronder).",
|
||||
"pl": "Ten link do ustawienia hasła jest nieprawidłowy lub wygasł. Poproś administratora firmy o ponowne wystawienie linku do ustawienia hasła na ten e-mail, a następnie otwórz nowy link (lub wklej nowy token poniżej).",
|
||||
"ja": "このパスワード設定リンクは無効または期限切れです。会社の管理者にこのメール向けのパスワード設定リンクの再発行を依頼し、新しいリンクを開くか(下に新しいトークンを貼り付けてください)。"
|
||||
},
|
||||
"You're signed in as a different email than this invite.": {
|
||||
"es": "Has iniciado sesión con un correo distinto al de esta invitación.",
|
||||
@@ -569,7 +569,7 @@
|
||||
"pl": "Jesteś zalogowany na inny e-mail niż w tym zaproszeniu.",
|
||||
"ja": "この招待とは別のメールアドレスでログインしています。"
|
||||
},
|
||||
"Expired link? Ask an admin to re-issue — there is no self-serve resend API. Platform admins:": {
|
||||
"Expired link? Ask a company admin to re-issue — there is no self-serve resend API.": {
|
||||
"es": "¿Enlace caducado? Pide a un administrador que lo reemita — no hay API de reenvío autoservicio. Administradores de plataforma:",
|
||||
"fr": "Lien expiré ? Demandez à un administrateur de le réémettre — il n'y a pas d'API de renvoi en libre-service. Administrateurs de plateforme :",
|
||||
"de": "Abgelaufener Link? Bitten Sie einen Admin um Neuausstellung — es gibt keine Self-Service-API zum erneuten Senden. Plattform-Admins:",
|
||||
@@ -729,7 +729,7 @@
|
||||
"pl": "Ścieżka ponownego wystawienia:",
|
||||
"ja": "再発行の手順:"
|
||||
},
|
||||
"if your real login email changed (email drift), ask a company admin to revoke this invite and send a new one to the email you use to sign in. Platform admins can also re-issue set-password links from Admin → Users.": {
|
||||
"ask a company admin to re-issue a set-password link to this email, or to revoke this invite and send a new one to the email you use to sign in.": {
|
||||
"es": "si cambió tu correo real de acceso (desfase de correo), pide a un administrador de la empresa que revoque esta invitación y envíe una nueva al correo con el que inicias sesión. Los administradores de plataforma también pueden reemitir enlaces para establecer contraseña desde Admin → Usuarios.",
|
||||
"fr": "si votre vrai e-mail de connexion a changé (dérive d'e-mail), demandez à un administrateur de l'entreprise de révoquer cette invitation et d'en envoyer une nouvelle à l'e-mail que vous utilisez pour vous connecter. Les administrateurs de la plateforme peuvent aussi réémettre des liens de définition de mot de passe depuis Admin → Utilisateurs.",
|
||||
"de": "wenn sich Ihre echte Anmelde-E-Mail geändert hat (E-Mail-Drift), bitten Sie einen Unternehmens-Admin, diese Einladung zu widerrufen und eine neue an die E-Mail zu senden, mit der Sie sich anmelden. Plattform-Admins können Passwort-Links auch unter Admin → Benutzer erneut ausstellen.",
|
||||
|
||||
@@ -57,19 +57,24 @@ export const handle: Handle = async ({ event, resolve }) => {
|
||||
}
|
||||
|
||||
const pathname = event.url.pathname;
|
||||
const authCredentialPath =
|
||||
pathname === "/login" ||
|
||||
pathname === "/register" ||
|
||||
pathname === "/accept-invite" ||
|
||||
pathname === "/forgot-password" ||
|
||||
pathname === "/reset-password";
|
||||
// Never keep credentials in the query string (e.g. native GET before hydration).
|
||||
if (
|
||||
(pathname === "/login" ||
|
||||
pathname === "/register" ||
|
||||
pathname === "/accept-invite" ||
|
||||
pathname === "/forgot-password" ||
|
||||
pathname === "/reset-password") &&
|
||||
event.url.searchParams.has("password")
|
||||
) {
|
||||
if (authCredentialPath && event.url.searchParams.has("password")) {
|
||||
const clean = new URL(event.url);
|
||||
clean.searchParams.delete("password");
|
||||
clean.searchParams.delete("token");
|
||||
redirect(303, `${clean.pathname}${clean.search}`);
|
||||
}
|
||||
// Redact invite/reset tokens from SSR page.url. Do not 303-strip: old emails
|
||||
// still send ?token= and the client reads window.location once, then replaceState.
|
||||
if (authCredentialPath && event.url.searchParams.has("token")) {
|
||||
event.url.searchParams.delete("token");
|
||||
}
|
||||
const isRapiDocVendor = pathname.startsWith("/vendor/rapidoc/");
|
||||
|
||||
// Serve precompressed RapiDoc when client accepts gzip (copy-rapidoc-ui.mjs).
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
import { browser } from "$app/environment";
|
||||
import { env } from "$env/dynamic/public";
|
||||
import { redactSensitiveUrl } from "./auth-link-token";
|
||||
import {
|
||||
CONSENT_STORAGE_KEY,
|
||||
CONSENT_WAIT_FOR_UPDATE_MS,
|
||||
@@ -165,9 +166,9 @@ export function trackPageview(path: string, opts?: { title?: string; location?:
|
||||
if (!isAnalyticsGranted()) return;
|
||||
pushDataLayer({
|
||||
event: "page_view",
|
||||
page_path: path,
|
||||
page_path: redactSensitiveUrl(path),
|
||||
page_title: opts?.title ?? document.title,
|
||||
page_location: opts?.location ?? window.location.href
|
||||
page_location: redactSensitiveUrl(opts?.location ?? window.location.href)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -90,13 +90,21 @@ describe("System assistant matching", () => {
|
||||
["ai integrations", "open_ai_integrations"],
|
||||
["email sending", "open_email_integrations"],
|
||||
["usage and billing", "open_billing"],
|
||||
["company settings", "open_settings"],
|
||||
["platform admin", "open_admin"]
|
||||
["company settings", "open_settings"]
|
||||
] as const;
|
||||
for (const [utterance, id] of cases) {
|
||||
assert.equal(matchIntent(utterance)?.intent.id, id, utterance);
|
||||
}
|
||||
});
|
||||
|
||||
it("does not send customers to platform admin", () => {
|
||||
assert.notEqual(matchIntent("platform admin")?.intent.id, "open_admin");
|
||||
assert.notEqual(matchIntent("go to admin")?.intent.id, "open_admin");
|
||||
});
|
||||
|
||||
it("matches open_admin only when staff intents are allowed", () => {
|
||||
assert.equal(matchIntent("platform admin", { allowStaffIntents: true })?.intent.id, "open_admin");
|
||||
});
|
||||
});
|
||||
|
||||
describe("bot / AI identity answers", () => {
|
||||
@@ -114,10 +122,11 @@ describe("bot / AI identity answers", () => {
|
||||
assert.equal(matchIntent("are you an LLM chatbot")?.intent.id, "identity_system");
|
||||
});
|
||||
|
||||
it("identity reply says System assistant and denies LLM chatbot", () => {
|
||||
it("identity reply says System assistant without LLM chatbot wording", () => {
|
||||
const msg = buildIdentityReply();
|
||||
assert.match(msg.text, /System assistant/i);
|
||||
assert.match(msg.text, /not an LLM chatbot/i);
|
||||
assert.match(msg.text, /navigate Descrybe/i);
|
||||
assert.doesNotMatch(msg.text, /LLM chatbot/i);
|
||||
assert.doesNotMatch(msg.text, /\bno LLM\b/i);
|
||||
assert.doesNotMatch(msg.text, /\bno AI\b/i);
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ export function buildIdentityReply(): AssistantMessage {
|
||||
return makeMessage({
|
||||
role: "assistant",
|
||||
kind: "text",
|
||||
text: "I am not an LLM chatbot. I am the System assistant — I help you navigate Descrybe, run supported actions after you confirm, and guide setup using built-in workflows."
|
||||
text: "I am the System assistant — I help you navigate Descrybe, run supported actions after you confirm, and guide setup using built-in workflows."
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ export type {
|
||||
|
||||
export { INTENT_REGISTRY, intentById, QUICK_START_REPLIES } from "./intents.ts";
|
||||
export { matchIntent, matchIdentityQuestion, normalizeUtterance, extractUrl } from "./match.ts";
|
||||
export type { MatchIntentOptions } from "./match.ts";
|
||||
export {
|
||||
makeMessage,
|
||||
idleFlow,
|
||||
|
||||
@@ -481,6 +481,7 @@ export const INTENT_REGISTRY: IntentDefinition[] = [
|
||||
description: "Navigate to Platform admin (staff only).",
|
||||
requiresConfirm: false,
|
||||
canExecute: false,
|
||||
staffOnly: true,
|
||||
route: "/admin",
|
||||
selector: '[data-assistant-target="nav-admin"],[data-tour="nav-admin"]',
|
||||
guideSteps: [{ title: "You're on Platform admin", detail: "Users, billing, support, and gates" }]
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { INTENT_REGISTRY } from "./intents.ts";
|
||||
import type { IntentMatch } from "./types.ts";
|
||||
|
||||
export type MatchIntentOptions = {
|
||||
/** Include staffOnly intents such as open_admin. Default false so customers are not sent to /admin. */
|
||||
allowStaffIntents?: boolean;
|
||||
};
|
||||
|
||||
const URL_RE = /https?:\/\/[^\s<>"']+/i;
|
||||
|
||||
/** Normalize for phrase/keyword matching. */
|
||||
@@ -40,7 +45,7 @@ export function matchIdentityQuestion(raw: string): boolean {
|
||||
* Score intents by phrase containment and keyword hits.
|
||||
* Returns null when nothing clears the confidence floor.
|
||||
*/
|
||||
export function matchIntent(raw: string): IntentMatch | null {
|
||||
export function matchIntent(raw: string, opts?: MatchIntentOptions): IntentMatch | null {
|
||||
const text = normalizeUtterance(raw);
|
||||
if (!text) return null;
|
||||
|
||||
@@ -54,6 +59,7 @@ export function matchIntent(raw: string): IntentMatch | null {
|
||||
|
||||
for (const intent of INTENT_REGISTRY) {
|
||||
if (intent.id === "identity_system") continue;
|
||||
if (intent.staffOnly && !opts?.allowStaffIntents) continue;
|
||||
let score = 0;
|
||||
|
||||
for (const phrase of intent.phrases) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { trackEvent } from "$lib/analytics";
|
||||
import { authSession } from "$lib/auth-session.svelte";
|
||||
import { intentById, QUICK_START_REPLIES } from "./intents.ts";
|
||||
import {
|
||||
buildApiExamplesMessage,
|
||||
@@ -557,7 +558,9 @@ function createAssistantController() {
|
||||
return;
|
||||
}
|
||||
|
||||
const matched = matchIntent(text);
|
||||
const matched = matchIntent(text, {
|
||||
allowStaffIntents: authSession.isSupportDesk
|
||||
});
|
||||
if (!matched) {
|
||||
push(buildUnknownReply());
|
||||
return;
|
||||
|
||||
@@ -100,6 +100,8 @@ export type IntentDefinition = {
|
||||
/** Prefer data-assistant-target; falls back to data-tour. */
|
||||
selector?: string;
|
||||
guideSteps: AssistantStep[];
|
||||
/** When true, omit from matchIntent unless allowStaffIntents. */
|
||||
staffOnly?: boolean;
|
||||
};
|
||||
|
||||
export type IntentMatch = {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { consumeAuthLinkSecrets, redactSensitiveUrl, tokenFromHash } from "./auth-link-token.ts";
|
||||
|
||||
describe("tokenFromHash", () => {
|
||||
it("reads token from hash params", () => {
|
||||
assert.equal(tokenFromHash("#token=abc123"), "abc123");
|
||||
assert.equal(tokenFromHash("token=abc123&mode=set-password"), "abc123");
|
||||
assert.equal(tokenFromHash("#mode=set-password"), "");
|
||||
});
|
||||
});
|
||||
|
||||
describe("consumeAuthLinkSecrets", () => {
|
||||
it("prefers hash token over query and strips both", () => {
|
||||
const got = consumeAuthLinkSecrets(
|
||||
"https://app.example.com/accept-invite?token=old&mode=set-password#token=fresh&mode=set-password"
|
||||
);
|
||||
assert.equal(got.token, "fresh");
|
||||
assert.equal(got.mode, "set-password");
|
||||
assert.equal(got.cleanedPathSearch, "/accept-invite?mode=set-password");
|
||||
assert.equal(got.stripped, true);
|
||||
});
|
||||
|
||||
it("accepts legacy query token once then strips it", () => {
|
||||
const got = consumeAuthLinkSecrets(
|
||||
"https://app.example.com/accept-invite?token=legacyTok&mode=set-password"
|
||||
);
|
||||
assert.equal(got.token, "legacyTok");
|
||||
assert.equal(got.mode, "set-password");
|
||||
assert.equal(got.cleanedPathSearch, "/accept-invite?mode=set-password");
|
||||
assert.equal(got.stripped, true);
|
||||
});
|
||||
|
||||
it("reads invite hash without query", () => {
|
||||
const got = consumeAuthLinkSecrets("https://app.example.com/accept-invite#token=invTok");
|
||||
assert.equal(got.token, "invTok");
|
||||
assert.equal(got.mode, "");
|
||||
assert.equal(got.cleanedPathSearch, "/accept-invite");
|
||||
assert.equal(got.stripped, true);
|
||||
});
|
||||
|
||||
it("leaves the URL alone when no token is present", () => {
|
||||
const got = consumeAuthLinkSecrets("https://app.example.com/accept-invite");
|
||||
assert.equal(got.token, "");
|
||||
assert.equal(got.stripped, false);
|
||||
assert.equal(got.cleanedPathSearch, "/accept-invite");
|
||||
});
|
||||
});
|
||||
|
||||
describe("redactSensitiveUrl", () => {
|
||||
it("redacts query token and password", () => {
|
||||
assert.equal(
|
||||
redactSensitiveUrl("/accept-invite?token=secret&mode=set-password"),
|
||||
"/accept-invite?token=REDACTED&mode=set-password"
|
||||
);
|
||||
});
|
||||
|
||||
it("redacts hash token and docs API keys in page_location", () => {
|
||||
const got = redactSensitiveUrl(
|
||||
"https://app.example.com/accept-invite#token=secret&mode=set-password"
|
||||
);
|
||||
assert.equal(got.includes("secret"), false);
|
||||
assert.match(got, /token=REDACTED/);
|
||||
assert.equal(
|
||||
redactSensitiveUrl("https://app.example.com/docs?k=dk_abcdefghijklmnop"),
|
||||
"https://app.example.com/docs?k=dk_REDACTED"
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
/** Parse invite / reset secrets from a URL hash (`#token=` / `#token=&mode=`). */
|
||||
export function paramsFromHash(hash: string): URLSearchParams {
|
||||
const raw = hash.startsWith("#") ? hash.slice(1) : hash;
|
||||
return new URLSearchParams(raw);
|
||||
}
|
||||
|
||||
export function tokenFromHash(hash: string): string {
|
||||
return (paramsFromHash(hash).get("token") ?? "").trim();
|
||||
}
|
||||
|
||||
export type AuthLinkMode = "invite" | "set-password";
|
||||
|
||||
/**
|
||||
* Read token from hash (preferred) or query (legacy emails), then strip both
|
||||
* from the address bar. Mode may live in hash or query; only `set-password` is special.
|
||||
*/
|
||||
export function consumeAuthLinkSecrets(href: string): {
|
||||
token: string;
|
||||
mode: AuthLinkMode | "";
|
||||
cleanedPathSearch: string;
|
||||
stripped: boolean;
|
||||
} {
|
||||
const url = new URL(href);
|
||||
const hashParams = paramsFromHash(url.hash);
|
||||
const fromHash = (hashParams.get("token") ?? "").trim();
|
||||
const fromQuery = (url.searchParams.get("token") ?? "").trim();
|
||||
const token = fromHash || fromQuery;
|
||||
const rawMode = (hashParams.get("mode") ?? url.searchParams.get("mode") ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const mode: AuthLinkMode | "" = rawMode === "set-password" ? "set-password" : "";
|
||||
const hadQueryToken = url.searchParams.has("token");
|
||||
url.searchParams.delete("token");
|
||||
url.hash = "";
|
||||
return {
|
||||
token,
|
||||
mode,
|
||||
cleanedPathSearch: `${url.pathname}${url.search}`,
|
||||
stripped: Boolean(fromHash) || hadQueryToken
|
||||
};
|
||||
}
|
||||
|
||||
const SENSITIVE_QUERY_KEYS = new Set(["token", "password"]);
|
||||
|
||||
/** Redact query/hash secrets and docs API keys from URLs sent to GTM. */
|
||||
export function redactSensitiveUrl(input: string): string {
|
||||
if (!input) return input;
|
||||
const redactDk = (value: string) => value.replace(/\bdk_[A-Za-z0-9_-]{8,}\b/g, "dk_REDACTED");
|
||||
try {
|
||||
const hasScheme = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(input);
|
||||
const u = hasScheme ? new URL(input) : new URL(input, "https://redact.invalid");
|
||||
for (const key of [...u.searchParams.keys()]) {
|
||||
if (SENSITIVE_QUERY_KEYS.has(key.toLowerCase())) {
|
||||
u.searchParams.set(key, "REDACTED");
|
||||
}
|
||||
}
|
||||
if (u.hash) {
|
||||
const hp = new URLSearchParams(u.hash.startsWith("#") ? u.hash.slice(1) : u.hash);
|
||||
let hashChanged = false;
|
||||
for (const key of [...hp.keys()]) {
|
||||
if (SENSITIVE_QUERY_KEYS.has(key.toLowerCase())) {
|
||||
hp.set(key, "REDACTED");
|
||||
hashChanged = true;
|
||||
}
|
||||
}
|
||||
if (hashChanged) u.hash = hp.toString();
|
||||
}
|
||||
const out = hasScheme ? u.toString() : `${u.pathname}${u.search}${u.hash}`;
|
||||
return redactDk(out);
|
||||
} catch {
|
||||
return redactDk(input.replace(/([?&#](?:token|password)=)[^&]*/gi, "$1REDACTED"));
|
||||
}
|
||||
}
|
||||
@@ -28,17 +28,17 @@ export const SECTION_MARKERS: Record<
|
||||
|
||||
/** Canonical shared intro (same idea as CategoryEnhanceUserTemplate preamble). */
|
||||
export const DEFAULT_ENHANCE_PREAMBLE =
|
||||
'Your reply is parsed as JSON {"name":"string","description":"string","meta_title":"string","meta_description":"string","attrs":{}} only (system schema). Write all string fields in {{language}} (do not hardcode a language).';
|
||||
"Write all product text in {{language}} (do not hardcode a language). Keep the title, description, SEO meta, and attributes consistent with the product evidence below.";
|
||||
|
||||
/** Minimal role bodies used when a section is empty on compose (keeps markers valid). */
|
||||
export const DEFAULT_SECTION_BODIES: Record<EnhancePromptSectionId, string> = {
|
||||
title:
|
||||
'Role: title. Build JSON "name": short retail title from Title formula + Attrs — never brand-only. Include product type and full model when evidence exists; follow any Title formula constraints that follow; use Attrs.\nName: {{name}}',
|
||||
"Write a short retail product title from the title formula and attributes — never brand-only. Include product type and full model when evidence exists; follow any title formula constraints that follow.\nName: {{name}}",
|
||||
description:
|
||||
'Role: description. Build JSON "description": product body HTML only (not SEO meta). When a Description formula follows, emit ONE HTML string covering each section in order; otherwise prefer 1-3 factual paragraphs as ONE string with limited HTML (<h2><p><ul><li>).\nDescription: {{description}}',
|
||||
meta: 'Role: meta. Build JSON "meta_title" and "meta_description" as plain SEO text (never HTML). meta_title: 50-60 chars; meta_description: 120-155 chars; follow any SEO meta formula that follows; never copy the full description HTML into meta_description.',
|
||||
"Write the product description as HTML (not SEO meta). When a description formula follows, cover each section in order as one HTML string; otherwise prefer 1–3 factual paragraphs with simple HTML (<h2><p><ul><li>).\nDescription: {{description}}",
|
||||
meta: "Write the SEO title (50–60 characters) and SEO description (120–155 characters) as plain text, never HTML. Follow any SEO meta formula that follows; do not copy the full description into the SEO description.",
|
||||
attributes:
|
||||
'Role: attributes. Build JSON "attrs" as an object of attribute_key → value strings. Prefer Allowed attribute keys / Title formula attr slots that follow; remap near-miss labels onto those keys; fill missing keys only from Name/Description/Category/Attrs evidence; never invent specs; omit unknown keys; never invent dimensions.\nCategory: {{category}}\nAttrs: {{attrs}}'
|
||||
"Fill product attributes as key/value pairs. Prefer allowed attribute keys and title-formula slots; remap near-miss labels onto those keys; fill missing keys only from name, description, category, and attributes evidence; never invent specs or dimensions; omit unknown keys.\nCategory: {{category}}\nAttrs: {{attrs}}"
|
||||
};
|
||||
|
||||
export type SectionSchemaHint = {
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
const companyHint = $derived.by(() => {
|
||||
const n = companyName;
|
||||
if (/^platform demo$/i.test(n) || /^demo$/i.test(n)) return "Platform Demo";
|
||||
if (n === "Local Demo Co" || /^a1(\s|$)/i.test(n)) return "A1 Slovenija";
|
||||
return n;
|
||||
});
|
||||
const impersonating = $derived(Boolean(me.impersonating));
|
||||
|
||||
@@ -129,15 +129,9 @@
|
||||
</div>
|
||||
|
||||
<p class="mx-auto mt-6 max-w-3xl text-center text-sm text-text-muted">
|
||||
{i18n.t("pricing.section.publicBefore")}
|
||||
<a href="/plans" class="font-medium text-link hover:underline"
|
||||
>{i18n.t("pricing.section.plansLink")}</a
|
||||
>
|
||||
{i18n.t("pricing.section.publicOr")}
|
||||
<a href="/billing" class="font-medium text-link hover:underline"
|
||||
>{i18n.t("pricing.section.billingLink")}</a
|
||||
>
|
||||
{i18n.t("pricing.section.publicAfter")}
|
||||
{i18n.t("pricing.section.guestPublicBefore")}
|
||||
<a href="/login" class="font-medium text-link hover:underline">{i18n.t("site.logIn")}</a>
|
||||
{i18n.t("pricing.section.guestPublicAfter")}
|
||||
</p>
|
||||
|
||||
<Card class="mt-12 border-border bg-surface">
|
||||
|
||||
@@ -132,5 +132,44 @@ export function validateDocsGuideTree(tree: DocsGuideTree): string[] {
|
||||
errors.push(`escapeLinks docs href must use RapiDoc ids (no braces): ${link.href}`);
|
||||
}
|
||||
}
|
||||
collectForbiddenDocsCopy(tree, errors);
|
||||
return errors;
|
||||
}
|
||||
|
||||
function rejectForbiddenDocsCopy(where: string, text: string | undefined, errors: string[]): void {
|
||||
if (!text) return;
|
||||
if (/legacy/i.test(text)) {
|
||||
errors.push(`${where} must not mention legacy`);
|
||||
}
|
||||
if (/\bA1\b/.test(text)) {
|
||||
errors.push(`${where} must not mention A1`);
|
||||
}
|
||||
}
|
||||
|
||||
function collectForbiddenDocsCopy(tree: DocsGuideTree, errors: string[]): void {
|
||||
rejectForbiddenDocsCopy("disclaimer", tree.disclaimer, errors);
|
||||
for (const link of tree.escapeLinks) {
|
||||
rejectForbiddenDocsCopy(`escapeLinks "${link.href}"`, link.label, errors);
|
||||
}
|
||||
for (const [id, node] of Object.entries(tree.nodes)) {
|
||||
rejectForbiddenDocsCopy(`node "${id}" title`, node.title, errors);
|
||||
rejectForbiddenDocsCopy(`node "${id}" body`, node.body, errors);
|
||||
if (node.kind === "question") {
|
||||
for (const c of node.choices) {
|
||||
rejectForbiddenDocsCopy(`question "${id}" choice "${c.id}" label`, c.label, errors);
|
||||
rejectForbiddenDocsCopy(`question "${id}" choice "${c.id}" description`, c.description, errors);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
rejectForbiddenDocsCopy(`answer "${id}" outcome`, node.outcome, errors);
|
||||
rejectForbiddenDocsCopy(`answer "${id}" tip`, node.tip, errors);
|
||||
rejectForbiddenDocsCopy(`answer "${id}" warning`, node.warning, errors);
|
||||
rejectForbiddenDocsCopy(`answer "${id}" authNote`, node.authNote, errors);
|
||||
for (const ep of node.endpoints ?? []) {
|
||||
rejectForbiddenDocsCopy(`answer "${id}" endpoint ${ep.method} ${ep.path}`, ep.summary, errors);
|
||||
}
|
||||
for (const link of node.links ?? []) {
|
||||
rejectForbiddenDocsCopy(`answer "${id}" link "${link.href}"`, link.label, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,8 +145,8 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
body: "Do not mix bodies or response envelopes between these two surfaces.",
|
||||
choices: [
|
||||
{
|
||||
id: "legacy",
|
||||
label: "Legacy EAN batch",
|
||||
id: "ean",
|
||||
label: "EAN batch",
|
||||
description: "POST /products/process · { data: { process_id } }",
|
||||
nextId: "answer.process.legacy"
|
||||
},
|
||||
@@ -300,7 +300,7 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
endpoints: [
|
||||
endpoint("GET", "/health", "Liveness (also /healthz and /readyz on the API host)"),
|
||||
endpoint("GET", "/openapi.yaml", "This OpenAPI document"),
|
||||
endpoint("GET", "/products", "List products (legacy { data, meta } envelope)")
|
||||
endpoint("GET", "/products", "List products ({ data, meta } envelope)")
|
||||
],
|
||||
links: [
|
||||
{ label: "Settings → API keys", href: "/settings?tab=api-keys", kind: "app" },
|
||||
@@ -325,7 +325,7 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
endpoints: [
|
||||
endpoint("GET", "/health", "No key required — confirm the viewer reaches the API"),
|
||||
endpoint("GET", "/products", "Authenticated smoke list (page=1&limit=1)"),
|
||||
endpoint("POST", "/products/process", "Legacy process — after Authorize"),
|
||||
endpoint("POST", "/products/process", "EAN batch — after Authorize"),
|
||||
endpoint("POST", "/process", "Jobs process — after Authorize")
|
||||
],
|
||||
links: [
|
||||
@@ -417,20 +417,20 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
"answer.process.legacy": {
|
||||
kind: "answer",
|
||||
id: "answer.process.legacy",
|
||||
pathKey: "process.legacy",
|
||||
pathKey: "process.ean",
|
||||
synonyms: ["ean", "items[].ean", "products/process"],
|
||||
title: "Legacy public process (EAN batch)",
|
||||
outcome: "Start and poll enrichment using the legacy Descrybe contract.",
|
||||
title: "Public process (EAN batch)",
|
||||
outcome: "Start and poll enrichment using POST/GET /products/process.",
|
||||
body: "POST body uses items[].ean (preferred). Handler also accepts raw_product_ids as an alternate on this same path. Responses use HTTP 200 with { data: { process_id, … } } and completed items[] when done.",
|
||||
authNote: AUTH_NOTE,
|
||||
endpoints: [
|
||||
endpoint("POST", "/products/process", "Start processing by EAN (legacy public contract)"),
|
||||
endpoint("POST", "/products/process", "Start processing by EAN"),
|
||||
endpoint("GET", "/products/process/{id}", "Processing job status by process_id")
|
||||
],
|
||||
links: [
|
||||
{ label: "Legacy start in docs", href: docsOperationHref("POST", "/products/process"), kind: "docs" },
|
||||
{ label: "Start in docs", href: docsOperationHref("POST", "/products/process"), kind: "docs" },
|
||||
{
|
||||
label: "Legacy status in docs",
|
||||
label: "Status in docs",
|
||||
href: docsOperationHref("GET", "/products/process/{id}"),
|
||||
kind: "docs"
|
||||
},
|
||||
@@ -448,7 +448,7 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
synonyms: ["raw_product_ids", "cancel job", "retry job"],
|
||||
title: "Dashboard-style processing jobs",
|
||||
outcome: "Start flat JSON jobs by raw_product_ids; poll, cancel, or retry.",
|
||||
body: "Same body shape as dashboard POST /api/processing/jobs. Start/retry return 202 Accepted with flat JSON (no data wrapper). Prefer /products/process for legacy integrations.",
|
||||
body: "Same body shape as dashboard POST /api/processing/jobs. Start/retry return 202 Accepted with flat JSON (no data wrapper). Prefer /products/process for EAN-batch integrations.",
|
||||
authNote: AUTH_NOTE,
|
||||
endpoints: [
|
||||
endpoint("POST", "/process", "Start processing job by raw_product_ids"),
|
||||
@@ -473,15 +473,15 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
pathKey: "process.which",
|
||||
synonyms: ["which process", "dual contract"],
|
||||
title: "Which process API should I use?",
|
||||
outcome: "Pick legacy EAN for integrations; pick /process for dashboard-style jobs.",
|
||||
body: "1) Legacy public: POST/GET /products/process — items[].ean, HTTP 200 { data: { process_id } }. 2) Jobs: POST/GET /process — raw_product_ids, flat JSON, 202 on start. Mixing envelopes is the most common integration bug.",
|
||||
outcome: "Pick EAN batch for integrations; pick /process for dashboard-style jobs.",
|
||||
body: "1) Public process: POST/GET /products/process — items[].ean, HTTP 200 { data: { process_id } }. 2) Jobs: POST/GET /process — raw_product_ids, flat JSON, 202 on start. Mixing envelopes is the most common integration bug.",
|
||||
authNote: AUTH_NOTE,
|
||||
endpoints: [
|
||||
endpoint("POST", "/products/process", "Legacy EAN batch"),
|
||||
endpoint("POST", "/products/process", "EAN batch"),
|
||||
endpoint("POST", "/process", "Dashboard-style jobs")
|
||||
],
|
||||
links: [
|
||||
{ label: "Legacy process", href: docsOperationHref("POST", "/products/process"), kind: "docs" },
|
||||
{ label: "EAN process", href: docsOperationHref("POST", "/products/process"), kind: "docs" },
|
||||
{ label: "Jobs process", href: docsOperationHref("POST", "/process"), kind: "docs" },
|
||||
{
|
||||
label: "Dual-mode overview",
|
||||
@@ -575,13 +575,13 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
endpoints: [
|
||||
endpoint("GET", "/categories", "List categories"),
|
||||
endpoint("POST", "/categories", "Create category"),
|
||||
endpoint("POST", "/categories/create", "Create category (legacy alias)"),
|
||||
endpoint("POST", "/categories/create", "Create category (alias of POST /categories)"),
|
||||
endpoint("GET", "/categories/{id}", "Get category by UUID"),
|
||||
endpoint("PATCH", "/categories/{id}", "Update category"),
|
||||
endpoint("DELETE", "/categories/{id}", "Delete category by unique_id"),
|
||||
endpoint("GET", "/attributes", "List attributes"),
|
||||
endpoint("POST", "/attributes", "Create attribute"),
|
||||
endpoint("POST", "/attributes/create", "Create attribute (legacy alias)"),
|
||||
endpoint("POST", "/attributes/create", "Create attribute (alias of POST /attributes)"),
|
||||
endpoint("PATCH", "/attributes/{id}", "Update attribute"),
|
||||
endpoint("DELETE", "/attributes/{id}", "Delete attribute")
|
||||
],
|
||||
@@ -592,7 +592,7 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
{ label: "Attributes tag", href: docsTagHref("Attributes"), kind: "docs" },
|
||||
{ label: "Authorize", href: docsAuthHref(), kind: "docs" }
|
||||
],
|
||||
tip: "Prefer canonical POST /categories and POST /attributes; /create aliases exist for legacy clients.",
|
||||
tip: "Prefer canonical POST /categories and POST /attributes; /create aliases exist for existing integrations.",
|
||||
relatedIds: ["answer.feeds.mapping", "answer.products"]
|
||||
},
|
||||
|
||||
@@ -615,7 +615,7 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
{ label: "Try GET /products", href: docsOperationHref("GET", "/products"), kind: "docs" },
|
||||
{ label: "Authorize", href: docsAuthHref(), kind: "docs" }
|
||||
],
|
||||
tip: "List uses legacy query params: page, limit, status, search, sortBy, sortOrder, feedId.",
|
||||
tip: "List uses query params: page, limit, status, search, sortBy, sortOrder, feedId.",
|
||||
relatedIds: ["answer.products.quality", "answer.process.legacy"]
|
||||
},
|
||||
|
||||
@@ -648,13 +648,13 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
synonyms: ["campaigns", "calendar", "seasonal"],
|
||||
title: "Marketing calendar (API)",
|
||||
outcome: "List seasonal presets and prepare a calendar export via the public API.",
|
||||
body: "Public /api/v1/marketing/calendar* (and legacy /campaigns aliases) are API-key routes for the content calendar. They are separate from session email campaigns under /api/campaigns in the dashboard UI.",
|
||||
body: "Public /api/v1/marketing/calendar* (and /campaigns aliases) are API-key routes for the content calendar. They are separate from session email campaigns under /api/campaigns in the dashboard UI.",
|
||||
authNote: AUTH_NOTE,
|
||||
endpoints: [
|
||||
endpoint("GET", "/marketing/calendar", "List seasonal campaign presets"),
|
||||
endpoint("POST", "/marketing/calendar/prepare", "Prepare seasonal campaign export"),
|
||||
endpoint("GET", "/campaigns", "List presets (legacy alias)"),
|
||||
endpoint("POST", "/campaigns/prepare", "Prepare export (legacy alias)")
|
||||
endpoint("GET", "/campaigns", "List presets (alias of GET /marketing/calendar)"),
|
||||
endpoint("POST", "/campaigns/prepare", "Prepare export (alias of POST /marketing/calendar/prepare)")
|
||||
],
|
||||
links: [
|
||||
{
|
||||
@@ -684,7 +684,7 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
{ label: "Settings", href: "/settings", kind: "app" },
|
||||
{ label: "Contact support", href: "/support/new", kind: "support" }
|
||||
],
|
||||
tip: "After upgrading, retry the same process endpoint you already chose (legacy vs jobs).",
|
||||
tip: "After upgrading, retry the same process endpoint you already chose (EAN batch vs jobs).",
|
||||
relatedIds: ["answer.error.job", "answer.process.chooser"]
|
||||
},
|
||||
|
||||
@@ -722,7 +722,7 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
authNote: AUTH_NOTE,
|
||||
endpoints: [
|
||||
endpoint("POST", "/feeds/{id}/sync", "Sync (rate-limited)"),
|
||||
endpoint("POST", "/products/process", "Legacy process (rate-limited)"),
|
||||
endpoint("POST", "/products/process", "EAN process (rate-limited)"),
|
||||
endpoint("POST", "/process", "Jobs process (rate-limited)"),
|
||||
endpoint("POST", "/export-feeds/{id}/generate", "Generate export (rate-limited)")
|
||||
],
|
||||
@@ -741,10 +741,10 @@ export const DOCS_GUIDE_TREE: DocsGuideTree = {
|
||||
synonyms: ["job failed", "pending", "cancel", "retry"],
|
||||
title: "Process job pending or failed",
|
||||
outcome: "Poll the matching status endpoint; cancel/retry only on the /process job surface.",
|
||||
body: "Legacy: GET /products/process/{id} (data envelope). Jobs: GET /process/{id} plus POST …/cancel|terminate|retry. Confirm you started the job on the same contract you are polling.",
|
||||
body: "EAN batch: GET /products/process/{id} (data envelope). Jobs: GET /process/{id} plus POST …/cancel|terminate|retry. Confirm you started the job on the same contract you are polling.",
|
||||
authNote: AUTH_NOTE,
|
||||
endpoints: [
|
||||
endpoint("GET", "/products/process/{id}", "Legacy poll"),
|
||||
endpoint("GET", "/products/process/{id}", "EAN batch poll"),
|
||||
endpoint("GET", "/process/{id}", "Jobs poll"),
|
||||
endpoint("POST", "/process/{id}/retry", "Retry failed/cancelled job")
|
||||
],
|
||||
|
||||
@@ -56,6 +56,7 @@ export function readStoredTryItKey(companyId: string): DocsTryItStoredKey | null
|
||||
export function writeStoredTryItKey(entry: DocsTryItStoredKey): void {
|
||||
if (typeof sessionStorage === "undefined") return;
|
||||
try {
|
||||
// Tab-scoped only. Never log the full key or send it to GTM/analytics.
|
||||
sessionStorage.setItem(storageKey(entry.companyId), JSON.stringify(entry));
|
||||
} catch {
|
||||
/* quota / private mode */
|
||||
@@ -89,6 +90,38 @@ export function clearRapiDocApiKeys(el: RapiDocAuthElement | null | undefined):
|
||||
el.removeAllSecurityKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* RapiDoc labels required-but-empty credentials as "(None Applied)".
|
||||
* Public /api/v1 ops use a company API key — show that instead.
|
||||
*/
|
||||
export function rapiDocAuthEmptyLabel(text: string): string {
|
||||
return text.replace(/None Applied/g, "API Key");
|
||||
}
|
||||
|
||||
export function relabelRapiDocAuthRequired(
|
||||
el: HTMLElement | null | undefined
|
||||
): MutationObserver | null {
|
||||
const root = el?.shadowRoot;
|
||||
if (!root) return null;
|
||||
|
||||
const apply = () => {
|
||||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
||||
let node: Node | null = walker.nextNode();
|
||||
while (node) {
|
||||
const text = node.textContent;
|
||||
if (text && text.includes("None Applied")) {
|
||||
node.textContent = rapiDocAuthEmptyLabel(text);
|
||||
}
|
||||
node = walker.nextNode();
|
||||
}
|
||||
};
|
||||
|
||||
apply();
|
||||
const observer = new MutationObserver(apply);
|
||||
observer.observe(root, { subtree: true, childList: true, characterData: true });
|
||||
return observer;
|
||||
}
|
||||
|
||||
export function maskKeyPrefix(prefix: string | null | undefined): string {
|
||||
const p = (prefix ?? "").trim();
|
||||
return p ? `${p}\u2026` : "dk_\u2026";
|
||||
|
||||
@@ -78,7 +78,7 @@ export const de: MessageDict = {
|
||||
"auth.login.failed": "Anmeldung fehlgeschlagen",
|
||||
"auth.login.passwordNotSet": "Dieses Konto benötigt noch ein Passwort. Öffnen Sie Ihren Einladungslink oder bitten Sie einen Admin, einen neuen auszustellen.",
|
||||
"auth.login.setPasswordFirstTitle": "Zuerst Passwort festlegen:",
|
||||
"auth.login.setPasswordFirstBody": "nutzen Sie den Einladungslink aus Ihrer E-Mail. Wenn der Link an eine alte Adresse ging (E-Mail-Drift), bitten Sie einen Unternehmens-Admin, eine neue Passwort-Einladung an {email} auszustellen.",
|
||||
"auth.login.setPasswordFirstBody": "nutzen Sie den Einladungslink aus Ihrer E-Mail. Wenn Sie einen neuen Link brauchen, bitten Sie einen Unternehmens-Admin, einen Link zum Festlegen des Passworts an {email} auszustellen.",
|
||||
"auth.login.yourEmail": "Ihre E-Mail",
|
||||
"auth.login.platformAdminsReissue": "Plattform-Admins können erneut ausstellen unter",
|
||||
"auth.login.adminUsersLink": "Admin → Benutzer",
|
||||
@@ -144,9 +144,9 @@ export const de: MessageDict = {
|
||||
"auth.invite.acceptFailed": "Einladung konnte nicht angenommen werden",
|
||||
"auth.invite.setPasswordFailed": "Passwort konnte nicht festgelegt werden",
|
||||
"auth.invite.expired": "Diese Einladung ist ungültig oder abgelaufen. Bitten Sie Ihren Unternehmens-Admin um eine neue Einladung und öffnen Sie den neuen Link (oder fügen Sie das neue Token unten ein).",
|
||||
"auth.invite.setPasswordExpired": "Dieser Passwort-Link ist ungültig oder abgelaufen. Bitten Sie einen Unternehmens- oder Plattform-Admin um Neuausstellung und öffnen Sie den neuen Link (oder fügen Sie das neue Token unten ein).",
|
||||
"auth.invite.setPasswordExpired": "Dieser Passwort-Link ist ungültig oder abgelaufen. Bitten Sie einen Unternehmens-Admin, einen Link zum Festlegen des Passworts an diese E-Mail auszustellen, und öffnen Sie den neuen Link (oder fügen Sie das neue Token unten ein).",
|
||||
"auth.invite.emailMismatchDefault": "Sie sind mit einer anderen E-Mail angemeldet als diese Einladung.",
|
||||
"auth.invite.expiredFooter": "Abgelaufener Link? Bitten Sie einen Admin um Neuausstellung  es gibt keine Self-Service-API zum erneuten Senden. Plattform-Admins:",
|
||||
"auth.invite.expiredFooter": "Abgelaufener Link? Bitten Sie einen Unternehmens-Admin um Neuausstellung — es gibt keine Self-Service-API zum erneuten Senden.",
|
||||
"auth.invite.adminUsersLink": "Admin → Benutzer",
|
||||
"auth.invite.doneTitle": "Sie sind im Team",
|
||||
"auth.invite.doneSetPasswordTitle": "Passwort gespeichert",
|
||||
@@ -163,7 +163,7 @@ export const de: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Konto wechseln:",
|
||||
"auth.invite.switchAccountBody": "melden Sie sich ab und schließen Sie dieses Formular mit der eingeladenen E-Mail{emailSuffix} ab.",
|
||||
"auth.invite.reissueTitle": "Neuausstellungs-Pfad:",
|
||||
"auth.invite.reissueBody": "wenn sich Ihre echte Anmelde-E-Mail geändert hat (E-Mail-Drift), bitten Sie einen Unternehmens-Admin, diese Einladung zu widerrufen und eine neue an die E-Mail zu senden, mit der Sie sich anmelden. Plattform-Admins können Passwort-Links auch unter Admin → Benutzer erneut ausstellen.",
|
||||
"auth.invite.reissueBody": "bitten Sie einen Unternehmens-Admin, einen Link zum Festlegen des Passworts an diese E-Mail auszustellen oder diese Einladung zu widerrufen und eine neue an die E-Mail zu senden, mit der Sie sich anmelden.",
|
||||
"locale.switcher": "Oberflächensprache",
|
||||
"locale.menu": "Oberflächensprache wählen",
|
||||
"locale.label": "Dashboard-Sprache",
|
||||
@@ -276,7 +276,7 @@ export const de: MessageDict = {
|
||||
"settings.table.lastUsed": "Zuletzt verwendet",
|
||||
"dashboard.demoSandbox": "Demo-Sandbox",
|
||||
"dashboard.demoEmptyTitle": "Demo-Sandbox ist leer",
|
||||
"dashboard.demoEmptyHint": "Demo-Sandbox ist leer  wechseln Sie zu A1 oder verbinden Sie einen Feed, um echte Katalogstatistiken zu sehen.",
|
||||
"dashboard.demoEmptyHint": "Demo-Sandbox ist leer — verbinden Sie einen Feed, um echte Katalogstatistiken zu sehen.",
|
||||
"dashboard.overviewTitle": "Übersicht",
|
||||
"dashboard.quickLinks": "Schnelllinks",
|
||||
"dashboard.whatsNew": "Neuigkeiten",
|
||||
@@ -319,7 +319,7 @@ export const de: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Zuordnen dann exportieren",
|
||||
"dashboard.workflowHint": "Katalog rein → anreichern / verarbeiten → exportieren oder zu Shops pushen. Zum nächsten Schritt für {name}.",
|
||||
"dashboard.overviewHint": "Live-Summen für {name}",
|
||||
"dashboard.demoEmptyMessage": "Wechseln Sie in der Kopfzeile zu A1 (oder einem anderen Seed-Unternehmen) oder verbinden Sie hier einen Feed, um diese Sandbox zu füllen.",
|
||||
"dashboard.demoEmptyMessage": "Verbinden Sie hier einen Feed, um diese Sandbox zu füllen, oder wechseln Sie in der Kopfzeile zu einem anderen Unternehmen.",
|
||||
"dashboard.emptyTitle": "Katalog hereinholen",
|
||||
"dashboard.emptyMessage": "Katalog rein → anreichern / verarbeiten → exportieren oder zu Shops pushen. Starten Sie mit Erste Schritte unten (oder Feed verbinden / CSV hochladen).",
|
||||
"dashboard.connectFeedAnyway": "Feed trotzdem verbinden",
|
||||
@@ -367,29 +367,29 @@ export const de: MessageDict = {
|
||||
"activation.focus.sync": "Als Nächstes: Nach dem Speichern der Zuordnung eine Stichprobe synchronisieren. Sync nur bei zugeordneten Feeds  nicht bei unmapped Quellen.",
|
||||
"activation.focus.dismiss": "Hinweis schließen",
|
||||
"activation.dismiss": "Checkliste ausblenden",
|
||||
"hypercare.report.title": "Cutover-Hypercare",
|
||||
"hypercare.report.title": "Hilfe nach dem Umzug?",
|
||||
"hypercare.report.message": "Fehlende oder falsche Daten nach der Migration? Melden Sie es, damit wir Ihren Workspace korrigieren können.",
|
||||
"hypercare.report.cta": "Fehlende oder falsche Daten melden",
|
||||
"hypercare.report.dismiss": "Verwerfen",
|
||||
"hypercare.report.adminTriage": "Hypercare-Warteschlange öffnen",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -456,9 +456,9 @@ export const de: MessageDict = {
|
||||
"errors.readOnly": "Das System ist im Nur-Lesen-Modus. Änderungen sind vorübergehend deaktiviert.",
|
||||
"errors.companyAdminDenied": "Nur Unternehmens-Admins können {action}. Bitten Sie einen Admin um Hilfe.",
|
||||
"errors.companyAdminDenied.actionDefault": "dies tun",
|
||||
"docs.tryIt.memberCannotCreate": "Nur Unternehmens-Admins können API-Schlüssel erstellen. Legacy-Schlüssel wurden nicht migriert  Schlüssel unten einfügen oder Admin um einen neuen bitten.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "Legacy-API-Schlüssel wurden nicht migriert. Neuen Schlüssel über Use my API key oder Einstellungen → API-Schlüssel erstellen  Geheimnis nur einmal sichtbar.",
|
||||
"docs.tryIt.noKeysLegacyMember": "Keine API-Schlüssel gelistet. Legacy-Schlüssel nicht migriert  Admin um Erstellung bitten oder dk_-Schlüssel einfügen.",
|
||||
"docs.tryIt.memberCannotCreate": "Nur Unternehmens-Admins können API-Schlüssel erstellen. Schlüssel wurden nicht migriert  Schlüssel unten einfügen oder Admin um einen neuen bitten.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "API-Schlüssel wurden nicht migriert. Neuen Schlüssel über Use my API key oder Einstellungen → API-Schlüssel erstellen  Geheimnis nur einmal sichtbar.",
|
||||
"docs.tryIt.noKeysLegacyMember": "Keine API-Schlüssel gelistet. Schlüssel nicht migriert  Admin um Erstellung bitten oder dk_-Schlüssel einfügen.",
|
||||
"errors.couldNotUpdateLanguage": "Sprache konnte nicht aktualisiert werden",
|
||||
"toast.support.replyTitle": "Support-Antwort",
|
||||
"toast.support.replyBody": "Das Team hat auf Ihr Support-Ticket geantwortet.",
|
||||
@@ -5065,7 +5065,7 @@ export const de: MessageDict = {
|
||||
"brand.uploadLogo": "Logo hochladen",
|
||||
"brand.clear": "Löschen",
|
||||
"brand.field.logoUrl": "Logo-URL",
|
||||
"brand.placeholder.logoUrl": "https://… oder hochgeladen /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "Vorschau des Markenlogos",
|
||||
"brand.tipsTitle": "Formel- / Vorschautipps",
|
||||
"brand.saving": "Wird gespeichert…",
|
||||
@@ -5291,7 +5291,7 @@ export const de: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Am beliebtesten",
|
||||
"pricing.card.custom": "Individuell",
|
||||
"pricing.card.forever": "für immer",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const en: MessageDict = {
|
||||
"auth.login.failed": "Login failed",
|
||||
"auth.login.passwordNotSet": "This account still needs a password. Open your invite link, or ask an admin to re-issue one.",
|
||||
"auth.login.setPasswordFirstTitle": "Set password first:",
|
||||
"auth.login.setPasswordFirstBody": "use the invite link from your email. If the link went to an old address (email drift), ask a company admin to re-issue a set-password invite to {email}.",
|
||||
"auth.login.setPasswordFirstBody": "use the invite link from your email. If you need a new link, ask a company admin to re-issue a set-password link to {email}.",
|
||||
"auth.login.yourEmail": "your email",
|
||||
"auth.login.platformAdminsReissue": "Platform admins can re-issue from",
|
||||
"auth.login.adminUsersLink": "Admin → Users",
|
||||
@@ -144,9 +144,9 @@ export const en: MessageDict = {
|
||||
"auth.invite.acceptFailed": "Could not accept invite",
|
||||
"auth.invite.setPasswordFailed": "Could not set password",
|
||||
"auth.invite.expired": "This invite is invalid or expired. Ask your company admin to send a new invite, then open the new link (or paste the new token below).",
|
||||
"auth.invite.setPasswordExpired": "This set-password link is invalid or expired. Ask a company or platform admin to re-issue it, then open the new link (or paste the new token below).",
|
||||
"auth.invite.setPasswordExpired": "This set-password link is invalid or expired. Ask a company admin to re-issue a set-password link to this email, then open the new link (or paste the new token below).",
|
||||
"auth.invite.emailMismatchDefault": "You're signed in as a different email than this invite.",
|
||||
"auth.invite.expiredFooter": "Expired link? Ask an admin to re-issue — there is no self-serve resend API. Platform admins:",
|
||||
"auth.invite.expiredFooter": "Expired link? Ask a company admin to re-issue — there is no self-serve resend API.",
|
||||
"auth.invite.adminUsersLink": "Admin → Users",
|
||||
"auth.invite.doneTitle": "You're on the team",
|
||||
"auth.invite.doneSetPasswordTitle": "Password saved",
|
||||
@@ -163,7 +163,7 @@ export const en: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Switch account:",
|
||||
"auth.invite.switchAccountBody": "sign out, then finish this form with the invited email{emailSuffix}.",
|
||||
"auth.invite.reissueTitle": "Re-issue path:",
|
||||
"auth.invite.reissueBody": "if your real login email changed (email drift), ask a company admin to revoke this invite and send a new one to the email you use to sign in. Platform admins can also re-issue set-password links from Admin → Users.",
|
||||
"auth.invite.reissueBody": "ask a company admin to re-issue a set-password link to this email, or to revoke this invite and send a new one to the email you use to sign in.",
|
||||
"locale.switcher": "Interface language",
|
||||
"locale.menu": "Choose interface language",
|
||||
"locale.label": "Dashboard language",
|
||||
@@ -296,7 +296,7 @@ export const en: MessageDict = {
|
||||
"settings.table.lastUsed": "Last Used",
|
||||
"dashboard.demoSandbox": "Demo sandbox",
|
||||
"dashboard.demoEmptyTitle": "Demo sandbox is empty",
|
||||
"dashboard.demoEmptyHint": "Demo sandbox is empty — switch to A1 or connect a feed to see real catalog stats.",
|
||||
"dashboard.demoEmptyHint": "Demo sandbox is empty — connect a feed to see catalog stats.",
|
||||
"dashboard.overviewTitle": "Overview",
|
||||
"dashboard.quickLinks": "Quick links",
|
||||
"dashboard.whatsNew": "What's new",
|
||||
@@ -339,7 +339,7 @@ export const en: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Map then export",
|
||||
"dashboard.workflowHint": "Catalog in → enrich / process → export or push to stores. Jump to the next step for {name}.",
|
||||
"dashboard.overviewHint": "Live totals for {name}",
|
||||
"dashboard.demoEmptyMessage": "Switch to A1 (or another seeded company) in the header, or connect a feed here to populate this sandbox.",
|
||||
"dashboard.demoEmptyMessage": "Connect a feed here to populate this sandbox, or switch to another company in the header.",
|
||||
"dashboard.emptyTitle": "Bring a catalog in",
|
||||
"dashboard.emptyMessage": "Catalog in → enrich / process → export or push to stores. Start with Getting started below (or connect a feed / upload a CSV).",
|
||||
"dashboard.connectFeedAnyway": "Connect feed anyway",
|
||||
@@ -391,28 +391,28 @@ export const en: MessageDict = {
|
||||
"activation.focus.sync": "Next: Sync a sample after mappings are saved. Use Sync on a mapped feed — avoid syncing unmapped sources.",
|
||||
"activation.focus.dismiss": "Dismiss hint",
|
||||
"activation.dismiss": "Dismiss checklist",
|
||||
"hypercare.report.title": "Cutover hypercare",
|
||||
"hypercare.report.message": "See missing or wrong data after migration? Report it so we can fix your workspace.",
|
||||
"hypercare.report.title": "Need help after the move?",
|
||||
"hypercare.report.message": "See missing or wrong data after the move? Report it so we can fix your workspace.",
|
||||
"hypercare.report.cta": "Report missing or wrong data",
|
||||
"hypercare.report.dismiss": "Dismiss",
|
||||
"hypercare.report.adminTriage": "Open hypercare queue",
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken” — recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied — re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run — empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover — that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -479,9 +479,9 @@ export const en: MessageDict = {
|
||||
"errors.readOnly": "The system is in read-only mode. Changes are temporarily disabled.",
|
||||
"errors.companyAdminDenied": "Only company admins can {action}. Ask a company admin for help.",
|
||||
"errors.companyAdminDenied.actionDefault": "do this",
|
||||
"docs.tryIt.memberCannotCreate": "Only company admins can create API keys. Legacy keys were not migrated — paste a key below, or ask an admin to create a new one.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "Legacy API keys were not migrated. Create a new key via Use my API key or Settings → API keys — the secret is shown only once.",
|
||||
"docs.tryIt.noKeysLegacyMember": "No API keys listed. Legacy keys were not migrated — ask a company admin to create one, or paste a dk_ key.",
|
||||
"docs.tryIt.memberCannotCreate": "Only company admins can create API keys. Keys from the previous platform were not migrated — paste a key below, or ask an admin to create a new one.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "API keys from the previous platform were not migrated. Create a new key via Use my API key or Settings → API keys — the secret is shown only once.",
|
||||
"docs.tryIt.noKeysLegacyMember": "No API keys listed. Keys from the previous platform were not migrated — ask a company admin to create one, or paste a dk_ key.",
|
||||
"errors.couldNotUpdateLanguage": "Could not update language",
|
||||
"toast.support.replyTitle": "Support reply",
|
||||
"toast.support.replyBody": "Staff replied to your support ticket.",
|
||||
@@ -3729,6 +3729,7 @@ export const en: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "The just-started job was cancelled.",
|
||||
"processing.receipt.cancelFailed": "Could not cancel processing job",
|
||||
"unsubscribe.title": "Unsubscribe",
|
||||
"unsubscribe.useEmailLink": "Use the unsubscribe link in the email we sent you. Opening this page without that link cannot change your email preferences.",
|
||||
"unsubscribe.me": "Unsubscribe me",
|
||||
"unsubscribe.invalidLink": "Invalid link",
|
||||
"unsubscribe.failedShort": "Unsubscribe failed",
|
||||
@@ -4445,23 +4446,23 @@ export const en: MessageDict = {
|
||||
"categories.promptSection.navHeading": "Sections",
|
||||
"categories.promptSection.navHint": "Edit one part of the enhance reply at a time.",
|
||||
"categories.promptSection.title": "Title",
|
||||
"categories.promptSection.titleHelp": "Instructions for the product title (JSON name).",
|
||||
"categories.promptSection.titleHelp": "Instructions for the product title.",
|
||||
"categories.promptSection.titleFormulaNote": "Title formula slots (type + brand + model) are appended automatically when set on this category.",
|
||||
"categories.promptSection.description": "Description",
|
||||
"categories.promptSection.descriptionHelp": "Instructions for the HTML product body (JSON description - not SEO meta).",
|
||||
"categories.promptSection.descriptionHelp": "Instructions for the HTML product body (not SEO meta).",
|
||||
"categories.promptSection.descriptionFormulaNote": "Description formula sections are appended at render time when configured.",
|
||||
"categories.promptSection.meta": "Meta",
|
||||
"categories.promptSection.metaHelp": "Instructions for SEO meta_title and meta_description (plain text).",
|
||||
"categories.promptSection.metaHelp": "Instructions for the SEO title and description (plain text).",
|
||||
"categories.promptSection.metaFormulaNote": "SEO meta formulas from the description template are appended when present.",
|
||||
"categories.promptSection.attributes": "Attributes",
|
||||
"categories.promptSection.attributesHelp": "Instructions for the attrs object (allowlisted keys).",
|
||||
"categories.promptSection.attributesHelp": "Instructions for product attributes (allowed keys only).",
|
||||
"categories.promptSection.attributesFormulaNote": "Allowed attribute keys and title-formula attr slots are appended at render time.",
|
||||
"categories.promptSection.schemaHeading": "One-shot JSON",
|
||||
"categories.promptSection.schemaHelp": "Enhance returns a single JSON object. This section owns the keys below.",
|
||||
"categories.promptSection.contentLabel": "Section instructions",
|
||||
"categories.promptSection.contentPlaceholder": "Role guidance and placeholders for this section...",
|
||||
"categories.promptSection.preambleToggle": "Shared intro (all sections)",
|
||||
"categories.promptSection.preambleHelp": "Shown once above the section markers. Keep the JSON schema reminder so the model replies correctly.",
|
||||
"categories.promptSection.preambleHelp": "Shown once above the section markers. Keep language and evidence reminders so the model replies correctly.",
|
||||
"categories.promptSection.clearLanguage": "Clear language override",
|
||||
"categories.promptSection.unstructuredHint": "This prompt is not sectioned yet. Content is shown under Description - edit the sections you need and save to store the standard Title / Description / Meta / Attributes layout.",
|
||||
"categories.promptSection.categorizeNote": "Categorize (taxonomy pick) is a separate pipeline step - not part of this enhance prompt.",
|
||||
@@ -4792,6 +4793,10 @@ export const en: MessageDict = {
|
||||
"seo.terms.description": "Terms for using Descrybe — feed import, catalog enrichment, AI-assisted content, exports, and WooCommerce sync for your business.",
|
||||
"seo.features.title": "Features — Feeds, enrichment, and export | Descrybe",
|
||||
"seo.features.description": "See how Descrybe imports supplier feeds, maps fields to your taxonomy, enriches product data, and ships catalogs via export feeds, WooCommerce, or API.",
|
||||
"seo.contactSales.title": "Contact sales | Descrybe",
|
||||
"seo.contactSales.description": "Tell us about your catalog and capacity needs — we will prepare a custom plan you can pay online.",
|
||||
"seo.unsubscribe.title": "Unsubscribe | Descrybe",
|
||||
"seo.unsubscribe.description": "Stop marketing emails from Descrybe using the unsubscribe link in the message we sent you.",
|
||||
"pricing.page.eyebrow": "Pricing",
|
||||
"pricing.page.title": "Simple plans for growing catalogs",
|
||||
"pricing.page.lead": "Start free with feed mapping and basic cleanup. Upgrade when you need AI titles and descriptions, more products, export feeds, or WooCommerce sync — Starter through Enterprise.",
|
||||
@@ -4799,6 +4804,8 @@ export const en: MessageDict = {
|
||||
"pricing.page.subscribedMid": "or compare plans in",
|
||||
"pricing.page.plansLink": "Plans",
|
||||
"pricing.page.subscribedAfter": ".",
|
||||
"pricing.page.guestSubscribedBefore": "Already subscribed?",
|
||||
"pricing.page.guestSubscribedAfter": "to manage billing and compare plans.",
|
||||
"legal.lastUpdated": "Last updated: {date}",
|
||||
"legal.backHome": "← Back to Home",
|
||||
"legal.emailLabel": "Email:",
|
||||
@@ -5130,7 +5137,7 @@ export const en: MessageDict = {
|
||||
"brand.uploadLogo": "Upload logo",
|
||||
"brand.clear": "Clear",
|
||||
"brand.field.logoUrl": "Logo URL",
|
||||
"brand.placeholder.logoUrl": "https://… or uploaded /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "Brand logo preview",
|
||||
"brand.tipsTitle": "Formula / preview tips",
|
||||
"brand.saving": "Saving…",
|
||||
@@ -5291,6 +5298,8 @@ export const en: MessageDict = {
|
||||
"pricing.section.publicBefore": "Public plans: Free, Starter, Plus, Growth, Business, Scale, and Enterprise. Create a Free account, then upgrade under",
|
||||
"pricing.section.publicOr": "or",
|
||||
"pricing.section.publicAfter": "via Stripe Checkout. Enterprise remains sales-led.",
|
||||
"pricing.section.guestPublicBefore": "Public plans: Free, Starter, Plus, Growth, Business, Scale, and Enterprise. Create a Free account, then",
|
||||
"pricing.section.guestPublicAfter": "to upgrade via Stripe Checkout. Enterprise remains sales-led.",
|
||||
"pricing.section.plansLink": "Plans",
|
||||
"pricing.section.billingLink": "Billing",
|
||||
"pricing.section.capabilitiesTitle": "What every plan is built for",
|
||||
@@ -5359,7 +5368,7 @@ export const en: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Most Popular",
|
||||
"pricing.card.custom": "Custom",
|
||||
"pricing.card.forever": "forever",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const es: MessageDict = {
|
||||
"auth.login.failed": "Error al iniciar sesión",
|
||||
"auth.login.passwordNotSet": "Esta cuenta aún necesita una contraseña. Abre el enlace de invitación o pide a un administrador que emita uno nuevo.",
|
||||
"auth.login.setPasswordFirstTitle": "Establece la contraseña primero:",
|
||||
"auth.login.setPasswordFirstBody": "usa el enlace de invitación de tu correo. Si el enlace fue a una dirección antigua (cambio de correo), pide a un administrador de la empresa que emita una nueva invitación para establecer contraseña a {email}.",
|
||||
"auth.login.setPasswordFirstBody": "usa el enlace de invitación de tu correo. Si necesitas un enlace nuevo, pide a un administrador de la empresa que reemita un enlace para establecer contraseña a {email}.",
|
||||
"auth.login.yourEmail": "tu correo",
|
||||
"auth.login.platformAdminsReissue": "Los administradores de plataforma pueden reemitir desde",
|
||||
"auth.login.adminUsersLink": "Admin → Usuarios",
|
||||
@@ -144,9 +144,9 @@ export const es: MessageDict = {
|
||||
"auth.invite.acceptFailed": "No se pudo aceptar la invitación",
|
||||
"auth.invite.setPasswordFailed": "No se pudo establecer la contraseña",
|
||||
"auth.invite.expired": "Esta invitación no es válida o ha caducado. Pide a tu administrador de la empresa que envÃÂe una nueva invitación y abre el nuevo enlace (o pega el nuevo token abajo).",
|
||||
"auth.invite.setPasswordExpired": "Este enlace para establecer contraseña no es válido o ha caducado. Pide a un administrador de la empresa o de la plataforma que lo reemita y abre el nuevo enlace (o pega el nuevo token abajo).",
|
||||
"auth.invite.setPasswordExpired": "Este enlace para establecer contraseña no es válido o ha caducado. Pide a un administrador de la empresa que reemita un enlace para establecer contraseña a este correo y abre el nuevo enlace (o pega el nuevo token abajo).",
|
||||
"auth.invite.emailMismatchDefault": "Has iniciado sesión con un correo distinto al de esta invitación.",
|
||||
"auth.invite.expiredFooter": "¿Enlace caducado? Pide a un administrador que lo reemita  no hay API de reenvÃÂo autoservicio. Administradores de plataforma:",
|
||||
"auth.invite.expiredFooter": "¿Enlace caducado? Pide a un administrador de la empresa que lo reemita — no hay API de reenvío autoservicio.",
|
||||
"auth.invite.adminUsersLink": "Admin → Usuarios",
|
||||
"auth.invite.doneTitle": "Ya formas parte del equipo",
|
||||
"auth.invite.doneSetPasswordTitle": "Contraseña guardada",
|
||||
@@ -163,7 +163,7 @@ export const es: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Cambiar de cuenta:",
|
||||
"auth.invite.switchAccountBody": "cierra sesión y completa este formulario con el correo invitado{emailSuffix}.",
|
||||
"auth.invite.reissueTitle": "VÃÂa de reemisión:",
|
||||
"auth.invite.reissueBody": "si cambió tu correo real de acceso (desfase de correo), pide a un administrador de la empresa que revoque esta invitación y envÃÂe una nueva al correo con el que inicias sesión. Los administradores de plataforma también pueden reemitir enlaces para establecer contraseña desde Admin → Usuarios.",
|
||||
"auth.invite.reissueBody": "pide a un administrador de la empresa que reemita un enlace para establecer contraseña a este correo, o que revoque esta invitación y envíe una nueva al correo con el que inicias sesión.",
|
||||
"locale.switcher": "Idioma de la interfaz",
|
||||
"locale.menu": "Elegir idioma de la interfaz",
|
||||
"locale.label": "Idioma del panel",
|
||||
@@ -276,7 +276,7 @@ export const es: MessageDict = {
|
||||
"settings.table.lastUsed": "Último uso",
|
||||
"dashboard.demoSandbox": "Zona de pruebas demo",
|
||||
"dashboard.demoEmptyTitle": "La zona de pruebas demo está vacÃÂa",
|
||||
"dashboard.demoEmptyHint": "La zona de pruebas demo está vacÃÂa  cambia a A1 o conecta un feed para ver estadÃÂsticas reales del catálogo.",
|
||||
"dashboard.demoEmptyHint": "La zona de pruebas demo está vacía — conecta un feed para ver estadísticas reales del catálogo.",
|
||||
"dashboard.overviewTitle": "Resumen",
|
||||
"dashboard.quickLinks": "Enlaces rápidos",
|
||||
"dashboard.whatsNew": "Novedades",
|
||||
@@ -319,7 +319,7 @@ export const es: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Mapear y exportar",
|
||||
"dashboard.workflowHint": "Catálogo dentro → enriquecer / procesar → exportar o enviar a tiendas. Salta al siguiente paso para {name}.",
|
||||
"dashboard.overviewHint": "Totales en vivo para {name}",
|
||||
"dashboard.demoEmptyMessage": "Cambia a A1 (u otra empresa con datos) en el encabezado, o conecta un feed aquàpara poblar esta zona de pruebas.",
|
||||
"dashboard.demoEmptyMessage": "Conecta un feed aquí para poblar esta zona de pruebas, o cambia a otra empresa en el encabezado.",
|
||||
"dashboard.emptyTitle": "Importa un catálogo",
|
||||
"dashboard.emptyMessage": "Catálogo dentro → enriquecer / procesar → exportar o enviar a tiendas. Empieza con Primeros pasos abajo (o conecta un feed / sube un CSV).",
|
||||
"dashboard.connectFeedAnyway": "Conectar feed de todos modos",
|
||||
@@ -367,29 +367,29 @@ export const es: MessageDict = {
|
||||
"activation.focus.sync": "Siguiente: sincroniza una muestra tras guardar el mapeo. Usa Sync en un feed mapeado  evita sincronizar orÃÂgenes sin mapear.",
|
||||
"activation.focus.dismiss": "Cerrar aviso",
|
||||
"activation.dismiss": "Descartar lista",
|
||||
"hypercare.report.title": "Hypercare de corte",
|
||||
"hypercare.report.title": "¿Necesitas ayuda tras el traslado?",
|
||||
"hypercare.report.message": "¿Faltan o están incorrectos datos tras la migración? Repórtalo para que podamos corregir tu espacio de trabajo.",
|
||||
"hypercare.report.cta": "Reportar datos faltantes o incorrectos",
|
||||
"hypercare.report.dismiss": "Descartar",
|
||||
"hypercare.report.adminTriage": "Abrir cola de hypercare",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -3690,6 +3690,7 @@ export const es: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "El trabajo recién iniciado se canceló.",
|
||||
"processing.receipt.cancelFailed": "No se pudo cancelar el trabajo de procesamiento",
|
||||
"unsubscribe.title": "Cancelar suscripción",
|
||||
"unsubscribe.useEmailLink": "Usa el enlace de baja del correo que te enviamos. Abrir esta pagina sin ese enlace no puede cambiar tus preferencias de email.",
|
||||
"unsubscribe.me": "Cancelar mi suscripción",
|
||||
"unsubscribe.invalidLink": "Enlace no válido",
|
||||
"unsubscribe.failedShort": "Error al cancelar la suscripción",
|
||||
@@ -4727,6 +4728,10 @@ export const es: MessageDict = {
|
||||
"seo.terms.description": "Términos de uso de Descrybe: importación de feeds, enriquecimiento de catálogo, contenido asistido por IA, exportaciones y sincronización con WooCommerce para tu negocio.",
|
||||
"seo.features.title": "Funciones  Feeds, enriquecimiento y exportación | Descrybe",
|
||||
"seo.features.description": "Descubre cómo Descrybe importa feeds de proveedores, mapea campos a tu taxonomÃÂa, enriquece datos de producto y envÃÂa catálogos mediante feeds de exportación, WooCommerce o API.",
|
||||
"seo.contactSales.title": "Contacto comercial | Descrybe",
|
||||
"seo.contactSales.description": "Cuentanos sobre tu catalogo y necesidades de capacidad: prepararemos un plan personalizado que puedes pagar en linea.",
|
||||
"seo.unsubscribe.title": "Cancelar suscripcion | Descrybe",
|
||||
"seo.unsubscribe.description": "Deja de recibir emails de marketing de Descrybe usando el enlace de baja del mensaje que te enviamos.",
|
||||
"pricing.page.eyebrow": "Precios",
|
||||
"pricing.page.title": "Planes sencillos para catálogos en crecimiento",
|
||||
"pricing.page.lead": "Empieza gratis con mapeo de feeds y limpieza básica. Mejora cuando necesites tÃÂtulos y descripciones con IA, más productos, feeds de exportación o sincronización con WooCommerce  de Starter a Enterprise.",
|
||||
@@ -4734,6 +4739,8 @@ export const es: MessageDict = {
|
||||
"pricing.page.subscribedMid": "o compara planes en",
|
||||
"pricing.page.plansLink": "Planes",
|
||||
"pricing.page.subscribedAfter": ".",
|
||||
"pricing.page.guestSubscribedBefore": "Ya estas suscrito?",
|
||||
"pricing.page.guestSubscribedAfter": "para gestionar la facturacion y comparar planes.",
|
||||
"legal.lastUpdated": "Última actualización: {date}",
|
||||
"legal.backHome": "↠Volver al inicio",
|
||||
"legal.emailLabel": "Correo electrónico:",
|
||||
@@ -5065,7 +5072,7 @@ export const es: MessageDict = {
|
||||
"brand.uploadLogo": "Subir logo",
|
||||
"brand.clear": "Borrar",
|
||||
"brand.field.logoUrl": "URL del logo",
|
||||
"brand.placeholder.logoUrl": "https://… o subido /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "Vista previa del logo de marca",
|
||||
"brand.tipsTitle": "Consejos de fórmula / vista previa",
|
||||
"brand.saving": "Guardando…",
|
||||
@@ -5226,6 +5233,8 @@ export const es: MessageDict = {
|
||||
"pricing.section.publicBefore": "Planes públicos: Free, Starter, Growth, Business y Enterprise. Crea una cuenta Free y luego mejora en",
|
||||
"pricing.section.publicOr": "o",
|
||||
"pricing.section.publicAfter": "mediante Stripe Checkout. Enterprise sigue siendo con ventas.",
|
||||
"pricing.section.guestPublicBefore": "Planes publicos: Free, Starter, Plus, Growth, Business, Scale y Enterprise. Crea una cuenta Free y luego",
|
||||
"pricing.section.guestPublicAfter": "para mejorar via Stripe Checkout. Enterprise sigue gestionado por ventas.",
|
||||
"pricing.section.plansLink": "Planes",
|
||||
"pricing.section.billingLink": "Facturación",
|
||||
"pricing.section.capabilitiesTitle": "Para qué está pensado cada plan",
|
||||
@@ -5291,7 +5300,7 @@ export const es: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Más popular",
|
||||
"pricing.card.custom": "Personalizado",
|
||||
"pricing.card.forever": "para siempre",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const fr: MessageDict = {
|
||||
"auth.login.failed": "Échec de la connexion",
|
||||
"auth.login.passwordNotSet": "Ce compte a encore besoin d'un mot de passe. Ouvrez votre lien d'invitation, ou demandez àun administrateur d'en émettre un nouveau.",
|
||||
"auth.login.setPasswordFirstTitle": "Définissez d'abord le mot de passe :",
|
||||
"auth.login.setPasswordFirstBody": "utilisez le lien d'invitation de votre e-mail. Si le lien a été envoyé àune ancienne adresse (dérive d'e-mail), demandez àun administrateur de l'entreprise de renvoyer une invitation de définition de mot de passe à{email}.",
|
||||
"auth.login.setPasswordFirstBody": "utilisez le lien d'invitation de votre e-mail. Si vous avez besoin d'un nouveau lien, demandez à un administrateur de l'entreprise de réémettre un lien de définition de mot de passe à {email}.",
|
||||
"auth.login.yourEmail": "votre e-mail",
|
||||
"auth.login.platformAdminsReissue": "Les administrateurs de la plateforme peuvent réémettre depuis",
|
||||
"auth.login.adminUsersLink": "Admin → Utilisateurs",
|
||||
@@ -144,9 +144,9 @@ export const fr: MessageDict = {
|
||||
"auth.invite.acceptFailed": "Impossible d'accepter l'invitation",
|
||||
"auth.invite.setPasswordFailed": "Impossible de définir le mot de passe",
|
||||
"auth.invite.expired": "Cette invitation est invalide ou expirée. Demandez àvotre administrateur d'envoyer une nouvelle invitation, puis ouvrez le nouveau lien (ou collez le nouveau jeton ci-dessous).",
|
||||
"auth.invite.setPasswordExpired": "Ce lien de définition de mot de passe est invalide ou expiré. Demandez àun administrateur de l'entreprise ou de la plateforme de le réémettre, puis ouvrez le nouveau lien (ou collez le nouveau jeton ci-dessous).",
|
||||
"auth.invite.setPasswordExpired": "Ce lien de définition de mot de passe est invalide ou expiré. Demandez à un administrateur de l'entreprise de réémettre un lien de définition de mot de passe vers cet e-mail, puis ouvrez le nouveau lien (ou collez le nouveau jeton ci-dessous).",
|
||||
"auth.invite.emailMismatchDefault": "Vous êtes connecté avec un e-mail différent de celui de cette invitation.",
|
||||
"auth.invite.expiredFooter": "Lien expiré ? Demandez àun administrateur de le réémettre  il n'y a pas d'API de renvoi en libre-service. Administrateurs de plateforme :",
|
||||
"auth.invite.expiredFooter": "Lien expiré ? Demandez à un administrateur de l'entreprise de le réémettre — il n'y a pas d'API de renvoi en libre-service.",
|
||||
"auth.invite.adminUsersLink": "Admin → Utilisateurs",
|
||||
"auth.invite.doneTitle": "Vous faites partie de l'équipe",
|
||||
"auth.invite.doneSetPasswordTitle": "Mot de passe enregistré",
|
||||
@@ -163,7 +163,7 @@ export const fr: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Changer de compte :",
|
||||
"auth.invite.switchAccountBody": "déconnectez-vous, puis terminez ce formulaire avec l'e-mail invité{emailSuffix}.",
|
||||
"auth.invite.reissueTitle": "Chemin de réémission :",
|
||||
"auth.invite.reissueBody": "si votre vrai e-mail de connexion a changé (dérive d'e-mail), demandez àun administrateur de l'entreprise de révoquer cette invitation et d'en envoyer une nouvelle àl'e-mail que vous utilisez pour vous connecter. Les administrateurs de la plateforme peuvent aussi réémettre des liens de définition de mot de passe depuis Admin → Utilisateurs.",
|
||||
"auth.invite.reissueBody": "demandez à un administrateur de l'entreprise de réémettre un lien de définition de mot de passe vers cet e-mail, ou de révoquer cette invitation et d'en envoyer une nouvelle à l'e-mail que vous utilisez pour vous connecter.",
|
||||
"locale.switcher": "Langue de l'interface",
|
||||
"locale.menu": "Choisir la langue de l'interface",
|
||||
"locale.label": "Langue du tableau de bord",
|
||||
@@ -276,7 +276,7 @@ export const fr: MessageDict = {
|
||||
"settings.table.lastUsed": "Dernière utilisation",
|
||||
"dashboard.demoSandbox": "Bac àsable démo",
|
||||
"dashboard.demoEmptyTitle": "Le bac àsable démo est vide",
|
||||
"dashboard.demoEmptyHint": "Le bac àsable démo est vide  basculez vers A1 ou connectez un flux pour voir de vraies stats catalogue.",
|
||||
"dashboard.demoEmptyHint": "Le bac à sable démo est vide — connectez un flux pour voir de vraies stats catalogue.",
|
||||
"dashboard.overviewTitle": "Vue d'ensemble",
|
||||
"dashboard.quickLinks": "Liens rapides",
|
||||
"dashboard.whatsNew": "Nouveautés",
|
||||
@@ -319,7 +319,7 @@ export const fr: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Mapper puis exporter",
|
||||
"dashboard.workflowHint": "Catalogue entrant → enrichir / traiter → exporter ou pousser vers les boutiques. Passez àl’étape suivante pour {name}.",
|
||||
"dashboard.overviewHint": "Totaux en direct pour {name}",
|
||||
"dashboard.demoEmptyMessage": "Basculez vers A1 (ou une autre entreprise seedée) dans l'en-tête, ou connectez un flux ici pour remplir ce bac àsable.",
|
||||
"dashboard.demoEmptyMessage": "Connectez un flux ici pour remplir ce bac à sable, ou basculez vers une autre entreprise dans l'en-tête.",
|
||||
"dashboard.emptyTitle": "Importez un catalogue",
|
||||
"dashboard.emptyMessage": "Catalogue entrant → enrichir / traiter → exporter ou pousser vers les boutiques. Commencez avec Premiers pas ci-dessous (ou connectez un flux / téléversez un CSV).",
|
||||
"dashboard.connectFeedAnyway": "Connecter un flux quand même",
|
||||
@@ -367,29 +367,29 @@ export const fr: MessageDict = {
|
||||
"activation.focus.sync": "Ensuite : synchronisez un échantillon après l’enregistrement du mapping. Utilisez Sync sur un flux mappé  évitez les sources non mappées.",
|
||||
"activation.focus.dismiss": "Fermer l’indication",
|
||||
"activation.dismiss": "Masquer la checklist",
|
||||
"hypercare.report.title": "Hypercare de bascule",
|
||||
"hypercare.report.title": "Besoin d'aide après le transfert ?",
|
||||
"hypercare.report.message": "Données manquantes ou incorrectes après la migration ? Signalez-le pour que nous corrigions votre espace de travail.",
|
||||
"hypercare.report.cta": "Signaler des données manquantes ou incorrectes",
|
||||
"hypercare.report.dismiss": "Ignorer",
|
||||
"hypercare.report.adminTriage": "Ouvrir la file hypercare",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -3690,6 +3690,7 @@ export const fr: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "La tâche qui vient de démarrer a été annulée.",
|
||||
"processing.receipt.cancelFailed": "Impossible d'annuler la tâche de traitement",
|
||||
"unsubscribe.title": "Se désabonner",
|
||||
"unsubscribe.useEmailLink": "Utilisez le lien de desabonnement dans l'e-mail que nous vous avons envoye. Ouvrir cette page sans ce lien ne peut pas modifier vos preferences e-mail.",
|
||||
"unsubscribe.me": "Me désabonner",
|
||||
"unsubscribe.invalidLink": "Lien invalide",
|
||||
"unsubscribe.failedShort": "Échec du désabonnement",
|
||||
@@ -4727,6 +4728,10 @@ export const fr: MessageDict = {
|
||||
"seo.terms.description": "Conditions d'utilisation de Descrybe : import de flux, enrichissement de catalogue, contenu assisté par IA, exports et synchronisation WooCommerce pour votre entreprise.",
|
||||
"seo.features.title": "Fonctionnalités  Flux, enrichissement et export | Descrybe",
|
||||
"seo.features.description": "Découvrez comment Descrybe importe les flux fournisseurs, mappe les champs àvotre taxonomie, enrichit les données produit et diffuse les catalogues via flux d'export, WooCommerce ou API.",
|
||||
"seo.contactSales.title": "Contacter les ventes | Descrybe",
|
||||
"seo.contactSales.description": "Parlez-nous de votre catalogue et de vos besoins de capacite: nous preparerons une offre personnalisee payable en ligne.",
|
||||
"seo.unsubscribe.title": "Se desabonner | Descrybe",
|
||||
"seo.unsubscribe.description": "Arretez les e-mails marketing Descrybe via le lien de desabonnement du message que nous vous avons envoye.",
|
||||
"pricing.page.eyebrow": "Tarifs",
|
||||
"pricing.page.title": "Des offres simples pour des catalogues en croissance",
|
||||
"pricing.page.lead": "Commencez gratuitement avec le mapping de flux et un nettoyage de base. Passez àun plan supérieur quand vous avez besoin de titres et descriptions IA, de plus de produits, d’exports ou de la sync WooCommerce  de Starter àEnterprise.",
|
||||
@@ -4734,6 +4739,8 @@ export const fr: MessageDict = {
|
||||
"pricing.page.subscribedMid": "ou comparez les offres dans",
|
||||
"pricing.page.plansLink": "Offres",
|
||||
"pricing.page.subscribedAfter": ".",
|
||||
"pricing.page.guestSubscribedBefore": "Deja abonne?",
|
||||
"pricing.page.guestSubscribedAfter": "pour gerer la facturation et comparer les offres.",
|
||||
"legal.lastUpdated": "Dernière mise àjour : {date}",
|
||||
"legal.backHome": "↠Retour àl’accueil",
|
||||
"legal.emailLabel": "E-mail :",
|
||||
@@ -5065,7 +5072,7 @@ export const fr: MessageDict = {
|
||||
"brand.uploadLogo": "Téléverser le logo",
|
||||
"brand.clear": "Effacer",
|
||||
"brand.field.logoUrl": "URL du logo",
|
||||
"brand.placeholder.logoUrl": "https://… ou téléversé /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "Aperçu du logo de marque",
|
||||
"brand.tipsTitle": "Conseils formule / aperçu",
|
||||
"brand.saving": "Enregistrement…",
|
||||
@@ -5226,6 +5233,8 @@ export const fr: MessageDict = {
|
||||
"pricing.section.publicBefore": "Offres publiques : Free, Starter, Growth, Business et Enterprise. Créez un compte Free, puis passez àun plan supérieur sous",
|
||||
"pricing.section.publicOr": "ou",
|
||||
"pricing.section.publicAfter": "via Stripe Checkout. Enterprise reste géré par les ventes.",
|
||||
"pricing.section.guestPublicBefore": "Offres publiques: Free, Starter, Plus, Growth, Business, Scale et Enterprise. Creez un compte Free, puis",
|
||||
"pricing.section.guestPublicAfter": "pour passer a un plan superieur via Stripe Checkout. Enterprise reste gere par les ventes.",
|
||||
"pricing.section.plansLink": "Offres",
|
||||
"pricing.section.billingLink": "Facturation",
|
||||
"pricing.section.capabilitiesTitle": "Ce pour quoi chaque offre est conçue",
|
||||
@@ -5291,7 +5300,7 @@ export const fr: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Le plus populaire",
|
||||
"pricing.card.custom": "Sur mesure",
|
||||
"pricing.card.forever": "pour toujours",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const it: MessageDict = {
|
||||
"auth.login.failed": "Accesso non riuscito",
|
||||
"auth.login.passwordNotSet": "Questo account richiede ancora una password. Apri il link di invito o chiedi a un amministratore di generarne uno nuovo.",
|
||||
"auth.login.setPasswordFirstTitle": "Imposta prima la password:",
|
||||
"auth.login.setPasswordFirstBody": "usa il link di invito dalla tua email. Se il link è andato a un indirizzo vecchio (deriva email), chiedi a un amministratore dell'azienda di riemettere un invito per impostare la password a {email}.",
|
||||
"auth.login.setPasswordFirstBody": "usa il link di invito dalla tua email. Se ti serve un nuovo link, chiedi a un amministratore dell'azienda di riemettere un link per impostare la password a {email}.",
|
||||
"auth.login.yourEmail": "la tua email",
|
||||
"auth.login.platformAdminsReissue": "Gli amministratori della piattaforma possono riemettere da",
|
||||
"auth.login.adminUsersLink": "Admin → Utenti",
|
||||
@@ -144,9 +144,9 @@ export const it: MessageDict = {
|
||||
"auth.invite.acceptFailed": "Impossibile accettare l'invito",
|
||||
"auth.invite.setPasswordFailed": "Impossibile impostare la password",
|
||||
"auth.invite.expired": "Questo invito non è valido o è scaduto. Chiedi all'amministratore dell'azienda di inviare un nuovo invito, poi apri il nuovo link (o incolla il nuovo token qui sotto).",
|
||||
"auth.invite.setPasswordExpired": "Questo link per impostare la password non è valido o è scaduto. Chiedi a un amministratore dell'azienda o della piattaforma di riemetterlo, poi apri il nuovo link (o incolla il nuovo token qui sotto).",
|
||||
"auth.invite.setPasswordExpired": "Questo link per impostare la password non è valido o è scaduto. Chiedi a un amministratore dell'azienda di riemettere un link per impostare la password a questa email, poi apri il nuovo link (o incolla il nuovo token qui sotto).",
|
||||
"auth.invite.emailMismatchDefault": "Hai effettuato l'accesso con un'email diversa da questo invito.",
|
||||
"auth.invite.expiredFooter": "Link scaduto? Chiedi a un amministratore di riemetterlo  non c'è un'API di reinvio self-service. Amministratori della piattaforma:",
|
||||
"auth.invite.expiredFooter": "Link scaduto? Chiedi a un amministratore dell'azienda di riemetterlo — non c'è un'API di reinvio self-service.",
|
||||
"auth.invite.adminUsersLink": "Admin → Utenti",
|
||||
"auth.invite.doneTitle": "Fai parte del team",
|
||||
"auth.invite.doneSetPasswordTitle": "Password salvata",
|
||||
@@ -163,7 +163,7 @@ export const it: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Cambia account:",
|
||||
"auth.invite.switchAccountBody": "esci, poi completa questo modulo con l'email invitata{emailSuffix}.",
|
||||
"auth.invite.reissueTitle": "Percorso di riemissione:",
|
||||
"auth.invite.reissueBody": "se la tua email di accesso reale è cambiata (deriva email), chiedi a un amministratore dell'azienda di revocare questo invito e inviarne uno nuovo all'email con cui accedi. Gli amministratori della piattaforma possono anche riemettere link per impostare la password da Admin → Utenti.",
|
||||
"auth.invite.reissueBody": "chiedi a un amministratore dell'azienda di riemettere un link per impostare la password a questa email, oppure di revocare questo invito e inviarne uno nuovo all'email con cui accedi.",
|
||||
"locale.switcher": "Lingua dell'interfaccia",
|
||||
"locale.menu": "Scegli la lingua dell'interfaccia",
|
||||
"locale.label": "Lingua della dashboard",
|
||||
@@ -276,7 +276,7 @@ export const it: MessageDict = {
|
||||
"settings.table.lastUsed": "Ultimo utilizzo",
|
||||
"dashboard.demoSandbox": "Sandbox demo",
|
||||
"dashboard.demoEmptyTitle": "La sandbox demo è vuota",
|
||||
"dashboard.demoEmptyHint": "La sandbox demo è vuota  passa ad A1 o collega un feed per vedere statistiche reali del catalogo.",
|
||||
"dashboard.demoEmptyHint": "La sandbox demo è vuota — collega un feed per vedere statistiche reali del catalogo.",
|
||||
"dashboard.overviewTitle": "Panoramica",
|
||||
"dashboard.quickLinks": "Collegamenti rapidi",
|
||||
"dashboard.whatsNew": "Novità",
|
||||
@@ -319,7 +319,7 @@ export const it: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Mappa poi esporta",
|
||||
"dashboard.workflowHint": "Catalogo in ingresso → arricchisci / elabora → esporta o invia agli store. Vai al passo successivo per {name}.",
|
||||
"dashboard.overviewHint": "Totali in tempo reale per {name}",
|
||||
"dashboard.demoEmptyMessage": "Passa ad A1 (o un'altra azienda con dati) nell'intestazione, oppure collega un feed qui per popolare questa sandbox.",
|
||||
"dashboard.demoEmptyMessage": "Collega un feed qui per popolare questa sandbox, oppure passa a un'altra azienda nell'intestazione.",
|
||||
"dashboard.emptyTitle": "Importa un catalogo",
|
||||
"dashboard.emptyMessage": "Catalogo in ingresso → arricchisci / elabora → esporta o invia agli store. Inizia con Per iniziare qui sotto (o collega un feed / carica un CSV).",
|
||||
"dashboard.connectFeedAnyway": "Collega comunque un feed",
|
||||
@@ -367,29 +367,29 @@ export const it: MessageDict = {
|
||||
"activation.focus.sync": "Avanti: sincronizza un campione dopo aver salvato la mappatura. Usa Sync su un feed mappato  evita fonti non mappate.",
|
||||
"activation.focus.dismiss": "Chiudi suggerimento",
|
||||
"activation.dismiss": "Nascondi checklist",
|
||||
"hypercare.report.title": "Hypercare di cutover",
|
||||
"hypercare.report.title": "Serve aiuto dopo il trasferimento?",
|
||||
"hypercare.report.message": "Dati mancanti o errati dopo la migrazione? Segnalalo così possiamo correggere il tuo workspace.",
|
||||
"hypercare.report.cta": "Segnala dati mancanti o errati",
|
||||
"hypercare.report.dismiss": "Ignora",
|
||||
"hypercare.report.adminTriage": "Apri coda hypercare",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -456,9 +456,9 @@ export const it: MessageDict = {
|
||||
"errors.readOnly": "Il sistema è in modalitàsola lettura. Le modifiche sono temporaneamente disabilitate.",
|
||||
"errors.companyAdminDenied": "Solo gli amministratori dell'azienda possono {action}. Chiedi aiuto a un amministratore.",
|
||||
"errors.companyAdminDenied.actionDefault": "fare questo",
|
||||
"docs.tryIt.memberCannotCreate": "Solo gli admin azienda possono creare chiavi API. Le chiavi legacy non sono state migrate  incolla una chiave sotto o chiedi a un admin di crearne una nuova.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "Le chiavi API legacy non sono state migrate. Creane una con Use my API key o Impostazioni → Chiavi API  il secret è mostrato una sola volta.",
|
||||
"docs.tryIt.noKeysLegacyMember": "Nessuna chiave API elencata. Le chiavi legacy non sono state migrate  chiedi a un admin di crearne una, o incolla una chiave dk_.",
|
||||
"docs.tryIt.memberCannotCreate": "Solo gli admin azienda possono creare chiavi API. Le chiavi non sono state migrate  incolla una chiave sotto o chiedi a un admin di crearne una nuova.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "Le chiavi API non sono state migrate. Creane una con Use my API key o Impostazioni → Chiavi API  il secret è mostrato una sola volta.",
|
||||
"docs.tryIt.noKeysLegacyMember": "Nessuna chiave API elencata. Le chiavi non sono state migrate  chiedi a un admin di crearne una, o incolla una chiave dk_.",
|
||||
"errors.couldNotUpdateLanguage": "Impossibile aggiornare la lingua",
|
||||
"toast.support.replyTitle": "Risposta del supporto",
|
||||
"toast.support.replyBody": "Lo staff ha risposto al tuo ticket di supporto.",
|
||||
@@ -3690,6 +3690,7 @@ export const it: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "Il processo appena avviato è stato annullato.",
|
||||
"processing.receipt.cancelFailed": "Impossibile annullare il processo",
|
||||
"unsubscribe.title": "Annulla iscrizione",
|
||||
"unsubscribe.useEmailLink": "Usa il link di disiscrizione nell'email che ti abbiamo inviato. Aprire questa pagina senza quel link non puo modificare le preferenze email.",
|
||||
"unsubscribe.me": "Annulla la mia iscrizione",
|
||||
"unsubscribe.invalidLink": "Link non valido",
|
||||
"unsubscribe.failedShort": "Annullamento iscrizione non riuscito",
|
||||
@@ -4727,6 +4728,10 @@ export const it: MessageDict = {
|
||||
"seo.terms.description": "Termini di utilizzo di Descrybe: importazione di feed, arricchimento del catalogo, contenuti assistiti da IA, esportazioni e sincronizzazione WooCommerce per la tua azienda.",
|
||||
"seo.features.title": "Funzionalità Feed, arricchimento ed esportazione | Descrybe",
|
||||
"seo.features.description": "Scopri come Descrybe importa i feed dei fornitori, mappa i campi alla tua tassonomia, arricchisce i dati di prodotto e distribuisce i cataloghi tramite feed di esportazione, WooCommerce o API.",
|
||||
"seo.contactSales.title": "Contatta le vendite | Descrybe",
|
||||
"seo.contactSales.description": "Parlaci del tuo catalogo e delle esigenze di capacita: prepareremo un piano personalizzato che puoi pagare online.",
|
||||
"seo.unsubscribe.title": "Annulla iscrizione | Descrybe",
|
||||
"seo.unsubscribe.description": "Interrompi le email di marketing Descrybe usando il link di disiscrizione nel messaggio che ti abbiamo inviato.",
|
||||
"pricing.page.eyebrow": "Prezzi",
|
||||
"pricing.page.title": "Piani semplici per cataloghi in crescita",
|
||||
"pricing.page.lead": "Inizia gratis con mappatura feed e pulizia di base. Passa a un piano superiore quando ti servono titoli e descrizioni IA, più prodotti, feed di esportazione o sync WooCommerce  da Starter a Enterprise.",
|
||||
@@ -4734,6 +4739,8 @@ export const it: MessageDict = {
|
||||
"pricing.page.subscribedMid": "o confronta i piani in",
|
||||
"pricing.page.plansLink": "Piani",
|
||||
"pricing.page.subscribedAfter": ".",
|
||||
"pricing.page.guestSubscribedBefore": "Gia abbonato?",
|
||||
"pricing.page.guestSubscribedAfter": "per gestire la fatturazione e confrontare i piani.",
|
||||
"legal.lastUpdated": "Ultimo aggiornamento: {date}",
|
||||
"legal.backHome": "↠Torna alla home",
|
||||
"legal.emailLabel": "Email:",
|
||||
@@ -5065,7 +5072,7 @@ export const it: MessageDict = {
|
||||
"brand.uploadLogo": "Carica logo",
|
||||
"brand.clear": "Cancella",
|
||||
"brand.field.logoUrl": "URL del logo",
|
||||
"brand.placeholder.logoUrl": "https://… oppure caricato /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "Anteprima logo del brand",
|
||||
"brand.tipsTitle": "Suggerimenti formula / anteprima",
|
||||
"brand.saving": "Salvataggio…",
|
||||
@@ -5226,6 +5233,8 @@ export const it: MessageDict = {
|
||||
"pricing.section.publicBefore": "Piani pubblici: Free, Starter, Growth, Business ed Enterprise. Crea un account Free, poi passa a un piano superiore in",
|
||||
"pricing.section.publicOr": "o",
|
||||
"pricing.section.publicAfter": "tramite Stripe Checkout. Enterprise resta gestito dalle vendite.",
|
||||
"pricing.section.guestPublicBefore": "Piani pubblici: Free, Starter, Plus, Growth, Business, Scale ed Enterprise. Crea un account Free, poi",
|
||||
"pricing.section.guestPublicAfter": "per passare a un piano superiore tramite Stripe Checkout. Enterprise resta gestito dalle vendite.",
|
||||
"pricing.section.plansLink": "Piani",
|
||||
"pricing.section.billingLink": "Fatturazione",
|
||||
"pricing.section.capabilitiesTitle": "A cosa è pensato ogni piano",
|
||||
@@ -5291,7 +5300,7 @@ export const it: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Più popolare",
|
||||
"pricing.card.custom": "Personalizzato",
|
||||
"pricing.card.forever": "per sempre",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const ja: MessageDict = {
|
||||
"auth.login.failed": "ãƒÂグインã«失敗ã—ã¾ã—ãŸ",
|
||||
"auth.login.passwordNotSet": "ã“ã®アカウントã«ã¯ã¾ã パスワードãŒ必è¦Âã§ã™。招待リンクを開ãÂÂã‹ã€Â管ç†者ã«å†Â発行をä¾Âé ¼ã—ã¦ãÂÂã ã•ã„。",
|
||||
"auth.login.setPasswordFirstTitle": "å…ˆã«パスワードをè¨Â定:",
|
||||
"auth.login.setPasswordFirstBody": "メールã®招待リンクを使çâ€Â¨Ã£Â—ã¦ãÂÂã ã•ã„。リンクãÂŒå¤ã„アドレスã«é€ÂられãŸ場åˆ(メール変更)ã€Â会社ã®管ç†者ã« {email} å‘ã‘ã®パスワードè¨Â定招待ã®å†Â発行をä¾Âé ¼ã—ã¦ãÂÂã ã•ã„。",
|
||||
"auth.login.setPasswordFirstBody": "メールの招待リンクを使用してください。新しいリンクが必要な場合は、会社の管理者に {email} 向けのパスワード設定リンクの再発行を依頼してください。",
|
||||
"auth.login.yourEmail": "ã‚ãªãŸã®メール",
|
||||
"auth.login.platformAdminsReissue": "プラットフォーム管ç†者ã¯次ã‹らå†Â発行ã§ãÂÂã¾ã™:",
|
||||
"auth.login.adminUsersLink": "管ç†→ ユーザー",
|
||||
@@ -144,9 +144,9 @@ export const ja: MessageDict = {
|
||||
"auth.invite.acceptFailed": "招待を承èªÂã§ãÂÂã¾ã›んã§ã—ãŸ",
|
||||
"auth.invite.setPasswordFailed": "パスワードをè¨Â定ã§ãÂÂã¾ã›んã§ã—ãŸ",
|
||||
"auth.invite.expired": "ã“ã®招待ã¯無åйã¾ãŸã¯期é™Â切れã§ã™。会社ã®管ç†者ã«新ã—ã„招待ã®é€Âä¿¡ã‚’ä¾Âé ¼ã—ã€Âæ–°ã—ã„リンクを開ãÂÂã‹(下ã«新ã—ã„トークンを貼り付ã‘ã¦ãÂÂã ã•ã„)。",
|
||||
"auth.invite.setPasswordExpired": "ã“ã®パスワードè¨Â定リンクã¯無åйã¾ãŸã¯期é™Â切れã§ã™。会社ã¾ãŸã¯プラットフォームã®管ç†者ã«å†Â発行をä¾Âé ¼ã—ã€Âæ–°ã—ã„リンクを開ãÂÂã‹(下ã«新ã—ã„トークンを貼り付ã‘ã¦ãÂÂã ã•ã„)。",
|
||||
"auth.invite.setPasswordExpired": "このパスワード設定リンクは無効または期限切れです。会社の管理者にこのメール向けのパスワード設定リンクの再発行を依頼し、新しいリンクを開くか(下に新しいトークンを貼り付けてください)。",
|
||||
"auth.invite.emailMismatchDefault": "ã“ã®招待ã¨ã¯別ã®メールアドレスã§ãƒÂグインã—ã¦ã„ã¾ã™。",
|
||||
"auth.invite.expiredFooter": "期é™Â切れã®リンクã§ã™ã‹?管ç†者ã«å†Â発行をä¾Âé ¼ã—ã¦ãÂÂã ã•ã„  セルフサービスã®å†Âé€Âä¿¡APIã¯ã‚りã¾ã›ん。プラットフォーム管ç†者:",
|
||||
"auth.invite.expiredFooter": "期限切れのリンクですか?会社の管理者に再発行を依頼してください — セルフサービスの再送信APIはありません。",
|
||||
"auth.invite.adminUsersLink": "管ç†→ ユーザー",
|
||||
"auth.invite.doneTitle": "ãƒÂームã«å‚加ã—ã¾ã—ãŸ",
|
||||
"auth.invite.doneSetPasswordTitle": "パスワードをä¿Âå˜ã—ã¾ã—ãŸ",
|
||||
@@ -163,7 +163,7 @@ export const ja: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "アカウント切替:",
|
||||
"auth.invite.switchAccountBody": "ãƒÂグアウトã—ã¦ã‹らã€Â招待ã•れãŸメール{emailSuffix}ã§ã“ã®フォームを完了ã—ã¦ãÂÂã ã•ã„。",
|
||||
"auth.invite.reissueTitle": "å†Â発行ã®手順:",
|
||||
"auth.invite.reissueBody": "実際ã®ãƒÂグインçâ€Â¨Ã£Æ’¡ãƒ¼ãƒ«ãŒ変ã‚Âã£ãŸ場åˆ(メール変更)ã€Â会社ã®管ç†者ã«ã“ã®招待ã®å–り消ã—ã¨ã€ÂãƒÂグインã«使ã†メールã¸ã®新ã—ã„招待é€Âä¿¡ã‚’ä¾Âé ¼ã—ã¦ãÂÂã ã•ã„。プラットフォーム管ç†者ã¯「管ç†→ ユーザーã€Âã‹らパスワードè¨Â定リンクもå†Â発行ã§ãÂÂã¾ã™。",
|
||||
"auth.invite.reissueBody": "会社の管理者にこのメール向けのパスワード設定リンクの再発行を依頼するか、この招待を取り消してログインに使うメールへ新しい招待を送るよう依頼してください。",
|
||||
"locale.switcher": "インターフェース言語",
|
||||
"locale.menu": "インターフェース言語をé¸択",
|
||||
"locale.label": "ダッシュボードã®言語",
|
||||
@@ -276,7 +276,7 @@ export const ja: MessageDict = {
|
||||
"settings.table.lastUsed": "最終使çâ€Â¨",
|
||||
"dashboard.demoSandbox": "デモサンドボックス",
|
||||
"dashboard.demoEmptyTitle": "デモサンドボックスã¯空ã§ãÂâ„¢",
|
||||
"dashboard.demoEmptyHint": "デモサンドボックスã¯空ã§ãÂâ„¢  A1ã«切り替ãˆるã‹フィードを接続ã—ã¦実際ã®カタãƒÂグ統計を表示ã—ã¾ã™。",
|
||||
"dashboard.demoEmptyHint": "デモサンドボックスは空です — フィードを接続して実際のカタログ統計を表示します。",
|
||||
"dashboard.overviewTitle": "概è¦Â",
|
||||
"dashboard.quickLinks": "クイックリンク",
|
||||
"dashboard.whatsNew": "æ–°ç€情報",
|
||||
@@ -319,7 +319,7 @@ export const ja: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "マップã—ã¦エクスãƒÂート",
|
||||
"dashboard.workflowHint": "ã‚«ã‚¿ãƒÂã‚°å–込 → 充実 / 処ç†→ エクスãƒÂートã¾ãŸã¯ストアã¸プッシュ。{name} ã®次ã®ステップã¸。",
|
||||
"dashboard.overviewHint": "{name} ã®リアルタイムåˆ計",
|
||||
"dashboard.demoEmptyMessage": "ヘッダーã§A1(ã¾ãŸã¯別ã®シード済ã¿会社)ã«切り替ãˆるã‹ã€Âã“ã“ã§フィードを接続ã—ã¦サンドボックスã«データを入れã¾ã™。",
|
||||
"dashboard.demoEmptyMessage": "ここでフィードを接続してサンドボックスにデータを入れるか、ヘッダーで別の会社に切り替えます。",
|
||||
"dashboard.emptyTitle": "ã‚«ã‚¿ãƒÂã‚°ã‚’å–り込む",
|
||||
"dashboard.emptyMessage": "ã‚«ã‚¿ãƒÂã‚°å–込 → 充実 / 処ç†→ エクスãƒÂートã¾ãŸã¯ストアã¸プッシュ。下ã®「ã¯ã˜ã‚Âã«ã€Âã‹ら開始(ã¾ãŸã¯フィード接続 / CSVアップãƒÂード)。",
|
||||
"dashboard.connectFeedAnyway": "ãÂÂれã§もフィードを接続",
|
||||
@@ -367,29 +367,29 @@ export const ja: MessageDict = {
|
||||
"activation.focus.sync": "次ã¸: マッãƒâ€Ã£Æ’³ã‚°ä¿Âå˜後ã«サンプルをåŒ期ã—ã¾ã™。マップ済ã¿フィードã§ Sync を使ã„ã€Â未マップã®ソースã¯é¿ã‘ã¦ãÂÂã ã•ã„。",
|
||||
"activation.focus.dismiss": "ヒントを閉ã˜る",
|
||||
"activation.dismiss": "ãƒÂェックリストを閉ã˜る",
|
||||
"hypercare.report.title": "カットオーãƒÂー hypercare",
|
||||
"hypercare.report.title": "移行後のサポートが必要ですか?",
|
||||
"hypercare.report.message": "移行後ã«データã®欠è½や誤りãÂ΋‚りã¾ã™ã‹?報告ã„ãŸã ã‘れã°ワークスペースを修æÂ£ã—ã¾ã™。",
|
||||
"hypercare.report.cta": "欠è½・誤ã£ãŸデータを報告",
|
||||
"hypercare.report.dismiss": "é–‰ã˜る",
|
||||
"hypercare.report.adminTriage": "hypercareã‚Âューを開ãÂÂ",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -3690,6 +3690,7 @@ export const ja: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "開始直後ã®ジョブãÂŒã‚Âャンセルã•れã¾ã—ãŸ。",
|
||||
"processing.receipt.cancelFailed": "処ç†ジョブをã‚Âャンセルã§ãÂÂã¾ã›んã§ã—ãŸ",
|
||||
"unsubscribe.title": "é…Âä¿¡åÂϾ¢",
|
||||
"unsubscribe.useEmailLink": "Use the unsubscribe link in the email we sent you. Opening this page without that link cannot change your email preferences.",
|
||||
"unsubscribe.me": "é…Âä¿¡ã‚’åÂϾ¢ã™る",
|
||||
"unsubscribe.invalidLink": "無効ãªリンク",
|
||||
"unsubscribe.failedShort": "é…Âä¿¡åÂϾ¢ã«失敗ã—ã¾ã—ãŸ",
|
||||
@@ -4727,6 +4728,10 @@ export const ja: MessageDict = {
|
||||
"seo.terms.description": "Descrybe ã®利çâ€Â¨Ã¦Â¡ä»¶ï¼šãƒ•ィードã®インãƒÂートã€Âã‚«ã‚¿ãƒÂã‚°ã®エンリッãƒÂメントã€ÂAI æâ€Â¯Ã¦Â´ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã€ÂエクスãƒÂートã€ÂãŠよã³ビジãƒÂスå‘ã‘ WooCommerce åŒ期。",
|
||||
"seo.features.title": "機能  フィードã€ÂエンリッãƒÂメントã€ÂエクスãƒÂート | Descrybe",
|
||||
"seo.features.description": "Descrybe ãŒサプライヤーフィードをå–り込ã¿ã€Âフィールドをタクソノミーã«マッãƒâ€Ã£Æ’³ã‚°ã—ã€Â商å“ÂデータをエンリッãƒÂã—ã€ÂエクスãƒÂートフィードã€ÂWooCommerceã€Âã¾ãŸã¯ API ã§カタãƒÂã‚°ã‚’é…Âä¿¡ã™る仕組ã¿をãÂâ€Ã§Â¢ÂºÃ¨ÂªÂãÂÂã ã•ã„。",
|
||||
"seo.contactSales.title": "Contact sales | Descrybe",
|
||||
"seo.contactSales.description": "Tell us about your catalog and capacity needs — we will prepare a custom plan you can pay online.",
|
||||
"seo.unsubscribe.title": "Unsubscribe | Descrybe",
|
||||
"seo.unsubscribe.description": "Stop marketing emails from Descrybe using the unsubscribe link in the message we sent you.",
|
||||
"pricing.page.eyebrow": "料金",
|
||||
"pricing.page.title": "æˆÂé•·ã™るカタãƒÂã‚°å‘ã‘ã®シンプルãªプラン",
|
||||
"pricing.page.lead": "フィードã®マッãƒâ€Ã£Æ’³ã‚°ã¨基本的ãª整形ã‹ら無料ã§始ã‚Âられã¾ã™。AI ã«よるタイトルï¼Â説明ã€Â商å“Âæ•°ã®増加ã€ÂエクスãƒÂートフィードã€ÂWooCommerce 連æÂºãŒ必è¦Âã«ãªã£ãŸらアップグレード  Starter ã‹ら Enterprise ã¾ã§。",
|
||||
@@ -4734,6 +4739,8 @@ export const ja: MessageDict = {
|
||||
"pricing.page.subscribedMid": "ã€Âプランæ¯â€Ã¨Â¼Æ’ã¯",
|
||||
"pricing.page.plansLink": "プラン",
|
||||
"pricing.page.subscribedAfter": "ã¸。",
|
||||
"pricing.page.guestSubscribedBefore": "Already subscribed?",
|
||||
"pricing.page.guestSubscribedAfter": "to manage billing and compare plans.",
|
||||
"legal.lastUpdated": "最終更新日: {date}",
|
||||
"legal.backHome": "↠ホームã«戻る",
|
||||
"legal.emailLabel": "メール:",
|
||||
@@ -5065,7 +5072,7 @@ export const ja: MessageDict = {
|
||||
"brand.uploadLogo": "ãƒÂゴをアップãƒÂード",
|
||||
"brand.clear": "クリア",
|
||||
"brand.field.logoUrl": "ãƒÂã‚´ URL",
|
||||
"brand.placeholder.logoUrl": "https://… ã¾ãŸã¯アップãƒÂード済ã¿ /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "ブランドãƒÂã‚´ã®プレビュー",
|
||||
"brand.tipsTitle": "æ•°å¼ / プレビューã®ヒント",
|
||||
"brand.saving": "ä¿Âå˜ä¸Â…",
|
||||
@@ -5226,6 +5233,8 @@ export const ja: MessageDict = {
|
||||
"pricing.section.publicBefore": "公開プラン:Freeã€ÂStarterã€ÂGrowthã€ÂBusinessã€ÂEnterprise。Freeアカウントを作æˆÂã—ã€ÂãÂÂã®後",
|
||||
"pricing.section.publicOr": "ã¾ãŸã¯",
|
||||
"pricing.section.publicAfter": "ã§Stripe Checkout経çâ€Â±Ã£Â§ã‚¢ãƒƒãƒ—グレード。Enterpriseã¯セールス主導ã®ã¾ã¾ã§ã™。",
|
||||
"pricing.section.guestPublicBefore": "Public plans: Free, Starter, Plus, Growth, Business, Scale, and Enterprise. Create a Free account, then",
|
||||
"pricing.section.guestPublicAfter": "to upgrade via Stripe Checkout. Enterprise remains sales-led.",
|
||||
"pricing.section.plansLink": "プラン",
|
||||
"pricing.section.billingLink": "請求",
|
||||
"pricing.section.capabilitiesTitle": "å„プランãŒ想定ã™るçâ€Â¨Ã©â‚¬â€",
|
||||
@@ -5291,7 +5300,7 @@ export const ja: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "一番人気",
|
||||
"pricing.card.custom": "カスタム",
|
||||
"pricing.card.forever": "ãšã£ã¨",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const nl: MessageDict = {
|
||||
"auth.login.failed": "Inloggen mislukt",
|
||||
"auth.login.passwordNotSet": "Dit account heeft nog een wachtwoord nodig. Open uw uitnodigingslink of vraag een beheerder om een nieuwe.",
|
||||
"auth.login.setPasswordFirstTitle": "Stel eerst een wachtwoord in:",
|
||||
"auth.login.setPasswordFirstBody": "gebruik de uitnodigingslink uit uw e-mail. Als de link naar een oud adres ging (e-maildrift), vraag dan een bedrijfsbeheerder om een nieuwe set-wachtwoorduitnodiging naar {email} te sturen.",
|
||||
"auth.login.setPasswordFirstBody": "gebruik de uitnodigingslink uit uw e-mail. Als u een nieuwe link nodig hebt, vraag dan een bedrijfsbeheerder om een set-wachtwoordlink opnieuw uit te geven naar {email}.",
|
||||
"auth.login.yourEmail": "uw e-mail",
|
||||
"auth.login.platformAdminsReissue": "Platformbeheerders kunnen opnieuw uitgeven via",
|
||||
"auth.login.adminUsersLink": "Admin → Gebruikers",
|
||||
@@ -144,9 +144,9 @@ export const nl: MessageDict = {
|
||||
"auth.invite.acceptFailed": "Uitnodiging kon niet worden geaccepteerd",
|
||||
"auth.invite.setPasswordFailed": "Wachtwoord kon niet worden ingesteld",
|
||||
"auth.invite.expired": "Deze uitnodiging is ongeldig of verlopen. Vraag uw bedrijfsbeheerder om een nieuwe uitnodiging te sturen en open de nieuwe link (of plak het nieuwe token hieronder).",
|
||||
"auth.invite.setPasswordExpired": "Deze set-wachtwoordlink is ongeldig of verlopen. Vraag een bedrijfs- of platformbeheerder om hem opnieuw uit te geven en open de nieuwe link (of plak het nieuwe token hieronder).",
|
||||
"auth.invite.setPasswordExpired": "Deze set-wachtwoordlink is ongeldig of verlopen. Vraag een bedrijfsbeheerder om een set-wachtwoordlink opnieuw uit te geven naar dit e-mailadres en open de nieuwe link (of plak het nieuwe token hieronder).",
|
||||
"auth.invite.emailMismatchDefault": "U bent ingelogd met een ander e-mailadres dan deze uitnodiging.",
|
||||
"auth.invite.expiredFooter": "Verlopen link? Vraag een beheerder om opnieuw uit te geven  er is geen self-service-API voor opnieuw verzenden. Platformbeheerders:",
|
||||
"auth.invite.expiredFooter": "Verlopen link? Vraag een bedrijfsbeheerder om opnieuw uit te geven — er is geen self-service-API voor opnieuw verzenden.",
|
||||
"auth.invite.adminUsersLink": "Admin → Gebruikers",
|
||||
"auth.invite.doneTitle": "U bent in het team",
|
||||
"auth.invite.doneSetPasswordTitle": "Wachtwoord opgeslagen",
|
||||
@@ -163,7 +163,7 @@ export const nl: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Account wisselen:",
|
||||
"auth.invite.switchAccountBody": "log uit en voltooi dit formulier met het uitgenodigde e-mailadres{emailSuffix}.",
|
||||
"auth.invite.reissueTitle": "Pad voor opnieuw uitgeven:",
|
||||
"auth.invite.reissueBody": "als uw echte login-e-mail is gewijzigd (e-maildrift), vraag dan een bedrijfsbeheerder om deze uitnodiging in te trekken en een nieuwe te sturen naar het e-mailadres waarmee u inlogt. Platformbeheerders kunnen ook set-wachtwoordlinks opnieuw uitgeven via Admin → Gebruikers.",
|
||||
"auth.invite.reissueBody": "vraag een bedrijfsbeheerder om een set-wachtwoordlink opnieuw uit te geven naar dit e-mailadres, of om deze uitnodiging in te trekken en een nieuwe te sturen naar het e-mailadres waarmee u inlogt.",
|
||||
"locale.switcher": "Interfacetaal",
|
||||
"locale.menu": "Kies interfacetaal",
|
||||
"locale.label": "Dashboardtaal",
|
||||
@@ -276,7 +276,7 @@ export const nl: MessageDict = {
|
||||
"settings.table.lastUsed": "Laatst gebruikt",
|
||||
"dashboard.demoSandbox": "Demo-sandbox",
|
||||
"dashboard.demoEmptyTitle": "Demo-sandbox is leeg",
|
||||
"dashboard.demoEmptyHint": "Demo-sandbox is leeg  schakel over naar A1 of koppel een feed om echte catalogusstatistieken te zien.",
|
||||
"dashboard.demoEmptyHint": "Demo-sandbox is leeg — koppel een feed om echte catalogusstatistieken te zien.",
|
||||
"dashboard.overviewTitle": "Overzicht",
|
||||
"dashboard.quickLinks": "Snelle links",
|
||||
"dashboard.whatsNew": "Wat is nieuw",
|
||||
@@ -319,7 +319,7 @@ export const nl: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Mappen en exporteren",
|
||||
"dashboard.workflowHint": "Catalogus in → verrijken / verwerken → exporteren of pushen naar winkels. Ga naar de volgende stap voor {name}.",
|
||||
"dashboard.overviewHint": "Live totalen voor {name}",
|
||||
"dashboard.demoEmptyMessage": "Schakel in de header over naar A1 (of een ander geseeded bedrijf), of koppel hier een feed om deze sandbox te vullen.",
|
||||
"dashboard.demoEmptyMessage": "Koppel hier een feed om deze sandbox te vullen, of schakel in de header over naar een ander bedrijf.",
|
||||
"dashboard.emptyTitle": "Haal een catalogus binnen",
|
||||
"dashboard.emptyMessage": "Catalogus in → verrijken / verwerken → exporteren of pushen naar winkels. Begin met Aan de slag hieronder (of koppel een feed / upload een CSV).",
|
||||
"dashboard.connectFeedAnyway": "Feed toch koppelen",
|
||||
@@ -367,29 +367,29 @@ export const nl: MessageDict = {
|
||||
"activation.focus.sync": "Volgende: synchroniseer een steekproef na het opslaan van de mapping. Gebruik Sync op een gemapte feed  vermijd ongemapte bronnen.",
|
||||
"activation.focus.dismiss": "Hint sluiten",
|
||||
"activation.dismiss": "Checklist verbergen",
|
||||
"hypercare.report.title": "Cutover-hypercare",
|
||||
"hypercare.report.title": "Hulp nodig na de verhuizing?",
|
||||
"hypercare.report.message": "Ontbrekende of verkeerde data na migratie? Meld het zodat we je workspace kunnen herstellen.",
|
||||
"hypercare.report.cta": "Ontbrekende of verkeerde data melden",
|
||||
"hypercare.report.dismiss": "Sluiten",
|
||||
"hypercare.report.adminTriage": "Hypercare-wachtrij openen",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -456,9 +456,9 @@ export const nl: MessageDict = {
|
||||
"errors.readOnly": "Het systeem staat in alleen-lezenmodus. Wijzigingen zijn tijdelijk uitgeschakeld.",
|
||||
"errors.companyAdminDenied": "Alleen bedrijfsbeheerders kunnen {action}. Vraag een beheerder om hulp.",
|
||||
"errors.companyAdminDenied.actionDefault": "dit doen",
|
||||
"docs.tryIt.memberCannotCreate": "Alleen bedrijfsadmins kunnen API-sleutels maken. Legacy-sleutels zijn niet gemigreerd  plak hieronder een sleutel of vraag een admin om een nieuwe.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "Legacy API-sleutels zijn niet gemigreerd. Maak een nieuwe via Use my API key of Instellingen → API-sleutels  het geheim wordt slechts één keer getoond.",
|
||||
"docs.tryIt.noKeysLegacyMember": "Geen API-sleutels vermeld. Legacy-sleutels niet gemigreerd  vraag een admin er een aan te maken, of plak een dk_-sleutel.",
|
||||
"docs.tryIt.memberCannotCreate": "Alleen bedrijfsadmins kunnen API-sleutels maken. sleutels zijn niet gemigreerd  plak hieronder een sleutel of vraag een admin om een nieuwe.",
|
||||
"docs.tryIt.noKeysLegacyAdmin": "API-sleutels zijn niet gemigreerd. Maak een nieuwe via Use my API key of Instellingen → API-sleutels  het geheim wordt slechts één keer getoond.",
|
||||
"docs.tryIt.noKeysLegacyMember": "Geen API-sleutels vermeld. sleutels niet gemigreerd  vraag een admin er een aan te maken, of plak een dk_-sleutel.",
|
||||
"errors.couldNotUpdateLanguage": "Taal kon niet worden bijgewerkt",
|
||||
"toast.support.replyTitle": "Supportantwoord",
|
||||
"toast.support.replyBody": "Medewerkers hebben gereageerd op uw supportticket.",
|
||||
@@ -3690,6 +3690,7 @@ export const nl: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "De zojuist gestarte taak is geannuleerd.",
|
||||
"processing.receipt.cancelFailed": "Kon verwerkingstaak niet annuleren",
|
||||
"unsubscribe.title": "Uitschrijven",
|
||||
"unsubscribe.useEmailLink": "Gebruik de afmeldlink in de e-mail die we u hebben gestuurd. Deze pagina openen zonder die link kan uw e-mailvoorkeuren niet wijzigen.",
|
||||
"unsubscribe.me": "Mij uitschrijven",
|
||||
"unsubscribe.invalidLink": "Ongeldige link",
|
||||
"unsubscribe.failedShort": "Uitschrijven mislukt",
|
||||
@@ -4727,6 +4728,10 @@ export const nl: MessageDict = {
|
||||
"seo.terms.description": "Gebruiksvoorwaarden van Descrybe: feed-import, catalogusverrijking, AI-ondersteunde content, exporten en synchronisatie met WooCommerce voor uw bedrijf.",
|
||||
"seo.features.title": "Functies  Feeds, verrijking en export | Descrybe",
|
||||
"seo.features.description": "Ontdek hoe Descrybe leveranciersfeeds importeert, velden toewijst aan uw taxonomie, productgegevens verrijkt en catalogi levert via exportfeeds, WooCommerce of API.",
|
||||
"seo.contactSales.title": "Contact sales | Descrybe",
|
||||
"seo.contactSales.description": "Vertel ons over uw catalogus en capaciteitsbehoefte: we maken een plan op maat dat u online kunt betalen.",
|
||||
"seo.unsubscribe.title": "Uitschrijven | Descrybe",
|
||||
"seo.unsubscribe.description": "Stop marketingmails van Descrybe via de afmeldlink in het bericht dat we u hebben gestuurd.",
|
||||
"pricing.page.eyebrow": "Prijzen",
|
||||
"pricing.page.title": "Eenvoudige plannen voor groeiende catalogi",
|
||||
"pricing.page.lead": "Begin gratis met feed-mapping en basisopschoning. Upgrade wanneer je AI-titels en -beschrijvingen, meer producten, exportfeeds of WooCommerce-sync nodig hebt  van Starter tot Enterprise.",
|
||||
@@ -4734,6 +4739,8 @@ export const nl: MessageDict = {
|
||||
"pricing.page.subscribedMid": "of vergelijk plannen in",
|
||||
"pricing.page.plansLink": "Plannen",
|
||||
"pricing.page.subscribedAfter": ".",
|
||||
"pricing.page.guestSubscribedBefore": "Al geabonneerd?",
|
||||
"pricing.page.guestSubscribedAfter": "om facturatie te beheren en plannen te vergelijken.",
|
||||
"legal.lastUpdated": "Laatst bijgewerkt: {date}",
|
||||
"legal.backHome": "↠Terug naar home",
|
||||
"legal.emailLabel": "E-mail:",
|
||||
@@ -5065,7 +5072,7 @@ export const nl: MessageDict = {
|
||||
"brand.uploadLogo": "Logo uploaden",
|
||||
"brand.clear": "Wissen",
|
||||
"brand.field.logoUrl": "Logo-URL",
|
||||
"brand.placeholder.logoUrl": "https://… of geüpload /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "Voorbeeld van merklogo",
|
||||
"brand.tipsTitle": "Formule- / voorbeeldtips",
|
||||
"brand.saving": "Opslaan…",
|
||||
@@ -5226,6 +5233,8 @@ export const nl: MessageDict = {
|
||||
"pricing.section.publicBefore": "Publieke plannen: Free, Starter, Growth, Business en Enterprise. Maak een Free-account aan en upgrade daarna onder",
|
||||
"pricing.section.publicOr": "of",
|
||||
"pricing.section.publicAfter": "via Stripe Checkout. Enterprise blijft sales-gestuurd.",
|
||||
"pricing.section.guestPublicBefore": "Publieke plannen: Free, Starter, Plus, Growth, Business, Scale en Enterprise. Maak een Free-account aan en",
|
||||
"pricing.section.guestPublicAfter": "om te upgraden via Stripe Checkout. Enterprise blijft sales-gestuurd.",
|
||||
"pricing.section.plansLink": "Plannen",
|
||||
"pricing.section.billingLink": "Facturering",
|
||||
"pricing.section.capabilitiesTitle": "Waarvoor elk plan is gebouwd",
|
||||
@@ -5291,7 +5300,7 @@ export const nl: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Meest populair",
|
||||
"pricing.card.custom": "Op maat",
|
||||
"pricing.card.forever": "voor altijd",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const pl: MessageDict = {
|
||||
"auth.login.failed": "Logowanie nie powiodło się",
|
||||
"auth.login.passwordNotSet": "To konto nadal wymaga hasła. Otwórz link zaproszenia lub poproś administratora o wystawienie nowego.",
|
||||
"auth.login.setPasswordFirstTitle": "Najpierw ustaw hasło:",
|
||||
"auth.login.setPasswordFirstBody": "użyj linku zaproszenia z e-maila. Jeśli link poszedł na stary adres (dryf e-mail), poproś administratora firmy o ponowne wystawienie zaproszenia do ustawienia hasła na {email}.",
|
||||
"auth.login.setPasswordFirstBody": "użyj linku zaproszenia z e-maila. Jeśli potrzebujesz nowego linku, poproś administratora firmy o ponowne wystawienie linku do ustawienia hasła na {email}.",
|
||||
"auth.login.yourEmail": "twój e-mail",
|
||||
"auth.login.platformAdminsReissue": "Administratorzy platformy mogą ponownie wystawić z",
|
||||
"auth.login.adminUsersLink": "Admin → Użytkownicy",
|
||||
@@ -144,9 +144,9 @@ export const pl: MessageDict = {
|
||||
"auth.invite.acceptFailed": "Nie można zaakceptować zaproszenia",
|
||||
"auth.invite.setPasswordFailed": "Nie można ustawić hasła",
|
||||
"auth.invite.expired": "To zaproszenie jest nieprawidłowe lub wygasło. Poproś administratora firmy o nowe zaproszenie, a następnie otwórz nowy link (lub wklej nowy token poniżej).",
|
||||
"auth.invite.setPasswordExpired": "Ten link do ustawienia hasła jest nieprawidłowy lub wygasł. Poproś administratora firmy lub platformy o ponowne wystawienie, a następnie otwórz nowy link (lub wklej nowy token poniżej).",
|
||||
"auth.invite.setPasswordExpired": "Ten link do ustawienia hasła jest nieprawidłowy lub wygasł. Poproś administratora firmy o ponowne wystawienie linku do ustawienia hasła na ten e-mail, a następnie otwórz nowy link (lub wklej nowy token poniżej).",
|
||||
"auth.invite.emailMismatchDefault": "Jesteś zalogowany na inny e-mail niż w tym zaproszeniu.",
|
||||
"auth.invite.expiredFooter": "Wygasły link? Poproś administratora o ponowne wystawienie  nie ma API samodzielnego ponownego wysyłania. Administratorzy platformy:",
|
||||
"auth.invite.expiredFooter": "Wygasły link? Poproś administratora firmy o ponowne wystawienie — nie ma API samodzielnego ponownego wysyłania.",
|
||||
"auth.invite.adminUsersLink": "Admin → Użytkownicy",
|
||||
"auth.invite.doneTitle": "JesteÅ› w zespole",
|
||||
"auth.invite.doneSetPasswordTitle": "Hasło zapisane",
|
||||
@@ -163,7 +163,7 @@ export const pl: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Zmień konto:",
|
||||
"auth.invite.switchAccountBody": "wyloguj się, a następnie dokończ ten formularz zaproszonym e-mailem{emailSuffix}.",
|
||||
"auth.invite.reissueTitle": "Ścieżka ponownego wystawienia:",
|
||||
"auth.invite.reissueBody": "jeśli zmienił się Twój prawdziwy e-mail logowania (dryf e-mail), poproś administratora firmy o unieważnienie tego zaproszenia i wysłanie nowego na e-mail używany do logowania. Administratorzy platformy mogą też ponownie wystawiać linki ustawienia hasła w Admin → Użytkownicy.",
|
||||
"auth.invite.reissueBody": "poproś administratora firmy o ponowne wystawienie linku do ustawienia hasła na ten e-mail albo o unieważnienie tego zaproszenia i wysłanie nowego na e-mail używany do logowania.",
|
||||
"locale.switcher": "Język interfejsu",
|
||||
"locale.menu": "Wybierz język interfejsu",
|
||||
"locale.label": "Język panelu",
|
||||
@@ -276,7 +276,7 @@ export const pl: MessageDict = {
|
||||
"settings.table.lastUsed": "Ostatnio użyty",
|
||||
"dashboard.demoSandbox": "Piaskownica demo",
|
||||
"dashboard.demoEmptyTitle": "Piaskownica demo jest pusta",
|
||||
"dashboard.demoEmptyHint": "Piaskownica demo jest pusta  przełącz na A1 lub podłącz feed, aby zobaczyć realne statystyki katalogu.",
|
||||
"dashboard.demoEmptyHint": "Piaskownica demo jest pusta — podłącz feed, aby zobaczyć realne statystyki katalogu.",
|
||||
"dashboard.overviewTitle": "PrzeglÄ…d",
|
||||
"dashboard.quickLinks": "Szybkie linki",
|
||||
"dashboard.whatsNew": "Co nowego",
|
||||
@@ -319,7 +319,7 @@ export const pl: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Mapuj, potem eksportuj",
|
||||
"dashboard.workflowHint": "Katalog wejściowy → wzbogacenie / przetwarzanie → eksport lub wypchnięcie do sklepów. Przejdź do następnego kroku dla {name}.",
|
||||
"dashboard.overviewHint": "Bieżące sumy dla {name}",
|
||||
"dashboard.demoEmptyMessage": "Przełącz na A1 (lub inną firmę z danymi) w nagłówku albo podłącz tu feed, aby wypełnić tę piaskownicę.",
|
||||
"dashboard.demoEmptyMessage": "Podłącz tu feed, aby wypełnić tę piaskownicę, albo przełącz na inną firmę w nagłówku.",
|
||||
"dashboard.emptyTitle": "WciÄ…gnij katalog",
|
||||
"dashboard.emptyMessage": "Katalog wejściowy → wzbogacenie / przetwarzanie → eksport lub wypchnięcie do sklepów. Zacznij od Pierwsze kroki poniżej (lub podłącz feed / prześlij CSV).",
|
||||
"dashboard.connectFeedAnyway": "Podłącz feed mimo to",
|
||||
@@ -367,29 +367,29 @@ export const pl: MessageDict = {
|
||||
"activation.focus.sync": "Dalej: zsynchronizuj próbkę po zapisaniu mapowania. Użyj Sync na zmapowanym feedzie  unikaj niezmapowanych źródeł.",
|
||||
"activation.focus.dismiss": "Zamknij podpowiedź",
|
||||
"activation.dismiss": "Ukryj listÄ™",
|
||||
"hypercare.report.title": "Hypercare cutover",
|
||||
"hypercare.report.title": "Potrzebujesz pomocy po przeniesieniu?",
|
||||
"hypercare.report.message": "Brakujące lub błędne dane po migracji? Zgłoś to, abyśmy mogli naprawić Twój workspace.",
|
||||
"hypercare.report.cta": "Zgłoś brakujące lub błędne dane",
|
||||
"hypercare.report.dismiss": "Odrzuć",
|
||||
"hypercare.report.adminTriage": "Otwórz kolejkę hypercare",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -3690,6 +3690,7 @@ export const pl: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "Właśnie uruchomione zadanie zostało anulowane.",
|
||||
"processing.receipt.cancelFailed": "Nie można anulować zadania przetwarzania",
|
||||
"unsubscribe.title": "Wypisz siÄ™",
|
||||
"unsubscribe.useEmailLink": "Uzyj linku wypisania w e-mailu, ktory wyslalismy. Otwarcie tej strony bez tego linku nie zmieni preferencji e-mail.",
|
||||
"unsubscribe.me": "Wypisz mnie",
|
||||
"unsubscribe.invalidLink": "Nieprawidłowy link",
|
||||
"unsubscribe.failedShort": "Wypisanie nie powiodło się",
|
||||
@@ -4727,6 +4728,10 @@ export const pl: MessageDict = {
|
||||
"seo.terms.description": "Warunki korzystania z Descrybe: import feedów, wzbogacanie katalogu, treści wspierane przez AI, eksporty oraz synchronizacja z WooCommerce dla Twojej firmy.",
|
||||
"seo.features.title": "Funkcje  Feedy, wzbogacanie i eksport | Descrybe",
|
||||
"seo.features.description": "Dowiedz się, jak Descrybe importuje feedy dostawców, mapuje pola na Twoją taksonomię, wzbogaca dane produktów i dostarcza katalogi przez feedy eksportowe, WooCommerce lub API.",
|
||||
"seo.contactSales.title": "Kontakt ze sprzedaza | Descrybe",
|
||||
"seo.contactSales.description": "Opowiedz nam o katalogu i potrzebach pojemnosci: przygotujemy plan niestandardowy, ktory oplacisz online.",
|
||||
"seo.unsubscribe.title": "Wypisz sie | Descrybe",
|
||||
"seo.unsubscribe.description": "Zatrzymaj e-maile marketingowe Descrybe, uzywajac linku wypisania w wiadomosci, ktora wyslalismy.",
|
||||
"pricing.page.eyebrow": "Cennik",
|
||||
"pricing.page.title": "Proste plany dla rosnących katalogów",
|
||||
"pricing.page.lead": "Zacznij za darmo od mapowania feedów i podstawowego czyszczenia. Ulepsz, gdy potrzebujesz tytułów i opisów AI, większej liczby produktów, feedów eksportu lub synchronizacji WooCommerce  od Starter do Enterprise.",
|
||||
@@ -4734,6 +4739,8 @@ export const pl: MessageDict = {
|
||||
"pricing.page.subscribedMid": "lub porównaj plany w",
|
||||
"pricing.page.plansLink": "Plany",
|
||||
"pricing.page.subscribedAfter": ".",
|
||||
"pricing.page.guestSubscribedBefore": "Masz juz subskrypcje?",
|
||||
"pricing.page.guestSubscribedAfter": "aby zarzadzac platnosciami i porownac plany.",
|
||||
"legal.lastUpdated": "Ostatnia aktualizacja: {date}",
|
||||
"legal.backHome": "↠Powrót do strony głównej",
|
||||
"legal.emailLabel": "E-mail:",
|
||||
@@ -5065,7 +5072,7 @@ export const pl: MessageDict = {
|
||||
"brand.uploadLogo": "Prześlij logo",
|
||||
"brand.clear": "Wyczyść",
|
||||
"brand.field.logoUrl": "URL logo",
|
||||
"brand.placeholder.logoUrl": "https://… lub przesłane /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "PodglÄ…d logo marki",
|
||||
"brand.tipsTitle": "Wskazówki formuły / podglądu",
|
||||
"brand.saving": "Zapisywanie…",
|
||||
@@ -5226,6 +5233,8 @@ export const pl: MessageDict = {
|
||||
"pricing.section.publicBefore": "Plany publiczne: Free, Starter, Growth, Business i Enterprise. Utwórz konto Free, a potem przejdź wyżej w",
|
||||
"pricing.section.publicOr": "lub",
|
||||
"pricing.section.publicAfter": "przez Stripe Checkout. Enterprise pozostaje obsługiwany przez sprzedaż.",
|
||||
"pricing.section.guestPublicBefore": "Plany publiczne: Free, Starter, Plus, Growth, Business, Scale i Enterprise. Utworz konto Free, a potem",
|
||||
"pricing.section.guestPublicAfter": "aby przejsc wyzej przez Stripe Checkout. Enterprise pozostaje obslugiwany przez sprzedaz.",
|
||||
"pricing.section.plansLink": "Plany",
|
||||
"pricing.section.billingLink": "Płatności",
|
||||
"pricing.section.capabilitiesTitle": "Do czego jest stworzony każdy plan",
|
||||
@@ -5291,7 +5300,7 @@ export const pl: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Najpopularniejszy",
|
||||
"pricing.card.custom": "Indywidualny",
|
||||
"pricing.card.forever": "na zawsze",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const pt: MessageDict = {
|
||||
"auth.login.failed": "Falha no inÃÂcio de sessão",
|
||||
"auth.login.passwordNotSet": "Esta conta ainda precisa de uma palavra-passe. Abra o link do convite ou peça a um administrador para emitir um novo.",
|
||||
"auth.login.setPasswordFirstTitle": "Defina primeiro a palavra-passe:",
|
||||
"auth.login.setPasswordFirstBody": "utilize o link do convite do seu e-mail. Se o link foi para um endereço antigo (desvio de e-mail), peça a um administrador da empresa para emitir um novo convite de definição de palavra-passe para {email}.",
|
||||
"auth.login.setPasswordFirstBody": "utilize o link do convite do seu e-mail. Se precisar de um novo link, peça a um administrador da empresa para reemitir um link de definição de palavra-passe para {email}.",
|
||||
"auth.login.yourEmail": "o seu e-mail",
|
||||
"auth.login.platformAdminsReissue": "Os administradores da plataforma podem reemitir a partir de",
|
||||
"auth.login.adminUsersLink": "Admin → Utilizadores",
|
||||
@@ -144,9 +144,9 @@ export const pt: MessageDict = {
|
||||
"auth.invite.acceptFailed": "Não foi possÃÂvel aceitar o convite",
|
||||
"auth.invite.setPasswordFailed": "Não foi possÃÂvel definir a palavra-passe",
|
||||
"auth.invite.expired": "Este convite é inválido ou expirou. Peça ao administrador da empresa para enviar um novo convite e abra o novo link (ou cole o novo token abaixo).",
|
||||
"auth.invite.setPasswordExpired": "Este link de definição de palavra-passe é inválido ou expirou. Peça a um administrador da empresa ou da plataforma para o reemitir e abra o novo link (ou cole o novo token abaixo).",
|
||||
"auth.invite.setPasswordExpired": "Este link de definição de palavra-passe é inválido ou expirou. Peça a um administrador da empresa para reemitir um link de definição de palavra-passe para este e-mail e abra o novo link (ou cole o novo token abaixo).",
|
||||
"auth.invite.emailMismatchDefault": "Tem sessão iniciada com um e-mail diferente deste convite.",
|
||||
"auth.invite.expiredFooter": "Link expirado? Peça a um administrador para o reemitir  não há API de reenvio self-service. Administradores da plataforma:",
|
||||
"auth.invite.expiredFooter": "Link expirado? Peça a um administrador da empresa para o reemitir — não há API de reenvio self-service.",
|
||||
"auth.invite.adminUsersLink": "Admin → Utilizadores",
|
||||
"auth.invite.doneTitle": "Já faz parte da equipa",
|
||||
"auth.invite.doneSetPasswordTitle": "Palavra-passe guardada",
|
||||
@@ -163,7 +163,7 @@ export const pt: MessageDict = {
|
||||
"auth.invite.switchAccountTitle": "Mudar de conta:",
|
||||
"auth.invite.switchAccountBody": "termine a sessão e conclua este formulário com o e-mail convidado{emailSuffix}.",
|
||||
"auth.invite.reissueTitle": "Caminho de reemissão:",
|
||||
"auth.invite.reissueBody": "se o seu e-mail real de inÃÂcio de sessão mudou (desvio de e-mail), peça a um administrador da empresa para revogar este convite e enviar um novo para o e-mail que utiliza para iniciar sessão. Os administradores da plataforma também podem reemitir links de definição de palavra-passe em Admin → Utilizadores.",
|
||||
"auth.invite.reissueBody": "peça a um administrador da empresa para reemitir um link de definição de palavra-passe para este e-mail, ou para revogar este convite e enviar um novo para o e-mail que utiliza para iniciar sessão.",
|
||||
"locale.switcher": "Idioma da interface",
|
||||
"locale.menu": "Escolher idioma da interface",
|
||||
"locale.label": "Idioma do painel",
|
||||
@@ -276,7 +276,7 @@ export const pt: MessageDict = {
|
||||
"settings.table.lastUsed": "Última utilização",
|
||||
"dashboard.demoSandbox": "Sandbox de demonstração",
|
||||
"dashboard.demoEmptyTitle": "A sandbox de demonstração está vazia",
|
||||
"dashboard.demoEmptyHint": "A sandbox de demonstração está vazia  mude para A1 ou ligue um feed para ver estatÃÂsticas reais do catálogo.",
|
||||
"dashboard.demoEmptyHint": "A sandbox de demonstração está vazia — ligue um feed para ver estatísticas reais do catálogo.",
|
||||
"dashboard.overviewTitle": "Visão geral",
|
||||
"dashboard.quickLinks": "Ligações rápidas",
|
||||
"dashboard.whatsNew": "Novidades",
|
||||
@@ -319,7 +319,7 @@ export const pt: MessageDict = {
|
||||
"dashboard.workflow.exportMap": "Mapear e exportar",
|
||||
"dashboard.workflowHint": "Catálogo a entrar → enriquecer / processar → exportar ou enviar para lojas. Salte para o passo seguinte para {name}.",
|
||||
"dashboard.overviewHint": "Totais em direto para {name}",
|
||||
"dashboard.demoEmptyMessage": "Mude para A1 (ou outra empresa com dados) no cabeçalho, ou ligue um feed aqui para preencher esta sandbox.",
|
||||
"dashboard.demoEmptyMessage": "Ligue um feed aqui para preencher esta sandbox, ou mude para outra empresa no cabeçalho.",
|
||||
"dashboard.emptyTitle": "Importe um catálogo",
|
||||
"dashboard.emptyMessage": "Catálogo a entrar → enriquecer / processar → exportar ou enviar para lojas. Comece com Primeiros passos abaixo (ou ligue um feed / carregue um CSV).",
|
||||
"dashboard.connectFeedAnyway": "Ligar feed mesmo assim",
|
||||
@@ -367,29 +367,29 @@ export const pt: MessageDict = {
|
||||
"activation.focus.sync": "Seguinte: sincronize uma amostra depois de guardar o mapeamento. Use Sync num feed mapeado  evite origens sem mapa.",
|
||||
"activation.focus.dismiss": "Fechar dica",
|
||||
"activation.dismiss": "Dispensar lista",
|
||||
"hypercare.report.title": "Hypercare de cutover",
|
||||
"hypercare.report.title": "Precisa de ajuda após a mudança?",
|
||||
"hypercare.report.message": "Dados em falta ou incorretos após a migração? Reporte para podermos corrigir o seu espaço de trabalho.",
|
||||
"hypercare.report.cta": "Reportar dados em falta ou incorretos",
|
||||
"hypercare.report.dismiss": "Dispensar",
|
||||
"hypercare.report.adminTriage": "Abrir fila de hypercare",
|
||||
|
||||
"etl.gaps.title": "What did not migrate",
|
||||
"etl.gaps.message": "These areas were intentionally left empty or partial after the Descrybe platform cutover. Nothing is “broken† recreate or reconnect as needed.",
|
||||
"etl.gaps.title": "What still needs setup",
|
||||
"etl.gaps.message": "Some items weren't copied when we moved your workspace. Nothing is broken — recreate or reconnect as needed.",
|
||||
"etl.gaps.dismiss": "Dismiss",
|
||||
"etl.gaps.apiKeys.title": "API keys",
|
||||
"etl.gaps.apiKeys.body": "Legacy API key secrets were not migrated. Create a new key to restore API access  the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.body": "Previous API keys weren't copied. Create a new key to restore API access — the secret is shown only once.",
|
||||
"etl.gaps.apiKeys.cta": "Open API keys",
|
||||
"etl.gaps.blobs.title": "File contents (blobs)",
|
||||
"etl.gaps.blobs.body": "Upload records may exist as metadata only. File bytes were not copied  re-upload CSVs or resync object storage if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} file records are metadata-only (bytes were not migrated).",
|
||||
"etl.gaps.blobs.title": "Uploaded files",
|
||||
"etl.gaps.blobs.body": "File names may appear even when the file itself wasn't copied. Re-upload CSVs if you need the originals.",
|
||||
"etl.gaps.blobs.countHint": "{count} files are listed without their contents (they weren't copied).",
|
||||
"etl.gaps.blobs.cta": "Open Files",
|
||||
"etl.gaps.jobs.title": "Processing history",
|
||||
"etl.gaps.jobs.body": "Legacy job and task history was not backfilled for cutover. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Optional jobs domain was not run  empty history is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were tagged migrated from an optional backfill.",
|
||||
"etl.gaps.jobs.body": "Earlier job history wasn't imported. New jobs you start here will appear normally.",
|
||||
"etl.gaps.jobs.emptyHint": "Processing history wasn't imported — an empty list is expected.",
|
||||
"etl.gaps.jobs.migratedHint": "{count} jobs were imported from the previous workspace.",
|
||||
"etl.gaps.jobs.cta": "Open Processing",
|
||||
"etl.gaps.woo.title": "Store credentials",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify secrets may need to be re-entered after cutover  that is a reconnect step, not a broken sync.",
|
||||
"etl.gaps.woo.body": "WooCommerce and Shopify passwords may need to be re-entered after the move — reconnect your store; sync is not broken.",
|
||||
"etl.gaps.woo.cta": "Open Stores",
|
||||
"etl.gaps.settings.title": "Company settings",
|
||||
"etl.gaps.settings.body": "Only language and merge-products settings were imported. Re-check other company preferences in Settings.",
|
||||
@@ -3690,6 +3690,7 @@ export const pt: MessageDict = {
|
||||
"processing.receipt.cancelledDesc": "O trabalho recém-iniciado foi cancelado.",
|
||||
"processing.receipt.cancelFailed": "Não foi possÃÂvel cancelar o trabalho de processamento",
|
||||
"unsubscribe.title": "Cancelar subscrição",
|
||||
"unsubscribe.useEmailLink": "Use a ligacao de cancelamento no email que lhe enviamos. Abrir esta pagina sem essa ligacao nao pode alterar as suas preferencias de email.",
|
||||
"unsubscribe.me": "Cancelar a minha subscrição",
|
||||
"unsubscribe.invalidLink": "Ligação inválida",
|
||||
"unsubscribe.failedShort": "Falha ao cancelar a subscrição",
|
||||
@@ -4727,6 +4728,10 @@ export const pt: MessageDict = {
|
||||
"seo.terms.description": "Termos de utilização da Descrybe: importação de feeds, enriquecimento de catálogo, conteúdo assistido por IA, exportações e sincronização com WooCommerce para o seu negócio.",
|
||||
"seo.features.title": "Funcionalidades  Feeds, enriquecimento e exportação | Descrybe",
|
||||
"seo.features.description": "Descubra como a Descrybe importa feeds de fornecedores, mapeia campos para a sua taxonomia, enriquece dados de produto e envia catálogos através de feeds de exportação, WooCommerce ou API.",
|
||||
"seo.contactSales.title": "Contactar vendas | Descrybe",
|
||||
"seo.contactSales.description": "Fale-nos do seu catalogo e necessidades de capacidade: prepararemos um plano personalizado que pode pagar online.",
|
||||
"seo.unsubscribe.title": "Cancelar subscricao | Descrybe",
|
||||
"seo.unsubscribe.description": "Pare os emails de marketing da Descrybe usando a ligacao de cancelamento na mensagem que lhe enviamos.",
|
||||
"pricing.page.eyebrow": "Preços",
|
||||
"pricing.page.title": "Planos simples para catálogos em crescimento",
|
||||
"pricing.page.lead": "Comece grátis com mapeamento de feeds e limpeza básica. Faça upgrade quando precisar de tÃÂtulos e descrições com IA, mais produtos, feeds de exportação ou sync WooCommerce  de Starter a Enterprise.",
|
||||
@@ -4734,6 +4739,8 @@ export const pt: MessageDict = {
|
||||
"pricing.page.subscribedMid": "ou comparar planos em",
|
||||
"pricing.page.plansLink": "Planos",
|
||||
"pricing.page.subscribedAfter": ".",
|
||||
"pricing.page.guestSubscribedBefore": "Ja e subscritor?",
|
||||
"pricing.page.guestSubscribedAfter": "para gerir a faturacao e comparar planos.",
|
||||
"legal.lastUpdated": "Última atualização: {date}",
|
||||
"legal.backHome": "↠Voltar ao inÃÂcio",
|
||||
"legal.emailLabel": "E-mail:",
|
||||
@@ -5065,7 +5072,7 @@ export const pt: MessageDict = {
|
||||
"brand.uploadLogo": "Carregar logótipo",
|
||||
"brand.clear": "Limpar",
|
||||
"brand.field.logoUrl": "URL do logótipo",
|
||||
"brand.placeholder.logoUrl": "https://… ou carregado /api/brand/logo/files/…",
|
||||
"brand.placeholder.logoUrl": "https://…",
|
||||
"brand.logoAlt": "Pré-visualização do logótipo da marca",
|
||||
"brand.tipsTitle": "Dicas de fórmula / pré-visualização",
|
||||
"brand.saving": "A guardar…",
|
||||
@@ -5226,6 +5233,8 @@ export const pt: MessageDict = {
|
||||
"pricing.section.publicBefore": "Planos públicos: Free, Starter, Growth, Business e Enterprise. Crie uma conta Free e depois faça upgrade em",
|
||||
"pricing.section.publicOr": "ou",
|
||||
"pricing.section.publicAfter": "via Stripe Checkout. O Enterprise continua a ser gerido pelas vendas.",
|
||||
"pricing.section.guestPublicBefore": "Planos publicos: Free, Starter, Plus, Growth, Business, Scale e Enterprise. Crie uma conta Free e depois",
|
||||
"pricing.section.guestPublicAfter": "para fazer upgrade via Stripe Checkout. O Enterprise continua a ser gerido pelas vendas.",
|
||||
"pricing.section.plansLink": "Planos",
|
||||
"pricing.section.billingLink": "Faturação",
|
||||
"pricing.section.capabilitiesTitle": "Para que está pensado cada plano",
|
||||
@@ -5291,7 +5300,7 @@ export const pt: MessageDict = {
|
||||
"pricing.calc.enterpriseTitle": "Sounds like Enterprise",
|
||||
"pricing.calc.enterpriseBody": "Your feeds or catalog size exceed self-serve caps. Talk to sales for unlimited capacity and a managed AI grant or BYOK.",
|
||||
"pricing.calc.ctaPlan": "Choose {name}",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. A1 and other client deals stay admin-only.",
|
||||
"pricing.calc.disclaimer": "Estimates use list prices and ~2 credits per AI product enhance. Checkout prices come from Stripe. Custom client deals stay admin-only.",
|
||||
"pricing.card.mostPopular": "Mais popular",
|
||||
"pricing.card.custom": "Personalizado",
|
||||
"pricing.card.forever": "para sempre",
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Merchant-facing copy: no A1 / seeded-company, cutover jargon, ETL/blobs/domain,
|
||||
* or brand-logo API paths in customer-visible strings.
|
||||
*/
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
|
||||
import { UI_LOCALES } from "./i18n/locales.ts";
|
||||
import { en } from "./i18n/messages/en.ts";
|
||||
import { loadAllMessages, messagesFor } from "./i18n/messages/catalog.ts";
|
||||
import {
|
||||
DEFAULT_ENHANCE_PREAMBLE,
|
||||
DEFAULT_SECTION_BODIES
|
||||
} from "./categories/prompt-sections.ts";
|
||||
|
||||
const CUSTOMER_DEMO_EMPTY_KEYS = ["dashboard.demoEmptyHint", "dashboard.demoEmptyMessage"] as const;
|
||||
const CUSTOMER_ETL_KEYS = [
|
||||
"etl.gaps.title",
|
||||
"etl.gaps.message",
|
||||
"etl.gaps.blobs.title",
|
||||
"etl.gaps.blobs.body",
|
||||
"etl.gaps.blobs.countHint",
|
||||
"etl.gaps.jobs.body",
|
||||
"etl.gaps.jobs.emptyHint",
|
||||
"etl.gaps.jobs.migratedHint",
|
||||
"etl.gaps.woo.body"
|
||||
] as const;
|
||||
|
||||
describe("customer-visible copy leaks", () => {
|
||||
it("English demo empty, hypercare, ETL, and logo placeholder stay merchant-facing", () => {
|
||||
for (const key of CUSTOMER_DEMO_EMPTY_KEYS) {
|
||||
assert.doesNotMatch(en[key], /\bA1\b/i, key);
|
||||
assert.doesNotMatch(en[key], /seeded company/i, key);
|
||||
}
|
||||
assert.doesNotMatch(en["hypercare.report.title"], /cutover|hypercare/i);
|
||||
assert.doesNotMatch(en["hypercare.report.message"], /cutover|hypercare/i);
|
||||
for (const key of CUSTOMER_ETL_KEYS) {
|
||||
assert.doesNotMatch(en[key], /\bETL\b/, key);
|
||||
assert.doesNotMatch(en[key], /\bblobs?\b/i, key);
|
||||
assert.doesNotMatch(en[key], /\bdomain\b/i, key);
|
||||
assert.doesNotMatch(en[key], /cutover/i, key);
|
||||
}
|
||||
assert.doesNotMatch(en["brand.placeholder.logoUrl"], /\/api\/brand\/logo\/files/i);
|
||||
});
|
||||
|
||||
it("every UI locale keeps demo empty, hypercare title, ETL, and logo copy merchant-facing", async () => {
|
||||
await loadAllMessages();
|
||||
for (const { code } of UI_LOCALES) {
|
||||
const pack = code === "en" ? en : messagesFor(code);
|
||||
for (const key of CUSTOMER_DEMO_EMPTY_KEYS) {
|
||||
const text = String(pack[key] ?? "");
|
||||
assert.doesNotMatch(text, /\bA1\b/i, `${code}:${key}`);
|
||||
assert.doesNotMatch(text, /seeded company/i, `${code}:${key}`);
|
||||
}
|
||||
assert.doesNotMatch(
|
||||
String(pack["hypercare.report.title"] ?? ""),
|
||||
/cutover|hypercare/i,
|
||||
`${code}:hypercare.report.title`
|
||||
);
|
||||
for (const key of CUSTOMER_ETL_KEYS) {
|
||||
const text = String(pack[key] ?? "");
|
||||
assert.doesNotMatch(text, /\bETL\b/, `${code}:${key}`);
|
||||
assert.doesNotMatch(text, /\bblobs?\b/i, `${code}:${key}`);
|
||||
assert.doesNotMatch(text, /\bdomain\b/i, `${code}:${key}`);
|
||||
}
|
||||
assert.doesNotMatch(
|
||||
String(pack["brand.placeholder.logoUrl"] ?? ""),
|
||||
/\/api\/brand\/logo\/files/i,
|
||||
`${code}:brand.placeholder.logoUrl`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("category prompt defaults hide JSON schema jargon from customer text", () => {
|
||||
const blob = [DEFAULT_ENHANCE_PREAMBLE, ...Object.values(DEFAULT_SECTION_BODIES)].join("\n");
|
||||
assert.doesNotMatch(blob, /system schema/i);
|
||||
assert.doesNotMatch(blob, /your reply is parsed as json/i);
|
||||
assert.doesNotMatch(blob, /build json/i);
|
||||
});
|
||||
});
|
||||
@@ -3,9 +3,15 @@ import { describe, it } from "node:test";
|
||||
import { isHttpError } from "@sveltejs/kit";
|
||||
import type { RequestEvent } from "@sveltejs/kit";
|
||||
import {
|
||||
adminLoginRedirect,
|
||||
assertSameOrigin,
|
||||
fetchMeStaff,
|
||||
isAdminBootstrapPath,
|
||||
isAdminSupportPath,
|
||||
isFullPlatformAdmin,
|
||||
requirePlatformAdminServer
|
||||
isSupportDesk,
|
||||
requirePlatformAdminServer,
|
||||
requireSupportDeskServer
|
||||
} from "./require-platform-admin.ts";
|
||||
|
||||
function makeEvent(opts: {
|
||||
@@ -122,6 +128,69 @@ describe("requirePlatformAdminServer", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchMeStaff", () => {
|
||||
it("returns 401 without throwing when /me is unauthorized", async () => {
|
||||
const event = makeEvent({
|
||||
fetchImpl: async () => new Response("{}", { status: 401 })
|
||||
});
|
||||
assert.deepEqual(await fetchMeStaff(event), { ok: false, status: 401 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("requireSupportDeskServer", () => {
|
||||
it("allows support_desk without full_admin", async () => {
|
||||
const me = { staff_access: { full_admin: false, support_desk: true } };
|
||||
const event = makeEvent({
|
||||
fetchImpl: async () =>
|
||||
new Response(JSON.stringify(me), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" }
|
||||
})
|
||||
});
|
||||
assert.deepEqual(await requireSupportDeskServer(event), me);
|
||||
});
|
||||
|
||||
it("403 for tenant with no staff_access", async () => {
|
||||
const event = makeEvent({
|
||||
fetchImpl: async () =>
|
||||
new Response(JSON.stringify({ user: { is_platform_admin: false } }), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" }
|
||||
})
|
||||
});
|
||||
await expectHttpAsync(403, () => requireSupportDeskServer(event));
|
||||
});
|
||||
});
|
||||
|
||||
describe("admin path split and login next=", () => {
|
||||
it("classifies support vs bootstrap vs other admin", () => {
|
||||
assert.equal(isAdminSupportPath("/admin/support"), true);
|
||||
assert.equal(isAdminSupportPath("/admin/support/tickets/1"), true);
|
||||
assert.equal(isAdminSupportPath("/admin"), false);
|
||||
assert.equal(isAdminSupportPath("/admin/logs"), false);
|
||||
assert.equal(isAdminBootstrapPath("/admin/bootstrap"), true);
|
||||
assert.equal(isAdminBootstrapPath("/admin/logs"), false);
|
||||
});
|
||||
|
||||
it("builds login redirect with next=", () => {
|
||||
assert.equal(
|
||||
adminLoginRedirect("/admin/logs", "?x=1"),
|
||||
"/login?next=%2Fadmin%2Flogs%3Fx%3D1"
|
||||
);
|
||||
});
|
||||
|
||||
it("isSupportDesk follows staff_access.support_desk", () => {
|
||||
assert.equal(isSupportDesk({ staff_access: { support_desk: true } }), true);
|
||||
assert.equal(
|
||||
isSupportDesk({
|
||||
staff_access: { full_admin: false, support_desk: false },
|
||||
user: { is_platform_admin: true }
|
||||
}),
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("assertSameOrigin", () => {
|
||||
it("allows matching Origin", () => {
|
||||
assertSameOrigin(
|
||||
|
||||
@@ -7,39 +7,90 @@ import { error } from "@sveltejs/kit";
|
||||
import type { RequestEvent } from "@sveltejs/kit";
|
||||
import {
|
||||
isFullPlatformAdmin,
|
||||
isSupportDesk,
|
||||
type StaffAccessMe
|
||||
} from "../staff-access.ts";
|
||||
|
||||
export { isFullPlatformAdmin } from "../staff-access.ts";
|
||||
export { isFullPlatformAdmin, isSupportDesk } from "../staff-access.ts";
|
||||
|
||||
type MeStaff = StaffAccessMe;
|
||||
|
||||
export type FetchMeStaffResult =
|
||||
| { ok: true; me: MeStaff }
|
||||
| { ok: false; status: 401 | 403 | 502 };
|
||||
|
||||
/** Absolute /api/auth/me when PUBLIC_API_URL is set (Compose/adapter-node); else Vite same-origin proxy. */
|
||||
function authMeUrl(): string {
|
||||
const base = (process.env.PUBLIC_API_URL ?? "").replace(/\/$/, "");
|
||||
return base ? `${base}/api/auth/me` : "/api/auth/me";
|
||||
}
|
||||
|
||||
/** `/admin/support` desk pages — full admin or support_staff. */
|
||||
export function isAdminSupportPath(pathname: string): boolean {
|
||||
return pathname === "/admin/support" || pathname.startsWith("/admin/support/");
|
||||
}
|
||||
|
||||
/** First-run bootstrap UI — full platform admin only. */
|
||||
export function isAdminBootstrapPath(pathname: string): boolean {
|
||||
return pathname === "/admin/bootstrap" || pathname.startsWith("/admin/bootstrap/");
|
||||
}
|
||||
|
||||
/** Open-redirect-safe login URL with next= pointing at the current admin path. */
|
||||
export function adminLoginRedirect(pathname: string, search = ""): string {
|
||||
const next = `${pathname}${search}`;
|
||||
return `/login?next=${encodeURIComponent(next)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side platform-admin gate for SvelteKit endpoints.
|
||||
* Uses event.fetch so session cookies reach the Go /api/auth/me (Vite proxy or PUBLIC_API_URL).
|
||||
* Fetch /api/auth/me without throwing. Layout uses this to redirect 401 → login.
|
||||
* API +server.ts handlers still use requirePlatformAdminServer (error 401/403).
|
||||
*/
|
||||
export async function requirePlatformAdminServer(event: RequestEvent): Promise<MeStaff> {
|
||||
export async function fetchMeStaff(event: RequestEvent): Promise<FetchMeStaffResult> {
|
||||
const headers: Record<string, string> = { Accept: "application/json" };
|
||||
const cookie = event.request.headers.get("cookie");
|
||||
if (cookie) headers.cookie = cookie;
|
||||
const res = await event.fetch(authMeUrl(), { headers });
|
||||
if (res.status === 401) {
|
||||
error(401, "Authentication required.");
|
||||
return { ok: false, status: 401 };
|
||||
}
|
||||
if (!res.ok) {
|
||||
error(res.status === 403 ? 403 : 502, "Failed to verify admin access.");
|
||||
return { ok: false, status: res.status === 403 ? 403 : 502 };
|
||||
}
|
||||
const me = (await res.json()) as MeStaff;
|
||||
if (!isFullPlatformAdmin(me)) {
|
||||
return { ok: true, me };
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side platform-admin gate for SvelteKit endpoints.
|
||||
* Uses event.fetch so session cookies reach the Go /api/auth/me (Vite proxy or PUBLIC_API_URL).
|
||||
*/
|
||||
export async function requirePlatformAdminServer(event: RequestEvent): Promise<MeStaff> {
|
||||
const result = await fetchMeStaff(event);
|
||||
if (!result.ok) {
|
||||
if (result.status === 401) {
|
||||
error(401, "Authentication required.");
|
||||
}
|
||||
error(result.status === 403 ? 403 : 502, "Failed to verify admin access.");
|
||||
}
|
||||
if (!isFullPlatformAdmin(result.me)) {
|
||||
error(403, "Platform admin required.");
|
||||
}
|
||||
return me;
|
||||
return result.me;
|
||||
}
|
||||
|
||||
/** Server-side support-desk gate (full admin or support_staff). */
|
||||
export async function requireSupportDeskServer(event: RequestEvent): Promise<MeStaff> {
|
||||
const result = await fetchMeStaff(event);
|
||||
if (!result.ok) {
|
||||
if (result.status === 401) {
|
||||
error(401, "Authentication required.");
|
||||
}
|
||||
error(result.status === 403 ? 403 : 502, "Failed to verify support access.");
|
||||
}
|
||||
if (!isSupportDesk(result.me)) {
|
||||
error(403, "Support desk access required.");
|
||||
}
|
||||
return result.me;
|
||||
}
|
||||
|
||||
function originOf(url: string): string | null {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { isFullPlatformAdmin, shouldUnlockAllFeatures } from "./staff-access.ts";
|
||||
import { isFullPlatformAdmin, isSupportDesk, shouldUnlockAllFeatures } from "./staff-access.ts";
|
||||
|
||||
describe("isFullPlatformAdmin", () => {
|
||||
it("allows staff_access.full_admin", () => {
|
||||
@@ -39,6 +39,27 @@ describe("isFullPlatformAdmin", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("isSupportDesk", () => {
|
||||
it("allows support_desk", () => {
|
||||
assert.equal(isSupportDesk({ staff_access: { support_desk: true } }), true);
|
||||
});
|
||||
|
||||
it("denies tenant even when legacy is_platform_admin is set alongside staff_access", () => {
|
||||
assert.equal(
|
||||
isSupportDesk({
|
||||
staff_access: { full_admin: false, support_desk: false },
|
||||
user: { is_platform_admin: true }
|
||||
}),
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it("legacy: allows is_platform_admin when staff_access is absent", () => {
|
||||
assert.equal(isSupportDesk({ user: { is_platform_admin: true } }), true);
|
||||
assert.equal(isSupportDesk({ user: { is_platform_admin: false } }), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("shouldUnlockAllFeatures", () => {
|
||||
it("unlocks Demo / full admin", () => {
|
||||
assert.equal(
|
||||
|
||||
@@ -24,6 +24,15 @@ export function isFullPlatformAdmin(me: StaffAccessMe | null | undefined): boole
|
||||
return Boolean(me.user?.is_platform_admin);
|
||||
}
|
||||
|
||||
/** Full admin or support_staff (legacy: is_platform_admin when staff_access is absent). */
|
||||
export function isSupportDesk(me: StaffAccessMe | null | undefined): boolean {
|
||||
if (me == null) return false;
|
||||
if (me.staff_access) {
|
||||
return Boolean(me.staff_access.support_desk);
|
||||
}
|
||||
return Boolean(me.user?.is_platform_admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Nav / shell preview unlock for Demo + platform staff.
|
||||
* Must stay false for normal A1 (and other tenant) users — even if a stale
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { page } from "$app/state";
|
||||
import { api, ApiError } from "$lib/api";
|
||||
import { consumeAuthLinkSecrets } from "$lib/auth-link-token";
|
||||
import { trackEvent } from "$lib/analytics";
|
||||
import { writeActivationProgress } from "$lib/activation";
|
||||
import { i18n } from "$lib/i18n";
|
||||
@@ -27,12 +27,11 @@
|
||||
mismatch: boolean;
|
||||
};
|
||||
|
||||
const initialToken = page.url.searchParams.get("token") ?? "";
|
||||
const initialMode = page.url.searchParams.get("mode");
|
||||
|
||||
let token = $state(initialToken);
|
||||
/** True when the token arrived via ?token=; never show it in a visible input. */
|
||||
let tokenFromLink = $state(initialToken.length > 0);
|
||||
let token = $state("");
|
||||
/** True when the token arrived via hash or query link; never show it in a visible input. */
|
||||
let tokenFromLink = $state(false);
|
||||
/** Fragment tokens are client-only; wait for mount before treating the token as missing. */
|
||||
let hydrated = $state(false);
|
||||
let name = $state("");
|
||||
let password = $state("");
|
||||
let error = $state("");
|
||||
@@ -44,9 +43,7 @@
|
||||
let sessionEmail = $state("");
|
||||
let signingOut = $state(false);
|
||||
/** Admin HMAC emails use mode=set-password; migrator invites use the invite token path. */
|
||||
let mode = $state<"invite" | "set-password">(
|
||||
initialMode === "set-password" ? "set-password" : "invite"
|
||||
);
|
||||
let mode = $state<"invite" | "set-password">("invite");
|
||||
const errorId = "accept-invite-form-error";
|
||||
const passwordHintId = "accept-invite-password-hint";
|
||||
|
||||
@@ -103,12 +100,21 @@
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (!tokenFromLink) return;
|
||||
// Drop the secret from the address bar / history (referrer + shoulder-surf).
|
||||
const cleaned = new URL(window.location.href);
|
||||
cleaned.searchParams.delete("token");
|
||||
history.replaceState(history.state, "", cleaned.pathname + cleaned.search + cleaned.hash);
|
||||
void loadPreview(token);
|
||||
const consumed = consumeAuthLinkSecrets(window.location.href);
|
||||
if (consumed.token) {
|
||||
token = consumed.token;
|
||||
tokenFromLink = true;
|
||||
}
|
||||
if (consumed.mode === "set-password") {
|
||||
mode = "set-password";
|
||||
}
|
||||
hydrated = true;
|
||||
if (consumed.stripped) {
|
||||
history.replaceState(history.state, "", consumed.cleanedPathSearch);
|
||||
}
|
||||
if (tokenFromLink) {
|
||||
void loadPreview(token);
|
||||
}
|
||||
});
|
||||
|
||||
async function onSubmit(event: Event) {
|
||||
@@ -179,7 +185,15 @@
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
{#if done}
|
||||
{#if !hydrated}
|
||||
<CardHeader>
|
||||
<CardTitle level={1}>{i18n.t("auth.invite.title")}</CardTitle>
|
||||
<CardDescription>{i18n.t("auth.invite.description")}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p class="text-sm text-text-muted" aria-live="polite">{i18n.t("auth.invite.checking")}</p>
|
||||
</CardContent>
|
||||
{:else if done}
|
||||
<CardHeader>
|
||||
<CardTitle level={1}>
|
||||
{mode === "set-password"
|
||||
@@ -377,9 +391,6 @@
|
||||
</p>
|
||||
<p class="mt-1.5 text-center text-xs text-text-muted">
|
||||
{i18n.t("auth.invite.expiredFooter")}
|
||||
<a href="/admin/users" class="font-medium text-link hover:underline"
|
||||
>{i18n.t("auth.invite.adminUsersLink")}</a
|
||||
>.
|
||||
</p>
|
||||
</CardContent>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { error, redirect } from "@sveltejs/kit";
|
||||
import type { LayoutServerLoad } from "./$types";
|
||||
import {
|
||||
adminLoginRedirect,
|
||||
fetchMeStaff,
|
||||
isAdminSupportPath,
|
||||
isFullPlatformAdmin,
|
||||
isSupportDesk
|
||||
} from "$lib/server/require-platform-admin";
|
||||
|
||||
/**
|
||||
* SSR gate for /admin/* pages (not +server.ts endpoints).
|
||||
* Unauthenticated → login?next=. Non-staff → /dashboard (no admin chrome).
|
||||
* /admin/support* → support desk. All other admin pages (including logs + bootstrap) → full platform admin.
|
||||
*/
|
||||
export const load: LayoutServerLoad = async (event) => {
|
||||
const result = await fetchMeStaff(event);
|
||||
if (!result.ok) {
|
||||
if (result.status === 401) {
|
||||
redirect(303, adminLoginRedirect(event.url.pathname, event.url.search));
|
||||
}
|
||||
error(result.status, "Forbidden");
|
||||
}
|
||||
|
||||
const me = result.me;
|
||||
const path = event.url.pathname;
|
||||
const supportPath = isAdminSupportPath(path);
|
||||
const fullAdmin = isFullPlatformAdmin(me);
|
||||
const supportDesk = isSupportDesk(me);
|
||||
|
||||
if (supportPath) {
|
||||
if (!supportDesk) {
|
||||
redirect(303, "/dashboard");
|
||||
}
|
||||
return { staff: { full_admin: fullAdmin, support_desk: true } };
|
||||
}
|
||||
|
||||
if (!fullAdmin) {
|
||||
if (supportDesk) {
|
||||
redirect(303, "/admin/support");
|
||||
}
|
||||
redirect(303, "/dashboard");
|
||||
}
|
||||
|
||||
return { staff: { full_admin: true, support_desk: supportDesk } };
|
||||
};
|
||||
@@ -264,18 +264,18 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<PageShell
|
||||
eyebrow={i18n.t("admin.overview.eyebrow")}
|
||||
title={i18n.t("admin.overview.title")}
|
||||
description={i18n.t("admin.overview.description")}
|
||||
>
|
||||
{#if loading}
|
||||
<Spinner />
|
||||
{:else if accessDenied}
|
||||
<ForbiddenEmptyState kind="platform" />
|
||||
{:else if error}
|
||||
<Alert message={error} />
|
||||
{:else}
|
||||
{#if loading}
|
||||
<Spinner />
|
||||
{:else if accessDenied}
|
||||
<ForbiddenEmptyState kind="platform" />
|
||||
{:else if error}
|
||||
<Alert message={error} />
|
||||
{:else}
|
||||
<PageShell
|
||||
eyebrow={i18n.t("admin.overview.eyebrow")}
|
||||
title={i18n.t("admin.overview.title")}
|
||||
description={i18n.t("admin.overview.description")}
|
||||
>
|
||||
{#if summary}
|
||||
<section class="space-y-3" aria-labelledby="admin-kpi-heading">
|
||||
<div class="flex flex-wrap items-end justify-between gap-2">
|
||||
@@ -517,5 +517,5 @@
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
{/if}
|
||||
</PageShell>
|
||||
</PageShell>
|
||||
{/if}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { api, failureMessage, isForbidden, isUnauthorized } from "$lib/api";
|
||||
import { requirePlatformAdmin } from "$lib/admin-gate";
|
||||
import { isFullPlatformAdmin } from "$lib/staff-access";
|
||||
import type { MeResponse } from "$lib/types";
|
||||
import PageShell from "$lib/components/PageShell.svelte";
|
||||
import Spinner from "$lib/components/Spinner.svelte";
|
||||
@@ -23,33 +24,33 @@
|
||||
let me = $state<MeResponse | null>(null);
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
me = await api<MeResponse>("/api/auth/me");
|
||||
} catch (err) {
|
||||
if (isUnauthorized(err)) {
|
||||
const gate = await requirePlatformAdmin();
|
||||
if (!gate.ok) {
|
||||
if (gate.reason === "auth") {
|
||||
await goto("/login");
|
||||
return;
|
||||
}
|
||||
if (isForbidden(err)) {
|
||||
accessDenied = true;
|
||||
return;
|
||||
accessDenied = true;
|
||||
if (gate.reason !== "forbidden") {
|
||||
error = gate.message;
|
||||
}
|
||||
error = failureMessage(err, i18n.t("admin.bootstrap.loadFailed"));
|
||||
} finally {
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
me = gate.me;
|
||||
loading = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<PageShell
|
||||
title={i18n.t("admin.bootstrap.title")}
|
||||
description={i18n.t("admin.bootstrap.description")}
|
||||
>
|
||||
{#if loading}
|
||||
<Spinner />
|
||||
{:else if accessDenied}
|
||||
<ForbiddenEmptyState kind="platform" />
|
||||
{:else}
|
||||
{#if loading}
|
||||
<Spinner />
|
||||
{:else if accessDenied}
|
||||
<ForbiddenEmptyState kind="platform" />
|
||||
{:else}
|
||||
<PageShell
|
||||
title={i18n.t("admin.bootstrap.title")}
|
||||
description={i18n.t("admin.bootstrap.description")}
|
||||
>
|
||||
<Card class="mx-auto max-w-md">
|
||||
<CardHeader>
|
||||
<CardTitle>{i18n.t("admin.bootstrap.statusTitle")}</CardTitle>
|
||||
@@ -58,11 +59,11 @@
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{#if me?.user?.is_platform_admin}
|
||||
{#if isFullPlatformAdmin(me)}
|
||||
<div class="rounded-md border border-green-500/30 bg-green-500/10 p-4 text-sm">
|
||||
<p class="font-medium">{i18n.t("admin.bootstrap.alreadyAdmin")}</p>
|
||||
<p class="mt-2 text-muted-foreground">
|
||||
{i18n.t("admin.bootstrap.signedInAs", { email: me.user.email })}
|
||||
{i18n.t("admin.bootstrap.signedInAs", { email: me?.user?.email ?? "" })}
|
||||
</p>
|
||||
</div>
|
||||
{:else if error}
|
||||
@@ -81,7 +82,7 @@
|
||||
{/if}
|
||||
</CardContent>
|
||||
<CardFooter class="flex justify-between gap-2">
|
||||
{#if me?.user?.is_platform_admin}
|
||||
{#if isFullPlatformAdmin(me)}
|
||||
<Button class="w-full" onclick={() => goto("/admin")}>{i18n.t("admin.bootstrap.goToPanel")}</Button>
|
||||
{:else}
|
||||
<Button variant="outline" class="w-full" onclick={() => goto("/dashboard")}>
|
||||
@@ -90,5 +91,5 @@
|
||||
{/if}
|
||||
</CardFooter>
|
||||
</Card>
|
||||
{/if}
|
||||
</PageShell>
|
||||
</PageShell>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { redirect } from "@sveltejs/kit";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
|
||||
/** Legacy `/admin/logs` → diagnostics. Layout.server already requires platform admin. */
|
||||
export const load: PageServerLoad = () => {
|
||||
redirect(307, "/admin/diagnostics");
|
||||
};
|
||||
@@ -528,7 +528,7 @@
|
||||
const link =
|
||||
res.accept_url?.trim() ||
|
||||
(res.token
|
||||
? `${window.location.origin}/accept-invite?token=${encodeURIComponent(res.token)}`
|
||||
? `${window.location.origin}/accept-invite#token=${encodeURIComponent(res.token)}`
|
||||
: "");
|
||||
if (link) {
|
||||
inviteAcceptLink = link;
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
import { DEMO_BOOKING_URL } from "$lib/site";
|
||||
import { submitSalesContact } from "$lib/sales-contact";
|
||||
import { notifySuccess, notifyApiError } from "$lib/notify";
|
||||
import PageShell from "$lib/components/PageShell.svelte";
|
||||
import SiteHeader from "$lib/components/site/SiteHeader.svelte";
|
||||
import Footer from "$lib/components/site/Footer.svelte";
|
||||
import SeoHead from "$lib/components/site/SeoHead.svelte";
|
||||
import Alert from "$lib/components/Alert.svelte";
|
||||
import {
|
||||
Button,
|
||||
@@ -65,7 +67,19 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<PageShell title={i18n.t("sales.contact.title")} description={i18n.t("sales.contact.lead")}>
|
||||
<SeoHead
|
||||
title={i18n.t("seo.contactSales.title")}
|
||||
description={i18n.t("seo.contactSales.description")}
|
||||
path="/contact-sales"
|
||||
/>
|
||||
|
||||
<div class="flex min-h-screen flex-col bg-background">
|
||||
<SiteHeader />
|
||||
<main id="main-content" class="mx-auto w-full max-w-3xl flex-1 px-4 pt-28 pb-12 sm:px-6">
|
||||
<div class="mb-8">
|
||||
<h1 class="text-4xl font-bold tracking-tight text-text">{i18n.t("sales.contact.title")}</h1>
|
||||
<p class="mt-2 text-lg text-text-muted">{i18n.t("sales.contact.lead")}</p>
|
||||
</div>
|
||||
{#if done}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@@ -152,4 +166,6 @@
|
||||
</CardContent>
|
||||
</Card>
|
||||
{/if}
|
||||
</PageShell>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
loadDocsAuthStatus,
|
||||
maskKeyPrefix,
|
||||
readStoredTryItKey,
|
||||
relabelRapiDocAuthRequired,
|
||||
resolveDocsTryItKey,
|
||||
writeStoredTryItKey,
|
||||
type DocsAuthStatus,
|
||||
@@ -54,6 +55,7 @@
|
||||
let runtimeWarning = $state("");
|
||||
/** $state so theme $effect re-runs after mount + SiteHeader toggle. */
|
||||
let rapiEl = $state<RapiDocElement | undefined>(undefined);
|
||||
let authLabelObserver: MutationObserver | null = null;
|
||||
let askOpen = $state(false);
|
||||
let mountGeneration = 0;
|
||||
let hydrateCheckTimer: number | undefined;
|
||||
@@ -121,6 +123,8 @@
|
||||
window.clearTimeout(hydrateCheckTimer);
|
||||
window.removeEventListener("error", onWindowError);
|
||||
window.removeEventListener("unhandledrejection", onRejection);
|
||||
authLabelObserver?.disconnect();
|
||||
authLabelObserver = null;
|
||||
rapiEl?.remove();
|
||||
rapiEl = undefined;
|
||||
};
|
||||
@@ -323,6 +327,8 @@
|
||||
loadError = "";
|
||||
runtimeWarning = "";
|
||||
window.clearTimeout(hydrateCheckTimer);
|
||||
authLabelObserver?.disconnect();
|
||||
authLabelObserver = null;
|
||||
rapiEl?.remove();
|
||||
rapiEl = undefined;
|
||||
|
||||
@@ -338,6 +344,7 @@
|
||||
return;
|
||||
}
|
||||
rapiEl = instance;
|
||||
authLabelObserver = relabelRapiDocAuthRequired(instance);
|
||||
} catch (err) {
|
||||
if (gen !== mountGeneration) return;
|
||||
loadState = "error";
|
||||
@@ -533,7 +540,7 @@
|
||||
{/if}
|
||||
</p>
|
||||
{:else}
|
||||
<p class="mt-1 text-xs text-text-muted" data-testid="docs-tryit-no-keys-legacy">
|
||||
<p class="mt-1 text-xs text-text-muted" data-testid="docs-tryit-no-keys">
|
||||
{docsAuth.canCreateKey
|
||||
? i18n.t("docs.tryIt.noKeysLegacyAdmin")
|
||||
: i18n.t("docs.tryIt.noKeysLegacyMember")}
|
||||
|
||||
@@ -470,7 +470,7 @@
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="custom_model">{i18n.t("ai.field.model")}</Label>
|
||||
<Input id="custom_model" bind:value={model} placeholder="gpt-4o-mini" autocomplete="off" />
|
||||
<Input id="custom_model" bind:value={model} placeholder={i18n.t("ai.placeholder.modelId")} autocomplete="off" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -494,7 +494,7 @@
|
||||
id="api_key"
|
||||
type="password"
|
||||
bind:value={apiKey}
|
||||
placeholder={hasApiKey ? i18n.t("ai.placeholder.keepKey") : "sk-…"}
|
||||
placeholder={hasApiKey ? i18n.t("ai.placeholder.keepKey") : i18n.t("ai.field.apiKey")}
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -95,12 +95,6 @@
|
||||
email: email || i18n.t("auth.login.yourEmail")
|
||||
})}
|
||||
</p>
|
||||
<p>
|
||||
{i18n.t("auth.login.platformAdminsReissue")}
|
||||
<a href="/admin/users" class="font-medium text-link hover:underline"
|
||||
>{i18n.t("auth.login.adminUsersLink")}</a
|
||||
>.
|
||||
</p>
|
||||
<p>
|
||||
<a href="/accept-invite" class="font-medium text-link hover:underline"
|
||||
>{i18n.t("auth.login.haveToken")}</a
|
||||
|
||||
@@ -28,14 +28,9 @@
|
||||
</p>
|
||||
<MarketingAuthCtas class="mt-8" />
|
||||
<p class="mt-4 text-sm text-text-muted">
|
||||
{i18n.t("pricing.page.subscribedBefore")}
|
||||
<a href="/billing" class="font-medium text-link hover:underline"
|
||||
>{i18n.t("nav.billing")}</a
|
||||
>
|
||||
{i18n.t("pricing.page.subscribedMid")}
|
||||
<a href="/plans" class="font-medium text-link hover:underline"
|
||||
>{i18n.t("pricing.page.plansLink")}</a
|
||||
>{i18n.t("pricing.page.subscribedAfter")}
|
||||
{i18n.t("pricing.page.guestSubscribedBefore")}
|
||||
<a href="/login" class="font-medium text-link hover:underline">{i18n.t("site.logIn")}</a>
|
||||
{i18n.t("pricing.page.guestSubscribedAfter")}
|
||||
</p>
|
||||
</section>
|
||||
<PricingSection hideIntro />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { page } from "$app/state";
|
||||
import { api, ApiError } from "$lib/api";
|
||||
import { consumeAuthLinkSecrets } from "$lib/auth-link-token";
|
||||
import { apiFormError, fieldDescribedBy, fieldInvalid } from "$lib/api-form-error";
|
||||
import { i18n } from "$lib/i18n";
|
||||
import {
|
||||
@@ -17,12 +17,6 @@
|
||||
Label
|
||||
} from "$lib/components/ui";
|
||||
|
||||
function tokenFromHash(hash: string): string {
|
||||
const raw = hash.startsWith("#") ? hash.slice(1) : hash;
|
||||
const params = new URLSearchParams(raw);
|
||||
return (params.get("token") ?? "").trim();
|
||||
}
|
||||
|
||||
let token = $state("");
|
||||
/** True when the token arrived via link; never show it in a visible input. */
|
||||
let tokenFromLink = $state(false);
|
||||
@@ -39,20 +33,15 @@
|
||||
const passwordHintId = "reset-password-hint";
|
||||
|
||||
onMount(() => {
|
||||
const fromHash = tokenFromHash(window.location.hash);
|
||||
const fromQuery = (new URL(window.location.href).searchParams.get("token") ?? "").trim();
|
||||
const fromSsrQuery = (page.url.searchParams.get("token") ?? "").trim();
|
||||
const resolved = fromHash || fromQuery || fromSsrQuery;
|
||||
if (resolved) {
|
||||
token = resolved;
|
||||
const consumed = consumeAuthLinkSecrets(window.location.href);
|
||||
if (consumed.token) {
|
||||
token = consumed.token;
|
||||
tokenFromLink = true;
|
||||
}
|
||||
hydrated = true;
|
||||
if (!fromHash && !fromQuery && !fromSsrQuery) return;
|
||||
const cleaned = new URL(window.location.href);
|
||||
cleaned.searchParams.delete("token");
|
||||
cleaned.hash = "";
|
||||
history.replaceState(history.state, "", cleaned.pathname + cleaned.search);
|
||||
if (consumed.stripped) {
|
||||
history.replaceState(history.state, "", consumed.cleanedPathSearch);
|
||||
}
|
||||
});
|
||||
|
||||
async function onSubmit(event: Event) {
|
||||
|
||||
@@ -598,7 +598,7 @@
|
||||
const link =
|
||||
created.accept_url?.trim() ||
|
||||
(created.token
|
||||
? `${window.location.origin}/accept-invite?token=${encodeURIComponent(created.token)}`
|
||||
? `${window.location.origin}/accept-invite#token=${encodeURIComponent(created.token)}`
|
||||
: "");
|
||||
trackEvent("invite_sent", {
|
||||
role: roleForEvent,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import { Button } from "$lib/components/ui";
|
||||
import SiteHeader from "$lib/components/site/SiteHeader.svelte";
|
||||
import Footer from "$lib/components/site/Footer.svelte";
|
||||
import SeoHead from "$lib/components/site/SeoHead.svelte";
|
||||
|
||||
const API_BASE = (PUBLIC_API_URL ?? "").replace(/\/$/, "") || "";
|
||||
|
||||
@@ -16,11 +17,12 @@
|
||||
let message = $state("");
|
||||
let error = $state("");
|
||||
let already = $state(false);
|
||||
let missingToken = $state(false);
|
||||
|
||||
onMount(async () => {
|
||||
token = page.url.searchParams.get("token") ?? "";
|
||||
if (!token) {
|
||||
error = i18n.t("flash.unsubscribe.missingToken");
|
||||
missingToken = true;
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
@@ -64,6 +66,12 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<SeoHead
|
||||
title={i18n.t("seo.unsubscribe.title")}
|
||||
description={i18n.t("seo.unsubscribe.description")}
|
||||
path="/unsubscribe"
|
||||
/>
|
||||
|
||||
<div class="flex min-h-screen flex-col bg-background">
|
||||
<SiteHeader />
|
||||
<main
|
||||
@@ -73,6 +81,8 @@
|
||||
<h1 class="text-2xl font-semibold text-text">{i18n.t("unsubscribe.title")}</h1>
|
||||
{#if loading}
|
||||
<p class="text-sm text-text-muted">{i18n.t("common.loading")}</p>
|
||||
{:else if missingToken}
|
||||
<p class="text-sm text-text-muted">{i18n.t("unsubscribe.useEmailLink")}</p>
|
||||
{:else if error}
|
||||
<p class="text-sm text-danger">{error}</p>
|
||||
{:else}
|
||||
|
||||
|
Before Width: | Height: | Size: 111 KiB |
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 1500ms — ok"
|
||||
],
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00-post-login-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00-post-login-mobile.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 1500ms — ok"
|
||||
],
|
||||
"generated_at": "2026-08-08T23:04:24Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:04:24Z",
|
||||
"load_ms": 1210,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00-post-login-mobile.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 188 KiB |
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 1500ms — ok"
|
||||
],
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00-post-login-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00-post-login-tablet.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 1500ms — ok"
|
||||
],
|
||||
"generated_at": "2026-08-08T23:08:42Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:08:42Z",
|
||||
"load_ms": 4242,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00-post-login-tablet.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 188 KiB |
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 1200ms — ok"
|
||||
],
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00b-login-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00b-login-tablet.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 1200ms — ok"
|
||||
],
|
||||
"generated_at": "2026-08-09T08:05:56Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-09T08:05:56Z",
|
||||
"load_ms": 16697,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\00b-login-tablet.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 111 KiB |
@@ -1,444 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"input[type=email],input[name=email],#email\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"input[type=password],input[name=password],#password\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 2000ms — ok"
|
||||
],
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\01-dashboard-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\01-dashboard-mobile.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open products",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "a[data-testid=\"store-reconnect-link-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[data-testid=\"store-reconnect-cta-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "Reconnect WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Reconnect WooCommerce",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "1. Feeds Connect import"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "2. Products 5 in catalog"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "3. Process 8 done"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "4. Export Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Products 5 8 processed · 0 unprocessed"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Categories 2 Catalog tree"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Attributes 1 Attribute library"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Feeds 0 Import sources"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(5)",
|
||||
"role": "link",
|
||||
"name": "Credits Unlimited Enterprise · Billing"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(1) \u003e div:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View all"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Feeds Import and map"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Products Browse and process"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Jobs Monitor tasks"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Exports Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e27",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e28",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e29",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 PLATFORM DEMO Platform Demo Unlimited Start \"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"PLATFORM DEMO Platform Demo Unlimited Start tutorial Open pr\"\nheading \"Platform Demo\" [level=1]\nbutton \"Start tutorial\"\nbutton \"Open products\"\nstatus \"Reconnect store after migration Store API credentials were n\" [testid=store-reconnect-banner]\nlink \"WooCommerce\" [testid=store-reconnect-link-woocommerce]\nlink \"Reconnect WooCommerce\" [testid=store-reconnect-cta-woocommerce]\nbutton \"Reconnect WooCommerce\"\nheading \"Catalog workflow\" [level=2]\nlink \"1. Feeds Connect import\"\nlink \"2. Products 5 in catalog\"\nlink \"3. Process 8 done\"\nlink \"4. Export Templates \u0026 download\"\nheading \"Overview\" [level=2]\nlink \"Products 5 8 processed · 0 unprocessed\"\nlink \"Categories 2 Catalog tree\"\nlink \"Attributes 1 Attribute library\"\nlink \"Feeds 0 Import sources\"\nlink \"Credits Unlimited Enterprise · Billing\"\nheading \"Recent activity\" [level=2]\nlink \"View all\"\nheading \"Quick links\" [level=2]\nlink \"Feeds Import and map\"\nlink \"Products Browse and process\"\nlink \"Jobs Monitor tasks\"\nlink \"Exports Templates \u0026 download\"\nheading \"WHAT'S NEW\" [level=3]\nheading \"User Experience Improvements\" [level=3]\nheading \"Key Features:\" [level=4]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 fill \"input[type=email],input[name=email],#email\"=\"demo@descrybe.local\" — ok",
|
||||
"step 3 fill \"input[type=password],input[name=password],#password\"=\"DemoPass123!\" — ok",
|
||||
"step 4 click button[type=submit] — ok",
|
||||
"step 5 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 6 wait_hydrate — ok",
|
||||
"step 7 wait 2000ms — ok"
|
||||
],
|
||||
"generated_at": "2026-08-08T23:03:35Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:03:35Z",
|
||||
"load_ms": 1357,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open products",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "a[data-testid=\"store-reconnect-link-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[data-testid=\"store-reconnect-cta-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "Reconnect WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Reconnect WooCommerce",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "1. Feeds Connect import"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "2. Products 5 in catalog"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "3. Process 8 done"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "4. Export Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Products 5 8 processed · 0 unprocessed"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Categories 2 Catalog tree"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Attributes 1 Attribute library"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Feeds 0 Import sources"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(5)",
|
||||
"role": "link",
|
||||
"name": "Credits Unlimited Enterprise · Billing"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(1) \u003e div:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View all"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Feeds Import and map"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Products Browse and process"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Jobs Monitor tasks"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Exports Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e27",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e28",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e29",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\01-dashboard-mobile.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 PLATFORM DEMO Platform Demo Unlimited Start \"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"PLATFORM DEMO Platform Demo Unlimited Start tutorial Open pr\"\nheading \"Platform Demo\" [level=1]\nbutton \"Start tutorial\"\nbutton \"Open products\"\nstatus \"Reconnect store after migration Store API credentials were n\" [testid=store-reconnect-banner]\nlink \"WooCommerce\" [testid=store-reconnect-link-woocommerce]\nlink \"Reconnect WooCommerce\" [testid=store-reconnect-cta-woocommerce]\nbutton \"Reconnect WooCommerce\"\nheading \"Catalog workflow\" [level=2]\nlink \"1. Feeds Connect import\"\nlink \"2. Products 5 in catalog\"\nlink \"3. Process 8 done\"\nlink \"4. Export Templates \u0026 download\"\nheading \"Overview\" [level=2]\nlink \"Products 5 8 processed · 0 unprocessed\"\nlink \"Categories 2 Catalog tree\"\nlink \"Attributes 1 Attribute library\"\nlink \"Feeds 0 Import sources\"\nlink \"Credits Unlimited Enterprise · Billing\"\nheading \"Recent activity\" [level=2]\nlink \"View all\"\nheading \"Quick links\" [level=2]\nlink \"Feeds Import and map\"\nlink \"Products Browse and process\"\nlink \"Jobs Monitor tasks\"\nlink \"Exports Templates \u0026 download\"\nheading \"WHAT'S NEW\" [level=3]\nheading \"User Experience Improvements\" [level=3]\nheading \"Key Features:\" [level=4]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 84 KiB |
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"action_log": null,
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/login",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\02-login-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\02-login-mobile.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"action_log": null,
|
||||
"generated_at": "2026-08-08T23:15:01Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/login",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:15:01Z",
|
||||
"load_ms": 969,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\02-login-mobile.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 123 KiB |
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"action_log": null,
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/login",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\02-login-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\02-login-tablet.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"action_log": null,
|
||||
"generated_at": "2026-08-08T23:15:03Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/login",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:15:03Z",
|
||||
"load_ms": 986,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\02-login-tablet.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 188 KiB |
@@ -1,492 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260809T080924Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260809T080924Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\03-dashboard-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\03-dashboard-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260809T080924Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open products",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "a[data-testid=\"store-reconnect-link-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "a[data-testid=\"store-reconnect-cta-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "Reconnect WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Reconnect WooCommerce",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "1. Feeds Connect import"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "2. Products 5 in catalog"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "3. Process 8 done"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "4. Export Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Products 5 8 processed · 0 unprocessed"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Categories 2 Catalog tree"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Attributes 1 Attribute library"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Feeds 0 Import sources"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(5)",
|
||||
"role": "link",
|
||||
"name": "Credits Unlimited Enterprise · Billing"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(1) \u003e div:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View all"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Feeds Import and map"
|
||||
},
|
||||
{
|
||||
"ref": "e27",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Products Browse and process"
|
||||
},
|
||||
{
|
||||
"ref": "e28",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Jobs Monitor tasks"
|
||||
},
|
||||
{
|
||||
"ref": "e29",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Exports Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e30",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e31",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e32",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e33",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e34",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D PLATFORM DEMO Platform Demo Unlimited Star\"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"PLATFORM DEMO Platform Demo Unlimited Start tutorial Open pr\"\nheading \"Platform Demo\" [level=1]\nbutton \"Open products\"\nstatus \"Reconnect store after migration Store API credentials were n\" [testid=store-reconnect-banner]\nlink \"WooCommerce\" [testid=store-reconnect-link-woocommerce]\nlink \"Reconnect WooCommerce\" [testid=store-reconnect-cta-woocommerce]\nbutton \"Reconnect WooCommerce\"\nheading \"Catalog workflow\" [level=2]\nlink \"1. Feeds Connect import\"\nlink \"2. Products 5 in catalog\"\nlink \"3. Process 8 done\"\nlink \"4. Export Templates \u0026 download\"\nheading \"Overview\" [level=2]\nlink \"Products 5 8 processed · 0 unprocessed\"\nlink \"Categories 2 Catalog tree\"\nlink \"Attributes 1 Attribute library\"\nlink \"Feeds 0 Import sources\"\nlink \"Credits Unlimited Enterprise · Billing\"\nheading \"Recent activity\" [level=2]\nlink \"View all\"\nheading \"Quick links\" [level=2]\nlink \"Feeds Import and map\"\nlink \"Products Browse and process\"\nlink \"Jobs Monitor tasks\"\nlink \"Exports Templates \u0026 download\"\nheading \"WHAT'S NEW\" [level=3]\nheading \"User Experience Improvements\" [level=3]\nheading \"Key Features:\" [level=4]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-09T08:09:24Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-09T08:09:24Z",
|
||||
"load_ms": 3416,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open products",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "a[data-testid=\"store-reconnect-link-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "a[data-testid=\"store-reconnect-cta-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "Reconnect WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Reconnect WooCommerce",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "1. Feeds Connect import"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "2. Products 5 in catalog"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "3. Process 8 done"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "4. Export Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Products 5 8 processed · 0 unprocessed"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Categories 2 Catalog tree"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Attributes 1 Attribute library"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Feeds 0 Import sources"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(5)",
|
||||
"role": "link",
|
||||
"name": "Credits Unlimited Enterprise · Billing"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(1) \u003e div:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View all"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Feeds Import and map"
|
||||
},
|
||||
{
|
||||
"ref": "e27",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Products Browse and process"
|
||||
},
|
||||
{
|
||||
"ref": "e28",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Jobs Monitor tasks"
|
||||
},
|
||||
{
|
||||
"ref": "e29",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Exports Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e30",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e31",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e32",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e33",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e34",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\03-dashboard-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D PLATFORM DEMO Platform Demo Unlimited Star\"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"PLATFORM DEMO Platform Demo Unlimited Start tutorial Open pr\"\nheading \"Platform Demo\" [level=1]\nbutton \"Open products\"\nstatus \"Reconnect store after migration Store API credentials were n\" [testid=store-reconnect-banner]\nlink \"WooCommerce\" [testid=store-reconnect-link-woocommerce]\nlink \"Reconnect WooCommerce\" [testid=store-reconnect-cta-woocommerce]\nbutton \"Reconnect WooCommerce\"\nheading \"Catalog workflow\" [level=2]\nlink \"1. Feeds Connect import\"\nlink \"2. Products 5 in catalog\"\nlink \"3. Process 8 done\"\nlink \"4. Export Templates \u0026 download\"\nheading \"Overview\" [level=2]\nlink \"Products 5 8 processed · 0 unprocessed\"\nlink \"Categories 2 Catalog tree\"\nlink \"Attributes 1 Attribute library\"\nlink \"Feeds 0 Import sources\"\nlink \"Credits Unlimited Enterprise · Billing\"\nheading \"Recent activity\" [level=2]\nlink \"View all\"\nheading \"Quick links\" [level=2]\nlink \"Feeds Import and map\"\nlink \"Products Browse and process\"\nlink \"Jobs Monitor tasks\"\nlink \"Exports Templates \u0026 download\"\nheading \"WHAT'S NEW\" [level=3]\nheading \"User Experience Improvements\" [level=3]\nheading \"Key Features:\" [level=4]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 91 KiB |
@@ -1,340 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230428Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230428Z\\report.json",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/settings?tab=profile",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\04-settings-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\04-settings-mobile.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230428Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(1)",
|
||||
"role": "tab",
|
||||
"name": "Profile",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(2)",
|
||||
"role": "tab",
|
||||
"name": "Company",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "tab",
|
||||
"name": "Alerts",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(4)",
|
||||
"role": "tab",
|
||||
"name": "API keys",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(5)",
|
||||
"role": "tab",
|
||||
"name": "Team",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div:nth-of-type(1) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Save changes",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "#firstName",
|
||||
"role": "textbox",
|
||||
"name": "First Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your first name",
|
||||
"value": "Demo"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "#lastName",
|
||||
"role": "textbox",
|
||||
"name": "Last Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your last name",
|
||||
"value": "User"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "#email",
|
||||
"role": "textbox",
|
||||
"name": "Email",
|
||||
"type": "email",
|
||||
"value": "demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#uiLocale",
|
||||
"role": "select",
|
||||
"name": "Dashboard language",
|
||||
"value": "en"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 Settings Account, company, API keys, and tea\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"Settings Account, company, API keys, and team.\"\nheading \"Settings\" [level=1]\ntab \"Profile\"\ntab \"Company\"\ntab \"Alerts\"\ntab \"API keys\"\ntab \"Team\"\nheading \"Profile\" [level=2]\nbutton \"Save changes\"\nheading \"Personal Information\" [level=3]\ntextbox \"First Name\"\ntextbox \"Last Name\"\ntextbox \"Email\"\ncombobox \"Dashboard language\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:04:28Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/settings?tab=profile",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:04:28Z",
|
||||
"load_ms": 1959,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(1)",
|
||||
"role": "tab",
|
||||
"name": "Profile",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(2)",
|
||||
"role": "tab",
|
||||
"name": "Company",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "tab",
|
||||
"name": "Alerts",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(4)",
|
||||
"role": "tab",
|
||||
"name": "API keys",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(5)",
|
||||
"role": "tab",
|
||||
"name": "Team",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div:nth-of-type(1) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Save changes",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "#firstName",
|
||||
"role": "textbox",
|
||||
"name": "First Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your first name",
|
||||
"value": "Demo"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "#lastName",
|
||||
"role": "textbox",
|
||||
"name": "Last Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your last name",
|
||||
"value": "User"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "#email",
|
||||
"role": "textbox",
|
||||
"name": "Email",
|
||||
"type": "email",
|
||||
"value": "demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#uiLocale",
|
||||
"role": "select",
|
||||
"name": "Dashboard language",
|
||||
"value": "en"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\04-settings-mobile.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 Settings Account, company, API keys, and tea\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"Settings Account, company, API keys, and team.\"\nheading \"Settings\" [level=1]\ntab \"Profile\"\ntab \"Company\"\ntab \"Alerts\"\ntab \"API keys\"\ntab \"Team\"\nheading \"Profile\" [level=2]\nbutton \"Save changes\"\nheading \"Personal Information\" [level=3]\ntextbox \"First Name\"\ntextbox \"Last Name\"\ntextbox \"Email\"\ncombobox \"Dashboard language\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 123 KiB |
@@ -1,408 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230850Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230850Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/settings?tab=profile",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\04-settings-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\04-settings-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230850Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(1)",
|
||||
"role": "tab",
|
||||
"name": "Profile",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(2)",
|
||||
"role": "tab",
|
||||
"name": "Company",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "tab",
|
||||
"name": "Alerts",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(4)",
|
||||
"role": "tab",
|
||||
"name": "API keys",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(5)",
|
||||
"role": "tab",
|
||||
"name": "Team",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div:nth-of-type(1) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Save changes",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#firstName",
|
||||
"role": "textbox",
|
||||
"name": "First Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your first name",
|
||||
"value": "Demo"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "#lastName",
|
||||
"role": "textbox",
|
||||
"name": "Last Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your last name",
|
||||
"value": "User"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "#email",
|
||||
"role": "textbox",
|
||||
"name": "Email",
|
||||
"type": "email",
|
||||
"value": "demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "#uiLocale",
|
||||
"role": "select",
|
||||
"name": "Dashboard language",
|
||||
"value": "en"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D Settings Account, company, API keys, and t\"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"Settings Account, company, API keys, and team.\"\nheading \"Settings\" [level=1]\ntab \"Profile\"\ntab \"Company\"\ntab \"Alerts\"\ntab \"API keys\"\ntab \"Team\"\nheading \"Profile\" [level=2]\nbutton \"Save changes\"\nheading \"Personal Information\" [level=3]\ntextbox \"First Name\"\ntextbox \"Last Name\"\ntextbox \"Email\"\ncombobox \"Dashboard language\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:08:50Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/settings?tab=profile",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:08:50Z",
|
||||
"load_ms": 3897,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(1)",
|
||||
"role": "tab",
|
||||
"name": "Profile",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(2)",
|
||||
"role": "tab",
|
||||
"name": "Company",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "tab",
|
||||
"name": "Alerts",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(4)",
|
||||
"role": "tab",
|
||||
"name": "API keys",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e aside \u003e div \u003e div \u003e button:nth-of-type(5)",
|
||||
"role": "tab",
|
||||
"name": "Team",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div:nth-of-type(1) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Save changes",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#firstName",
|
||||
"role": "textbox",
|
||||
"name": "First Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your first name",
|
||||
"value": "Demo"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "#lastName",
|
||||
"role": "textbox",
|
||||
"name": "Last Name",
|
||||
"type": "text",
|
||||
"placeholder": "Your last name",
|
||||
"value": "User"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "#email",
|
||||
"role": "textbox",
|
||||
"name": "Email",
|
||||
"type": "email",
|
||||
"value": "demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "#uiLocale",
|
||||
"role": "select",
|
||||
"name": "Dashboard language",
|
||||
"value": "en"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\04-settings-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D Settings Account, company, API keys, and t\"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"Settings Account, company, API keys, and team.\"\nheading \"Settings\" [level=1]\ntab \"Profile\"\ntab \"Company\"\ntab \"Alerts\"\ntab \"API keys\"\ntab \"Team\"\nheading \"Profile\" [level=2]\nbutton \"Save changes\"\nheading \"Personal Information\" [level=3]\ntextbox \"First Name\"\ntextbox \"Last Name\"\ntextbox \"Email\"\ncombobox \"Dashboard language\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 103 KiB |
@@ -1,268 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230430Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230430Z\\report.json",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/billing",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\05-billing-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\05-billing-mobile.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230430Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Compare plans"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Manage payment",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Add credits",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div \u003e section \u003e div:nth-of-type(1) \u003e select",
|
||||
"role": "select",
|
||||
"name": "Last 7 days Last 30 days Current cycle All time",
|
||||
"value": "30d"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Public pricing"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Manage plan on Plans"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 Usage \u0026 Billing Platform Demo · Unlimited pr\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nheading \"Usage \u0026 Billing\" [level=1]\nlink \"Compare plans\"\nbutton \"Manage payment\"\nbutton \"Add credits\"\nheading \"Current plan\" [level=3]\nheading \"Credits remaining\" [level=3]\nheading \"Usage\" [level=2]\ncombobox \"Last 7 days Last 30 days Current cycle All time\"\nheading \"Products by day\" [level=3]\nlink \"Public pricing\"\nlink \"Manage plan on Plans\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:04:30Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/billing",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:04:30Z",
|
||||
"load_ms": 1417,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Compare plans"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Manage payment",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Add credits",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div \u003e section \u003e div:nth-of-type(1) \u003e select",
|
||||
"role": "select",
|
||||
"name": "Last 7 days Last 30 days Current cycle All time",
|
||||
"value": "30d"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Public pricing"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Manage plan on Plans"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\05-billing-mobile.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 Usage \u0026 Billing Platform Demo · Unlimited pr\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nheading \"Usage \u0026 Billing\" [level=1]\nlink \"Compare plans\"\nbutton \"Manage payment\"\nbutton \"Add credits\"\nheading \"Current plan\" [level=3]\nheading \"Credits remaining\" [level=3]\nheading \"Usage\" [level=2]\ncombobox \"Last 7 days Last 30 days Current cycle All time\"\nheading \"Products by day\" [level=3]\nlink \"Public pricing\"\nlink \"Manage plan on Plans\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 150 KiB |
@@ -1,336 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230857Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230857Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/billing",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\05-billing-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\05-billing-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230857Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Compare plans"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Manage payment",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Add credits",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e div \u003e section \u003e div:nth-of-type(1) \u003e select",
|
||||
"role": "select",
|
||||
"name": "Last 7 days Last 30 days Current cycle All time",
|
||||
"value": "30d"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Public pricing"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Manage plan on Plans"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D Usage \u0026 Billing Platform Demo · Unlimited \"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nheading \"Usage \u0026 Billing\" [level=1]\nlink \"Compare plans\"\nbutton \"Manage payment\"\nbutton \"Add credits\"\nheading \"Current plan\" [level=3]\nheading \"Credits remaining\" [level=3]\nheading \"Usage\" [level=2]\ncombobox \"Last 7 days Last 30 days Current cycle All time\"\nheading \"Products by day\" [level=3]\nlink \"Public pricing\"\nlink \"Manage plan on Plans\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:08:57Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/billing",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:08:57Z",
|
||||
"load_ms": 4040,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Compare plans"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Manage payment",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(1) \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Add credits",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e div \u003e section \u003e div:nth-of-type(1) \u003e select",
|
||||
"role": "select",
|
||||
"name": "Last 7 days Last 30 days Current cycle All time",
|
||||
"value": "30d"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Public pricing"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#main-content \u003e div \u003e div \u003e div:nth-of-type(3) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Manage plan on Plans"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\05-billing-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D Usage \u0026 Billing Platform Demo · Unlimited \"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nheading \"Usage \u0026 Billing\" [level=1]\nlink \"Compare plans\"\nbutton \"Manage payment\"\nbutton \"Add credits\"\nheading \"Current plan\" [level=3]\nheading \"Credits remaining\" [level=3]\nheading \"Usage\" [level=2]\ncombobox \"Last 7 days Last 30 days Current cycle All time\"\nheading \"Products by day\" [level=3]\nlink \"Public pricing\"\nlink \"Manage plan on Plans\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 93 KiB |
@@ -1,312 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230434Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230434Z\\report.json",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/support",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\06-support-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\06-support-mobile.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230434Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Refresh",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e a",
|
||||
"role": "link",
|
||||
"name": "New ticket"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "header \u003e div:nth-of-type(2) \u003e div \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "New ticket",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "All",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Pending",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(4)",
|
||||
"role": "button",
|
||||
"name": "Resolved",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(5)",
|
||||
"role": "button",
|
||||
"name": "Closed",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "tr[aria-label=\"Open ticket API matrix smoke billing\"]",
|
||||
"role": "link",
|
||||
"name": "Open ticket API matrix smoke billing"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 Support Center Open a ticket for billing, bu\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"Support Center Open a ticket for billing, bugs, or account h\"\nheading \"Support Center\" [level=1]\nbutton \"Refresh\"\nlink \"New ticket\"\nbutton \"New ticket\"\nheading \"Your tickets\" [level=3]\nbutton \"All\"\nbutton \"Open\"\nbutton \"Pending\"\nbutton \"Resolved\"\nbutton \"Closed\"\nlink \"Open ticket API matrix smoke billing\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:04:34Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/support",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:04:34Z",
|
||||
"load_ms": 2358,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Refresh",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e a",
|
||||
"role": "link",
|
||||
"name": "New ticket"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "header \u003e div:nth-of-type(2) \u003e div \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "New ticket",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "All",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Pending",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(4)",
|
||||
"role": "button",
|
||||
"name": "Resolved",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(5)",
|
||||
"role": "button",
|
||||
"name": "Closed",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "tr[aria-label=\"Open ticket API matrix smoke billing\"]",
|
||||
"role": "link",
|
||||
"name": "Open ticket API matrix smoke billing"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\06-support-mobile.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 Support Center Open a ticket for billing, bu\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"Support Center Open a ticket for billing, bugs, or account h\"\nheading \"Support Center\" [level=1]\nbutton \"Refresh\"\nlink \"New ticket\"\nbutton \"New ticket\"\nheading \"Your tickets\" [level=3]\nbutton \"All\"\nbutton \"Open\"\nbutton \"Pending\"\nbutton \"Resolved\"\nbutton \"Closed\"\nlink \"Open ticket API matrix smoke billing\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 113 KiB |
@@ -1,380 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230905Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230905Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/support",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\06-support-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\06-support-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230905Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Refresh",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e a",
|
||||
"role": "link",
|
||||
"name": "New ticket"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "header \u003e div:nth-of-type(2) \u003e div \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "New ticket",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "All",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Pending",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(4)",
|
||||
"role": "button",
|
||||
"name": "Resolved",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(5)",
|
||||
"role": "button",
|
||||
"name": "Closed",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "tr[aria-label=\"Open ticket API matrix smoke billing\"]",
|
||||
"role": "link",
|
||||
"name": "Open ticket API matrix smoke billing"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D Support Center Open a ticket for billing, \"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"Support Center Open a ticket for billing, bugs, or account h\"\nheading \"Support Center\" [level=1]\nbutton \"Refresh\"\nlink \"New ticket\"\nbutton \"New ticket\"\nheading \"Your tickets\" [level=3]\nbutton \"All\"\nbutton \"Open\"\nbutton \"Pending\"\nbutton \"Resolved\"\nbutton \"Closed\"\nlink \"Open ticket API matrix smoke billing\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:09:05Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/support",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:09:05Z",
|
||||
"load_ms": 2695,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Refresh",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e a",
|
||||
"role": "link",
|
||||
"name": "New ticket"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "header \u003e div:nth-of-type(2) \u003e div \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "New ticket",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "All",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Pending",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(4)",
|
||||
"role": "button",
|
||||
"name": "Resolved",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(5)",
|
||||
"role": "button",
|
||||
"name": "Closed",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "tr[aria-label=\"Open ticket API matrix smoke billing\"]",
|
||||
"role": "link",
|
||||
"name": "Open ticket API matrix smoke billing"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\06-support-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D Support Center Open a ticket for billing, \"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"Support Center Open a ticket for billing, bugs, or account h\"\nheading \"Support Center\" [level=1]\nbutton \"Refresh\"\nlink \"New ticket\"\nbutton \"New ticket\"\nheading \"Your tickets\" [level=3]\nbutton \"All\"\nbutton \"Open\"\nbutton \"Pending\"\nbutton \"Resolved\"\nbutton \"Closed\"\nlink \"Open ticket API matrix smoke billing\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 96 KiB |
@@ -1,346 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230439Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230439Z\\report.json",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/support/new",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\07-support-new-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\07-support-new-mobile.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230439Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Back to tickets"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Back to tickets",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#support-subject",
|
||||
"role": "textbox",
|
||||
"name": "Subject",
|
||||
"type": "text",
|
||||
"placeholder": "Short summary"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "#support-category",
|
||||
"role": "select",
|
||||
"name": "Category",
|
||||
"value": "other"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "#support-priority",
|
||||
"role": "select",
|
||||
"name": "Priority",
|
||||
"value": "normal"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "#support-sku",
|
||||
"role": "textbox",
|
||||
"name": "Related SKU",
|
||||
"type": "text",
|
||||
"placeholder": "e.g. ABC-123"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "#support-tags",
|
||||
"role": "textbox",
|
||||
"name": "Tags",
|
||||
"type": "text",
|
||||
"placeholder": "login, invoice (comma-separated)"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "#support-body",
|
||||
"role": "textbox",
|
||||
"name": "Message",
|
||||
"placeholder": "Describe the issue, what you expected, and anything that helps us reproduce it."
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Create ticket",
|
||||
"type": "submit"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Cancel"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Cancel",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 New support ticket Tell us what you need hel\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"New support ticket Tell us what you need help with. Include \"\nheading \"New support ticket\" [level=1]\nlink \"Back to tickets\"\nbutton \"Back to tickets\"\nform \"Ticket details Status starts as open. You may get an automat\" [testid=support-create-form]\nheading \"Ticket details\" [level=3]\ntextbox \"Subject\"\ncombobox \"Category\"\ncombobox \"Priority\"\ntextbox \"Related SKU\"\ntextbox \"Tags\"\ntextbox \"Message\"\nbutton \"Create ticket\"\nlink \"Cancel\"\nbutton \"Cancel\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:04:39Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/support/new",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:04:39Z",
|
||||
"load_ms": 2556,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Back to tickets"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Back to tickets",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#support-subject",
|
||||
"role": "textbox",
|
||||
"name": "Subject",
|
||||
"type": "text",
|
||||
"placeholder": "Short summary"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "#support-category",
|
||||
"role": "select",
|
||||
"name": "Category",
|
||||
"value": "other"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "#support-priority",
|
||||
"role": "select",
|
||||
"name": "Priority",
|
||||
"value": "normal"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "#support-sku",
|
||||
"role": "textbox",
|
||||
"name": "Related SKU",
|
||||
"type": "text",
|
||||
"placeholder": "e.g. ABC-123"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "#support-tags",
|
||||
"role": "textbox",
|
||||
"name": "Tags",
|
||||
"type": "text",
|
||||
"placeholder": "login, invoice (comma-separated)"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "#support-body",
|
||||
"role": "textbox",
|
||||
"name": "Message",
|
||||
"placeholder": "Describe the issue, what you expected, and anything that helps us reproduce it."
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Create ticket",
|
||||
"type": "submit"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Cancel"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Cancel",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\07-support-new-mobile.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 New support ticket Tell us what you need hel\"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"New support ticket Tell us what you need help with. Include \"\nheading \"New support ticket\" [level=1]\nlink \"Back to tickets\"\nbutton \"Back to tickets\"\nform \"Ticket details Status starts as open. You may get an automat\" [testid=support-create-form]\nheading \"Ticket details\" [level=3]\ntextbox \"Subject\"\ncombobox \"Category\"\ncombobox \"Priority\"\ntextbox \"Related SKU\"\ntextbox \"Tags\"\ntextbox \"Message\"\nbutton \"Create ticket\"\nlink \"Cancel\"\nbutton \"Cancel\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 134 KiB |
@@ -1,414 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230911Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230911Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/support/new",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\07-support-new-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\07-support-new-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230911Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Back to tickets"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Back to tickets",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "#support-subject",
|
||||
"role": "textbox",
|
||||
"name": "Subject",
|
||||
"type": "text",
|
||||
"placeholder": "Short summary"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "#support-category",
|
||||
"role": "select",
|
||||
"name": "Category",
|
||||
"value": "other"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#support-priority",
|
||||
"role": "select",
|
||||
"name": "Priority",
|
||||
"value": "normal"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#support-sku",
|
||||
"role": "textbox",
|
||||
"name": "Related SKU",
|
||||
"type": "text",
|
||||
"placeholder": "e.g. ABC-123"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#support-tags",
|
||||
"role": "textbox",
|
||||
"name": "Tags",
|
||||
"type": "text",
|
||||
"placeholder": "login, invoice (comma-separated)"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "#support-body",
|
||||
"role": "textbox",
|
||||
"name": "Message",
|
||||
"placeholder": "Describe the issue, what you expected, and anything that helps us reproduce it."
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Create ticket",
|
||||
"type": "submit"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Cancel"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Cancel",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D New support ticket Tell us what you need h\"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"New support ticket Tell us what you need help with. Include \"\nheading \"New support ticket\" [level=1]\nlink \"Back to tickets\"\nbutton \"Back to tickets\"\nform \"Ticket details Status starts as open. You may get an automat\" [testid=support-create-form]\nheading \"Ticket details\" [level=3]\ntextbox \"Subject\"\ncombobox \"Category\"\ncombobox \"Priority\"\ntextbox \"Related SKU\"\ntextbox \"Tags\"\ntextbox \"Message\"\nbutton \"Create ticket\"\nlink \"Cancel\"\nbutton \"Cancel\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:09:11Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/support/new",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:09:11Z",
|
||||
"load_ms": 2657,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "header \u003e div \u003e div \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[aria-label=\"Account settings for demo@descrybe.local\"]",
|
||||
"role": "link",
|
||||
"name": "Account settings for demo@descrybe.local"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Back to tickets"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Back to tickets",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "#support-subject",
|
||||
"role": "textbox",
|
||||
"name": "Subject",
|
||||
"type": "text",
|
||||
"placeholder": "Short summary"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "#support-category",
|
||||
"role": "select",
|
||||
"name": "Category",
|
||||
"value": "other"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "#support-priority",
|
||||
"role": "select",
|
||||
"name": "Priority",
|
||||
"value": "normal"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#support-sku",
|
||||
"role": "textbox",
|
||||
"name": "Related SKU",
|
||||
"type": "text",
|
||||
"placeholder": "e.g. ABC-123"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "#support-tags",
|
||||
"role": "textbox",
|
||||
"name": "Tags",
|
||||
"type": "text",
|
||||
"placeholder": "login, invoice (comma-separated)"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "#support-body",
|
||||
"role": "textbox",
|
||||
"name": "Message",
|
||||
"placeholder": "Describe the issue, what you expected, and anything that helps us reproduce it."
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Create ticket",
|
||||
"type": "submit"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "form \u003e div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Cancel"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div:nth-of-type(4) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Cancel",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\07-support-new-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 D New support ticket Tell us what you need h\"\nbanner \"Platform Demo 1 D\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Account settings for demo@descrybe.local\"\nbutton \"Sign out\"\nbanner \"New support ticket Tell us what you need help with. Include \"\nheading \"New support ticket\" [level=1]\nlink \"Back to tickets\"\nbutton \"Back to tickets\"\nform \"Ticket details Status starts as open. You may get an automat\" [testid=support-create-form]\nheading \"Ticket details\" [level=3]\ntextbox \"Subject\"\ncombobox \"Category\"\ncombobox \"Priority\"\ntextbox \"Related SKU\"\ntextbox \"Tags\"\ntextbox \"Message\"\nbutton \"Create ticket\"\nlink \"Cancel\"\nbutton \"Cancel\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 54 KiB |
@@ -1,136 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231439Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231439Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/admin/support",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\10-admin-support-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\10-admin-support-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231439Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#admin-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Refresh",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Support Center Staff inbox — claim from the queue, filter by\"\nbanner \"Support Center Staff inbox — claim from the queue, filter by\"\nheading \"Support Center\" [level=1]\nbutton \"Refresh\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:14:39Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/admin/support",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:14:39Z",
|
||||
"load_ms": 15197,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#admin-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "div \u003e header \u003e div:nth-of-type(2) \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Refresh",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\10-admin-support-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Support Center Staff inbox — claim from the queue, filter by\"\nbanner \"Support Center Staff inbox — claim from the queue, filter by\"\nheading \"Support Center\" [level=1]\nbutton \"Refresh\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 64 KiB |
@@ -1,136 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231441Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231441Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/admin/users",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\11-admin-users-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\11-admin-users-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231441Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#admin-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "#main-content \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Re-issue set-password invites",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"PLATFORM ADMIN Users \u0026 organizations Platform user directory\"\nbanner \"PLATFORM ADMIN Users \u0026 organizations Platform user directory\"\nheading \"Users \u0026 organizations\" [level=1]\nbutton \"Re-issue set-password invites\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:14:41Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/admin/users",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:14:41Z",
|
||||
"load_ms": 1162,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#admin-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "#main-content \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button",
|
||||
"role": "button",
|
||||
"name": "Re-issue set-password invites",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\11-admin-users-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"PLATFORM ADMIN Users \u0026 organizations Platform user directory\"\nbanner \"PLATFORM ADMIN Users \u0026 organizations Platform user directory\"\nheading \"Users \u0026 organizations\" [level=1]\nbutton \"Re-issue set-password invites\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 51 KiB |
@@ -1,122 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231457Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231457Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/admin/settings",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\12-admin-settings-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\12-admin-settings-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231457Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#admin-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform settings Platform credentials, AI roles, mail, and \"\nbanner \"Platform settings Platform credentials, AI roles, mail, and \"\nheading \"Platform settings\" [level=1]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:14:57Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/admin/settings",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:14:57Z",
|
||||
"load_ms": 15130,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#admin-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\12-admin-settings-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform settings Platform credentials, AI roles, mail, and \"\nbanner \"Platform settings Platform credentials, AI roles, mail, and \"\nheading \"Platform settings\" [level=1]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 111 KiB |
@@ -1,424 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230831Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230831Z\\report.json",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\13-nav-open-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\13-nav-open-mobile.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T230831Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open products",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "a[data-testid=\"store-reconnect-link-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[data-testid=\"store-reconnect-cta-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "Reconnect WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Reconnect WooCommerce",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "1. Feeds Connect import"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "2. Products 5 in catalog"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "3. Process 8 done"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "4. Export Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Products 5 8 processed · 0 unprocessed"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Categories 2 Catalog tree"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Attributes 1 Attribute library"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Feeds 0 Import sources"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(5)",
|
||||
"role": "link",
|
||||
"name": "Credits Unlimited Enterprise · Billing"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(1) \u003e div:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View all"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Feeds Import and map"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Products Browse and process"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Jobs Monitor tasks"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Exports Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e27",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e28",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e29",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 PLATFORM DEMO Platform Demo Unlimited Start \"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"PLATFORM DEMO Platform Demo Unlimited Start tutorial Open pr\"\nheading \"Platform Demo\" [level=1]\nbutton \"Start tutorial\"\nbutton \"Open products\"\nstatus \"Reconnect store after migration Store API credentials were n\" [testid=store-reconnect-banner]\nlink \"WooCommerce\" [testid=store-reconnect-link-woocommerce]\nlink \"Reconnect WooCommerce\" [testid=store-reconnect-cta-woocommerce]\nbutton \"Reconnect WooCommerce\"\nheading \"Catalog workflow\" [level=2]\nlink \"1. Feeds Connect import\"\nlink \"2. Products 5 in catalog\"\nlink \"3. Process 8 done\"\nlink \"4. Export Templates \u0026 download\"\nheading \"Overview\" [level=2]\nlink \"Products 5 8 processed · 0 unprocessed\"\nlink \"Categories 2 Catalog tree\"\nlink \"Attributes 1 Attribute library\"\nlink \"Feeds 0 Import sources\"\nlink \"Credits Unlimited Enterprise · Billing\"\nheading \"Recent activity\" [level=2]\nlink \"View all\"\nheading \"Quick links\" [level=2]\nlink \"Feeds Import and map\"\nlink \"Products Browse and process\"\nlink \"Jobs Monitor tasks\"\nlink \"Exports Templates \u0026 download\"\nheading \"WHAT'S NEW\" [level=3]\nheading \"User Experience Improvements\" [level=3]\nheading \"Key Features:\" [level=4]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:08:31Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:08:31Z",
|
||||
"load_ms": 3676,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Switch user: Demo User · Platform Demo\"]",
|
||||
"role": "button",
|
||||
"name": "Switch user: Demo User · Platform Demo",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "a[aria-label=\"Support notifications, 1 unread\"]",
|
||||
"role": "link",
|
||||
"name": "Support notifications, 1 unread"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "div \u003e div \u003e header \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Open products",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "a[data-testid=\"store-reconnect-link-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "a[data-testid=\"store-reconnect-cta-woocommerce\"]",
|
||||
"role": "link",
|
||||
"name": "Reconnect WooCommerce"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div:nth-of-type(1) \u003e div \u003e div:nth-of-type(2) \u003e a \u003e button",
|
||||
"role": "button",
|
||||
"name": "Reconnect WooCommerce",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "1. Feeds Connect import"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "2. Products 5 in catalog"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "3. Process 8 done"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "div \u003e section:nth-of-type(1) \u003e ol \u003e li:nth-of-type(4) \u003e a",
|
||||
"role": "link",
|
||||
"name": "4. Export Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Products 5 8 processed · 0 unprocessed"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Categories 2 Catalog tree"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Attributes 1 Attribute library"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Feeds 0 Import sources"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(5)",
|
||||
"role": "link",
|
||||
"name": "Credits Unlimited Enterprise · Billing"
|
||||
},
|
||||
{
|
||||
"ref": "e20",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(1) \u003e div:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View all"
|
||||
},
|
||||
{
|
||||
"ref": "e21",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Feeds Import and map"
|
||||
},
|
||||
{
|
||||
"ref": "e22",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Products Browse and process"
|
||||
},
|
||||
{
|
||||
"ref": "e23",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Jobs Monitor tasks"
|
||||
},
|
||||
{
|
||||
"ref": "e24",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e section:nth-of-type(2) \u003e div:nth-of-type(2) \u003e a:nth-of-type(4)",
|
||||
"role": "link",
|
||||
"name": "Exports Templates \u0026 download"
|
||||
},
|
||||
{
|
||||
"ref": "e25",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e26",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e27",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e28",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e29",
|
||||
"selector": "button[aria-label=\"Open system assistant\"]",
|
||||
"role": "button",
|
||||
"name": "Open system assistant",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\13-nav-open-mobile.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Platform Demo 1 PLATFORM DEMO Platform Demo Unlimited Start \"\nbanner \"Platform Demo 1\"\nbutton \"Open navigation\"\nbutton \"Switch user: Demo User · Platform Demo\"\nlink \"Support notifications, 1 unread\"\nbutton \"Sign out\"\nbanner \"PLATFORM DEMO Platform Demo Unlimited Start tutorial Open pr\"\nheading \"Platform Demo\" [level=1]\nbutton \"Start tutorial\"\nbutton \"Open products\"\nstatus \"Reconnect store after migration Store API credentials were n\" [testid=store-reconnect-banner]\nlink \"WooCommerce\" [testid=store-reconnect-link-woocommerce]\nlink \"Reconnect WooCommerce\" [testid=store-reconnect-cta-woocommerce]\nbutton \"Reconnect WooCommerce\"\nheading \"Catalog workflow\" [level=2]\nlink \"1. Feeds Connect import\"\nlink \"2. Products 5 in catalog\"\nlink \"3. Process 8 done\"\nlink \"4. Export Templates \u0026 download\"\nheading \"Overview\" [level=2]\nlink \"Products 5 8 processed · 0 unprocessed\"\nlink \"Categories 2 Catalog tree\"\nlink \"Attributes 1 Attribute library\"\nlink \"Feeds 0 Import sources\"\nlink \"Credits Unlimited Enterprise · Billing\"\nheading \"Recent activity\" [level=2]\nlink \"View all\"\nheading \"Quick links\" [level=2]\nlink \"Feeds Import and map\"\nlink \"Products Browse and process\"\nlink \"Jobs Monitor tasks\"\nlink \"Exports Templates \u0026 download\"\nheading \"WHAT'S NEW\" [level=3]\nheading \"User Experience Improvements\" [level=3]\nheading \"Key Features:\" [level=4]\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"\nbutton \"Open system assistant\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 58 KiB |
@@ -1,206 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231500Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231500Z\\report.json",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\13-nav-open-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\13-nav-open-tablet.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260808T231500Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "header \u003e div \u003e div \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Loading… Loading…\"\nbanner \"Start tutorial Tour topics Sign out\"\nbutton \"Open navigation\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nbutton \"Sign out\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"action_log": [
|
||||
"step 1 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-08T23:15:00Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-08T23:15:00Z",
|
||||
"load_ms": 913,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#app-shell \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "button[aria-label=\"Open navigation\"]",
|
||||
"role": "button",
|
||||
"name": "Open navigation",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Start tutorial\"]",
|
||||
"role": "button",
|
||||
"name": "Start tutorial",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "button[aria-label=\"Browse tutorial sections\"]",
|
||||
"role": "button",
|
||||
"name": "Browse tutorial sections",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "header \u003e div \u003e div \u003e div \u003e button",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "#main-content \u003e header \u003e div \u003e div \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "button[aria-label=\"Sign out\"]",
|
||||
"role": "button",
|
||||
"name": "Sign out",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\13-nav-open-tablet.png",
|
||||
"snapshot": "link \"Skip to content\"\nmain \"Loading… Loading…\"\nbanner \"Start tutorial Tour topics Sign out\"\nbutton \"Open navigation\"\nbutton \"Start tutorial\"\nbutton \"Browse tutorial sections\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nbutton \"Sign out\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 31 KiB |
@@ -1,185 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Batch mobile/tablet screenshots with a reused codehelper browser session."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(r"F:\laragon\www\_MY\descrybe-v2")
|
||||
OUT = ROOT / "apps" / "web" / "static" / ".audit"
|
||||
BASE = "http://localhost:28472"
|
||||
|
||||
PAGES = [
|
||||
("02-login", "/login", True),
|
||||
("03-dashboard", "/dashboard", False),
|
||||
("04-settings", "/settings", False),
|
||||
("05-billing", "/billing", False),
|
||||
("06-support", "/support", False),
|
||||
("07-support-new", "/support/new", False),
|
||||
("08-admin", "/admin", False),
|
||||
("09-admin-billing", "/admin/billing", False),
|
||||
("10-admin-support", "/admin/support", False),
|
||||
("11-admin-users", "/admin/users", False),
|
||||
("12-admin-settings", "/admin/settings", False),
|
||||
]
|
||||
|
||||
|
||||
def run(cmd: list[str]) -> subprocess.CompletedProcess[str]:
|
||||
print(">", " ".join(cmd[:8]), "...")
|
||||
r = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if r.stdout:
|
||||
print(r.stdout[-2000:] if len(r.stdout) > 2000 else r.stdout)
|
||||
if r.stderr:
|
||||
print(r.stderr[-2000:] if len(r.stderr) > 2000 else r.stderr, file=sys.stderr)
|
||||
return r
|
||||
|
||||
|
||||
def main() -> int:
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
login_actions = json.dumps(
|
||||
[
|
||||
{"action": "wait_hydrate"},
|
||||
{
|
||||
"action": "fill",
|
||||
"selector": "input[type=email],input[name=email],#email",
|
||||
"text": "demo@descrybe.local",
|
||||
},
|
||||
{
|
||||
"action": "fill",
|
||||
"selector": "input[type=password],input[name=password],#password",
|
||||
"text": "DemoPass123!",
|
||||
},
|
||||
{"action": "click", "selector": "button[type=submit]"},
|
||||
{"action": "wait_nav"},
|
||||
{"action": "wait_hydrate"},
|
||||
{"action": "wait", "ms": 1500},
|
||||
# dismiss cookies if present
|
||||
{"action": "click", "selector": "button:has-text('Accept all'), [data-testid=cookie-consent-banner] button:nth-of-type(3)"},
|
||||
{"action": "wait", "ms": 500},
|
||||
]
|
||||
)
|
||||
|
||||
for device in ("mobile", "tablet"):
|
||||
session = f"audit-{device}"
|
||||
# login once per device
|
||||
r = run(
|
||||
[
|
||||
"codehelper",
|
||||
"browser",
|
||||
"test",
|
||||
f"{BASE}/login",
|
||||
"--device",
|
||||
device,
|
||||
"--format",
|
||||
"png",
|
||||
"--wait-hydrate",
|
||||
"--session",
|
||||
session,
|
||||
"--session-clear",
|
||||
"--actions",
|
||||
login_actions,
|
||||
"-o",
|
||||
str(OUT / f"00-post-login-{device}.png"),
|
||||
"--path",
|
||||
str(ROOT),
|
||||
]
|
||||
)
|
||||
if r.returncode != 0:
|
||||
print(f"login failed for {device}", file=sys.stderr)
|
||||
return r.returncode
|
||||
|
||||
for slug, path, public in PAGES:
|
||||
if path == "/login":
|
||||
# public unauth shot (separate short session not needed — skip for auth device)
|
||||
continue
|
||||
actions = json.dumps(
|
||||
[
|
||||
{"action": "navigate", "url": f"{BASE}{path}"},
|
||||
{"action": "wait_hydrate"},
|
||||
{"action": "wait", "ms": 1200},
|
||||
]
|
||||
)
|
||||
out = OUT / f"{slug}-{device}.png"
|
||||
r = run(
|
||||
[
|
||||
"codehelper",
|
||||
"browser",
|
||||
"test",
|
||||
f"{BASE}{path}",
|
||||
"--device",
|
||||
device,
|
||||
"--format",
|
||||
"png",
|
||||
"--wait-hydrate",
|
||||
"--session",
|
||||
session,
|
||||
"--actions",
|
||||
actions,
|
||||
"-o",
|
||||
str(out),
|
||||
"--path",
|
||||
str(ROOT),
|
||||
"--snapshot",
|
||||
]
|
||||
)
|
||||
print(f"{slug} {device} exit={r.returncode} -> {out.exists()}")
|
||||
|
||||
# nav open on dashboard
|
||||
nav_actions = json.dumps(
|
||||
[
|
||||
{"action": "navigate", "url": f"{BASE}/dashboard"},
|
||||
{"action": "wait_hydrate"},
|
||||
{"action": "click", "selector": 'button[aria-label="Open navigation"], [data-tour=nav-mobile-toggle]'},
|
||||
{"action": "wait", "ms": 800},
|
||||
]
|
||||
)
|
||||
r = run(
|
||||
[
|
||||
"codehelper",
|
||||
"browser",
|
||||
"test",
|
||||
f"{BASE}/dashboard",
|
||||
"--device",
|
||||
device,
|
||||
"--format",
|
||||
"png",
|
||||
"--wait-hydrate",
|
||||
"--session",
|
||||
session,
|
||||
"--actions",
|
||||
nav_actions,
|
||||
"-o",
|
||||
str(OUT / f"13-nav-open-{device}.png"),
|
||||
"--path",
|
||||
str(ROOT),
|
||||
]
|
||||
)
|
||||
print(f"nav-open {device} exit={r.returncode}")
|
||||
|
||||
# public login (no session)
|
||||
for device in ("mobile", "tablet"):
|
||||
run(
|
||||
[
|
||||
"codehelper",
|
||||
"browser",
|
||||
"test",
|
||||
f"{BASE}/login",
|
||||
"--device",
|
||||
device,
|
||||
"--format",
|
||||
"png",
|
||||
"--wait-hydrate",
|
||||
"-o",
|
||||
str(OUT / f"02-login-{device}.png"),
|
||||
"--path",
|
||||
str(ROOT),
|
||||
]
|
||||
)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,9 +0,0 @@
|
||||
[
|
||||
{"action": "wait_hydrate"},
|
||||
{"action": "fill", "selector": "input[type=email],input[name=email],#email", "text": "demo@descrybe.local"},
|
||||
{"action": "fill", "selector": "input[type=password],input[name=password],#password", "text": "DemoPass123!"},
|
||||
{"action": "click", "selector": "button[type=submit]"},
|
||||
{"action": "wait_nav"},
|
||||
{"action": "wait_hydrate"},
|
||||
{"action": "wait", "ms": 2000}
|
||||
]
|
||||
|
Before Width: | Height: | Size: 116 KiB |
@@ -1,304 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 2 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"actions_failed": true,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260809T081043Z",
|
||||
"debug_pack_json": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260809T081043Z\\report.json",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": null,
|
||||
"failure_pack": {
|
||||
"failed": true,
|
||||
"final_url": "http://localhost:28472/login",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\probe-consent.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\probe-consent.report.json",
|
||||
"pack_dir": "C:\\Users\\Green Eclipse\\.codehelper\\browser\\debug-packs\\20260809T081043Z",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": null,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#auth-shell \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "a[aria-label=\"Descrybe home\"]",
|
||||
"role": "link",
|
||||
"name": "Descrybe home"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Interface language: English\"]",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "button[aria-label=\"Switch to dark theme\"]",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "header \u003e div \u003e div \u003e div \u003e a",
|
||||
"role": "link",
|
||||
"name": "Demo Book a Demo"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "#email",
|
||||
"role": "textbox",
|
||||
"name": "Email",
|
||||
"type": "email"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "#password",
|
||||
"role": "textbox",
|
||||
"name": "Password",
|
||||
"type": "password"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e form \u003e button",
|
||||
"role": "button",
|
||||
"name": "Sign in",
|
||||
"type": "submit"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e p:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Create company"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e p:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Accept invite"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e p:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View pricing"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Privacy Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e button",
|
||||
"role": "button",
|
||||
"name": "Cookie settings",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Terms of Service"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"snapshot": "link \"Skip to content\"\nbanner \"Descrybe Demo\"\nlink \"Descrybe home\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Demo\"\nmain \"Sign in Use your Descrybe email and password. Email Password\"\nheading \"Sign in\" [level=1]\nform \"Email Password Sign in\"\ntextbox \"Email\"\ntextbox \"Password\"\nbutton \"Sign in\"\nlink \"Create company\"\nlink \"Accept invite\"\nlink \"View pricing\"\ncontentinfo \"Descrybe © 2026 Descrybe. All rights reserved. Privacy Polic\"\nnavigation \"Legal\"\nlink \"Privacy Policy\"\nlink \"Cookie Policy\"\nbutton \"Cookie settings\"\nlink \"Terms of Service\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"action_log": [
|
||||
"step 1 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 2 navigate — FAILED: navigate requires text=url"
|
||||
],
|
||||
"failure_shot": true,
|
||||
"generated_at": "2026-08-09T08:10:43Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/login",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-09T08:10:43Z",
|
||||
"load_ms": 1322,
|
||||
"outline": [
|
||||
{
|
||||
"ref": "e1",
|
||||
"selector": "#auth-shell \u003e div:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Skip to content"
|
||||
},
|
||||
{
|
||||
"ref": "e2",
|
||||
"selector": "a[aria-label=\"Descrybe home\"]",
|
||||
"role": "link",
|
||||
"name": "Descrybe home"
|
||||
},
|
||||
{
|
||||
"ref": "e3",
|
||||
"selector": "button[aria-label=\"Interface language: English\"]",
|
||||
"role": "button",
|
||||
"name": "Interface language: English",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e4",
|
||||
"selector": "button[aria-label=\"Switch to dark theme\"]",
|
||||
"role": "button",
|
||||
"name": "Switch to dark theme",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e5",
|
||||
"selector": "header \u003e div \u003e div \u003e div \u003e a",
|
||||
"role": "link",
|
||||
"name": "Demo Book a Demo"
|
||||
},
|
||||
{
|
||||
"ref": "e6",
|
||||
"selector": "#email",
|
||||
"role": "textbox",
|
||||
"name": "Email",
|
||||
"type": "email"
|
||||
},
|
||||
{
|
||||
"ref": "e7",
|
||||
"selector": "#password",
|
||||
"role": "textbox",
|
||||
"name": "Password",
|
||||
"type": "password"
|
||||
},
|
||||
{
|
||||
"ref": "e8",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e form \u003e button",
|
||||
"role": "button",
|
||||
"name": "Sign in",
|
||||
"type": "submit"
|
||||
},
|
||||
{
|
||||
"ref": "e9",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e p:nth-of-type(1) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Create company"
|
||||
},
|
||||
{
|
||||
"ref": "e10",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e p:nth-of-type(2) \u003e a",
|
||||
"role": "link",
|
||||
"name": "Accept invite"
|
||||
},
|
||||
{
|
||||
"ref": "e11",
|
||||
"selector": "div \u003e div \u003e div:nth-of-type(2) \u003e p:nth-of-type(3) \u003e a",
|
||||
"role": "link",
|
||||
"name": "View pricing"
|
||||
},
|
||||
{
|
||||
"ref": "e12",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e a:nth-of-type(1)",
|
||||
"role": "link",
|
||||
"name": "Privacy Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e13",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e a:nth-of-type(2)",
|
||||
"role": "link",
|
||||
"name": "Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e14",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e button",
|
||||
"role": "button",
|
||||
"name": "Cookie settings",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e15",
|
||||
"selector": "footer \u003e div \u003e div \u003e nav \u003e a:nth-of-type(3)",
|
||||
"role": "link",
|
||||
"name": "Terms of Service"
|
||||
},
|
||||
{
|
||||
"ref": "e16",
|
||||
"selector": "#cookie-consent-desc \u003e a",
|
||||
"role": "link",
|
||||
"name": "Read our Cookie Policy"
|
||||
},
|
||||
{
|
||||
"ref": "e17",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(1)",
|
||||
"role": "button",
|
||||
"name": "Customize",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e18",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(2)",
|
||||
"role": "button",
|
||||
"name": "Reject non-essential",
|
||||
"type": "button"
|
||||
},
|
||||
{
|
||||
"ref": "e19",
|
||||
"selector": "div \u003e div:nth-of-type(2) \u003e div \u003e div:nth-of-type(2) \u003e button:nth-of-type(3)",
|
||||
"role": "button",
|
||||
"name": "Accept all",
|
||||
"type": "button"
|
||||
}
|
||||
],
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\probe-consent.png",
|
||||
"snapshot": "link \"Skip to content\"\nbanner \"Descrybe Demo\"\nlink \"Descrybe home\"\nbutton \"Interface language: English\"\nbutton \"Switch to dark theme\"\nlink \"Demo\"\nmain \"Sign in Use your Descrybe email and password. Email Password\"\nheading \"Sign in\" [level=1]\nform \"Email Password Sign in\"\ntextbox \"Email\"\ntextbox \"Password\"\nbutton \"Sign in\"\nlink \"Create company\"\nlink \"Accept invite\"\nlink \"View pricing\"\ncontentinfo \"Descrybe © 2026 Descrybe. All rights reserved. Privacy Polic\"\nnavigation \"Legal\"\nlink \"Privacy Policy\"\nlink \"Cookie Policy\"\nbutton \"Cookie settings\"\nlink \"Terms of Service\"\ndialog \"Cookies and analytics We use necessary cookies to run Descry\" [testid=cookie-consent-banner]\nheading \"Cookies and analytics\" [level=2]\nlink \"Read our Cookie Policy\"\nbutton \"Customize\"\nbutton \"Reject non-essential\"\nbutton \"Accept all\"",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 111 KiB |
@@ -1,86 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 3 navigate http://localhost:28472/login — ok (http://localhost:28472/login)",
|
||||
"step 4 wait_hydrate — ok",
|
||||
"step 5 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 6 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 7 click button[type=submit] — ok",
|
||||
"step 8 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 9 wait_hydrate — ok",
|
||||
"step 10 wait 1500ms — ok"
|
||||
],
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-logged-in-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-logged-in-mobile.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 3 navigate http://localhost:28472/login — ok (http://localhost:28472/login)",
|
||||
"step 4 wait_hydrate — ok",
|
||||
"step 5 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 6 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 7 click button[type=submit] — ok",
|
||||
"step 8 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 9 wait_hydrate — ok",
|
||||
"step 10 wait 1500ms — ok"
|
||||
],
|
||||
"generated_at": "2026-08-09T08:11:21Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-09T08:11:21Z",
|
||||
"load_ms": 1752,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-logged-in-mobile.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 178 KiB |
@@ -1,86 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 3 navigate http://localhost:28472/login — ok (http://localhost:28472/login)",
|
||||
"step 4 wait_hydrate — ok",
|
||||
"step 5 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 6 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 7 click button[type=submit] — ok",
|
||||
"step 8 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 9 wait_hydrate — ok",
|
||||
"step 10 wait 1500ms — ok"
|
||||
],
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "tablet",
|
||||
"doc_status": 200,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "tablet",
|
||||
"viewport": "768x1024@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-logged-in-tablet.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-logged-in-tablet.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 3 navigate http://localhost:28472/login — ok (http://localhost:28472/login)",
|
||||
"step 4 wait_hydrate — ok",
|
||||
"step 5 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 6 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 7 click button[type=submit] — ok",
|
||||
"step 8 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 9 wait_hydrate — ok",
|
||||
"step 10 wait 1500ms — ok"
|
||||
],
|
||||
"generated_at": "2026-08-09T08:15:39Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-09T08:15:39Z",
|
||||
"load_ms": 6075,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-logged-in-tablet.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "768x1024@2x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 111 KiB |
@@ -1,86 +0,0 @@
|
||||
{
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 3 navigate http://localhost:28472/login — ok (http://localhost:28472/login)",
|
||||
"step 4 wait_hydrate — ok",
|
||||
"step 5 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 6 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 7 click button[type=submit] — ok",
|
||||
"step 8 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 9 wait_hydrate — ok",
|
||||
"step 10 wait 1200ms — ok"
|
||||
],
|
||||
"actions_failed": false,
|
||||
"console": [
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connecting..."
|
||||
},
|
||||
{
|
||||
"level": "debug",
|
||||
"text": "[vite] connected."
|
||||
}
|
||||
],
|
||||
"console_errors": [],
|
||||
"debug_pack_dir": "",
|
||||
"debug_pack_json": "",
|
||||
"device": "mobile",
|
||||
"doc_status": 200,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"failure_pack": {
|
||||
"failed": false,
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"title": "Descrybe",
|
||||
"doc_status": 200,
|
||||
"device": "mobile",
|
||||
"viewport": "390x844@2x",
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-mobile.png",
|
||||
"report_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-mobile.report.json",
|
||||
"console_errors": [],
|
||||
"page_errors": null,
|
||||
"failed_requests": [
|
||||
{
|
||||
"url": "http://localhost:28471/api/auth/me",
|
||||
"status": 401
|
||||
}
|
||||
],
|
||||
"action_log": [
|
||||
"step 1 wait_hydrate — ok",
|
||||
"step 2 storage_set descrybe-cookie-consent — ok (descrybe-cookie-consent)",
|
||||
"step 3 navigate http://localhost:28472/login — ok (http://localhost:28472/login)",
|
||||
"step 4 wait_hydrate — ok",
|
||||
"step 5 fill \"#email,input[type=email]\"=\"demo@descrybe.local\" — ok",
|
||||
"step 6 fill \"#password,input[type=password]\"=\"DemoPass123!\" — ok",
|
||||
"step 7 click button[type=submit] — ok",
|
||||
"step 8 wait_nav — ok (http://localhost:28472/login)",
|
||||
"step 9 wait_hydrate — ok",
|
||||
"step 10 wait 1200ms — ok"
|
||||
],
|
||||
"generated_at": "2026-08-09T08:13:06Z"
|
||||
},
|
||||
"final_url": "http://localhost:28472/dashboard",
|
||||
"format": "png",
|
||||
"generated_at": "2026-08-09T08:13:06Z",
|
||||
"load_ms": 1486,
|
||||
"outline": null,
|
||||
"page_errors": null,
|
||||
"screenshot_path": "F:\\laragon\\www\\_MY\\descrybe-v2\\apps\\web\\static\\.audit\\r00-mobile.png",
|
||||
"snapshot": "",
|
||||
"title": "Descrybe",
|
||||
"trace": null,
|
||||
"viewport": "390x844@2x"
|
||||
}
|
||||