ich möchte das Popup-Fenster über die Theme-Komponente anzeigen, wenn sich ein Benutzer zum ersten Mal anmeldet.
1. Ich habe versucht, die Login-Aktion des Login-Controllers mit der Theme-Komponente zu überschreiben, um das Popup-Fenster nach einer erfolgreichen Anmeldung anzuzeigen. In der Login-Aktion habe ich den Code bootbox.alert(“Test Alert”); vor hiddenLoginForm.submit(); eingefügt.
Das Popup wird jedoch erst angezeigt, nachdem hiddenLoginForm abgesendet wurde und die Weiterleitung zur Startseite erfolgt ist.
Mein Ziel ist es, dass das Popup-Fenster erst nach der Weiterleitung zur Startseite nach erfolgreicher Anmeldung angezeigt wird.
2. Um zu prüfen, ob sich ein Benutzer zum ersten Mal anmeldet, habe ich versucht, den Wert der Eigenschaft previous_visit_at des aktuellen Benutzers zu überprüfen. Wenn previous_visit_at = null ist (d. h. der Benutzer meldet sich zum ersten Mal an), sollte dies der Fall sein. Doch auch hier schlägt mein Test fehl: Wenn ich mich ein zweites Mal anmelde, ist der Wert der Eigenschaft previous_visit_at weiterhin null. Ich möchte wissen, wann genau der Wert der Eigenschaft previous_visit_at aktualisiert wird.
Bitte helfen Sie mir, die oben genannten Anforderungen umzusetzen.
Ich würde davon abraten, dies auf diese Weise zu tun; Login ist eine der kritischsten Aktionen, und jegliche Überschreibungen dieser Aktion sind fragil und anfällig für Fehler, falls wir Änderungen im Kernbereich vornehmen.
Wenn du dich erinnerst, hast du beim ersten Registrieren auf dieser Seite etwas wie folgendes gesehen.
Wenn du also dieselben Bedingungen in einem Initialisierer verwendest, kannst du ein Bootbox beim allerersten Seitenaufruf des Benutzers nach dem Login rendern.
Du kannst etwas Ähnliches in deiner Theme-Komponente ausprobieren:
import { withPluginApi } from "discourse/lib/plugin-api";
import bootbox from "bootbox";
export default {
name: "first-login-bootbox",
initialize() {
withPluginApi("0.8", api => {
const user = api.getCurrentUser();
if (!user) return;
if (!user.read_first_notification && !user.enforcedSecondFactor) {
const text = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor`;
bootbox.alert(text);
}
});
}
};
Du kannst bei Bedarf HTML im Text des Bootbox verwenden. Sobald der Benutzer das Bootbox schließt und auf das eingekreiste Avatar-Bild klickt, wird er das Bootbox nie wieder sehen.
Bitte beachte, dass Bootboxes für einfache Dialoge/Bestätigungen gedacht sind. Wenn du etwas etwas Komplexeres benötigst, ist es wahrscheinlich besser, ein Modal mit showModal() zu verwenden.
Hallo, @Johani, ich habe einen einfachen Hyperlink (z. B. “/new-topic”) in das Popup-Fenster eingefügt, der sich in einem neuen Tab öffnet.
Wenn ich auf diesen Link klicke, öffnet er sich zwar in einem neuen Tab, aber es wird erneut ein Popup-Fenster angezeigt, da wir die folgenden Bedingungen geprüft haben:
Diese Eigenschaften haben keine Setter; selbst wenn sie welche hätten, würden Ihre Änderungen nur vorübergehend im ersten Fenster gelten. Sobald der Benutzer den zweiten Tab aufruft, basieren die Daten auf dem, was in der Datenbank gespeichert ist. Themes haben keinen Zugriff auf das Backend; sie können nur das Frontend ändern.
Was Sie tun können, ist, einen Hash zu Ihrem Link hinzuzufügen und diesen wie folgt zu prüfen.
import { withPluginApi } from "discourse/lib/plugin-api";
import bootbox from "bootbox";
export default {
name: "first-login-bootbox",
initialize() {
withPluginApi("0.8", api => {
const user = api.getCurrentUser();
if (!user) return;
if (
!user.read_first_notification &&
!user.enforcedSecondFactor &&
!window.location.hash
) {
const text = `Lorem ipsum dolor sit amet <a href="http://localhost:3000/new-topic#some-hash" target="_blank">Link</a>, consectetur adipiscing elit, sed do eiusmod tempor`;
bootbox.alert(text);
}
});
}
};
Ich bin mir nicht sicher, ob der Link zu „/new-topic
Ich möchte Links wie “/new-topic” und “/my/preferences” innerhalb eines Popups anzeigen.
Ansonsten habe ich überlegt, das Popup nur auf der Startseite anzuzeigen, indem ich die aktuelle URL überprüfe.
Beim Besuch anderer Seiten wird das Popup also nicht angezeigt.
Können wir ein Widget wie unten gezeigt erstellen und darin bootbox() aufrufen?
Und können wir nach dem Aufruf von bootbox die Methode “skipNewUserTips()” aufrufen, die auch von Discourse im header-notifications-Widget verwendet wird.
<script type="text/discourse-plugin" version="0.8">
const { h } = require('virtual-dom');
const { ajax } = require("discourse/lib/ajax").default;
const DiscourseURL = require("discourse/lib/url");
const { userPath } = require("discourse/lib/url");
api.createWidget("welcome-popup", {
tagName: "div.welcome-popup",
html(attrs) {
let user = this.currentUser;
if (!user) return;
if (
!user.get("read_first_notification") &&
!user.get("enforcedSecondFactor")
) {
const title = `<div class="first-login-bootbox-title">You're a member. Welcome aboard!</div>`;
const body = `<div class="first-login-bootbox-body">Now you can: </br> <ol class="user-suggestions"><li><a href="/new-topic" target="_blank" >Ask a question or start a discussion</a></li> <li><a href="/my/preferences/tags" target="_blank">Set up your notification settings</a></li></ol></div>`;
bootbox.alert({
title: title,
message: body
});
this.skipNewUserTips();
}
return null;
},
skipNewUserTips() {
ajax(userPath(this.currentUser.username_lower), {
type: "PUT",
data: {
skip_new_user_tips: true,
},
}).then(() => {
this.currentUser.set("skip_new_user_tips", true);
});
},
});
</script>
<script
type="text/x-handlebars"
data-template-name="/connectors/below-site-header/welcome-popup"
>
{{mount-widget widget="welcome-popup"}}
</script>
Diese Optionen wurden zu neueren Versionen von Bootbox hinzugefügt und funktionieren nicht mit der Version, die wir derzeit in Discourse verwenden (wir diskutieren dies intern, aber vorerst kannst du sie nicht verwenden).
Da du außerdem eine PUT-Anfrage erstellst, kannst du dies ebenfalls überspringen.
this.currentUser.set("skip_new_user_tips", true);
Also vielleicht so etwas wie das hier.
api.createWidget("welcome-popup", {
tagName: "div.welcome-popup",
html(attrs) {
let user = this.currentUser;
if (!user) return;
if (
!user.get("read_first_notification") &&
!user.get("enforcedSecondFactor")
) {
const body = `<h2 class="first-login-bootbox-title">Du bist ein Mitglied. Willkommen an Bord!</h2>
<hr>
<div class="first-login-bootbox-body">
Jetzt kannst du:
<br>
<ol class="user-suggestions">
<li>
<a href="/new-topic" target="_blank"
>Eine Frage stellen oder eine Diskussion starten</a
>
</li>
<li>
<a href="/my/preferences/tags" target="_blank"
>Deine Benachrichtigungseinstellungen einrichten</a
>
</li>
</ol>
</div>`;
bootbox.alert(body);
this.skipNewUserTips();
}
return null;
},
skipNewUserTips() {
ajax(userPath(this.currentUser.username_lower), {
type: "PUT",
data: {
skip_new_user_tips: true
}
});
}
});
Da wir skip_new_user_tips auf true gesetzt haben, wird auch die Discobot-Gruß-Benachrichtigung übersprungen. Es ist in Ordnung, wenn die erste Benachrichtigungs-Overlay-Maske nicht angezeigt wird, aber wir möchten die Discobot-Gruß-Benachrichtigung.
Deshalb haben wir den Code so geändert, dass die Discobot-Gruß-Benachrichtigung für alle neuen Benutzer geladen wird.
Jetzt haben wir eine neue Methode zum Header-Widget hinzugefügt: “closeFirstNotificationMask()”, bei der wir “ringBackdrop” auf false und “userVisible” auf das Gegenteil davon setzen. Diese Methode rufen wir auf, nachdem wir die bootbox-Methode im welcome-popup-Widget aufgerufen haben.
Wir haben uns dabei an der “toggleUserMenu”-Methode des Header-Widgets orientiert, die aufgerufen wird, wenn auf das Benutzer-Symbol geklickt wird.
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.1/bootbox.min.js" integrity="sha512-eoo3vw71DUo5NRvDXP/26LFXjSFE1n5GQ+jZJhHz+oOTR4Bwt7QBCjsgGvuVMQUMMMqeEvKrQrNEI4xQMXp3uA==" crossorigin="anonymous"></script>
<script type="text/discourse-plugin" version="0.8">
const { h } = require('virtual-dom');
const { ajax } = require("discourse/lib/ajax").default;
/* Neue Methode zum Header-Widget hinzufügen, die nach der Anzeige des Welcome-Popups aufgerufen wird */
api.reopenWidget("header",{
closeFirstNotificationMask() {
this.state.ringBackdrop = false;
this.state.userVisible = !this.state.userVisible;
this.toggleBodyScrolling(this.state.userVisible);
}
});
/* Neues Widget "welcome-popup" erstellen; dieses Widget wird nur gerendert, wenn der Benutzer sich zum ersten Mal anmeldet */
api.createWidget("welcome-popup", {
tagName: "div.welcome-popup",
html(attrs) {
let user = this.currentUser;
if (!user) return;
if ( !user.get("read_first_notification") && !user.get("enforcedSecondFactor") ) {
const title = `<div class="first-login-bootbox-title">Sie sind jetzt Mitglied. Herzlich willkommen!</div>`;
const body = `<div class="first-login-bootbox-body">Jetzt können Sie: </br> <ol class="user-suggestions"><li><a href="/new-topic" target="_blank">Eine Frage stellen oder eine Diskussion starten</a></li> <li><a href="/my/preferences/tags" target="_blank">Ihre Benachrichtigungseinstellungen konfigurieren</a></li></ol></div>`;
bootbox.alert({
title: title,
message: body
});
// Aufruf der closeFirstNotificationMask-Aktionsmethode des Header-Widgets
this.sendWidgetAction("closeFirstNotificationMask", this.attrs);
}
return null;
},
});
/* Der folgende Code rendert das "welcome-popup"-Widget nach dem Rendern des "header-notifications"-Widgets, wenn sich der Benutzer zum ersten Mal anmeldet */
api.decorateWidget("header-notifications:after", helper => {
if(!helper.attrs.active && helper.attrs.ringBackdrop){
return helper.attach("welcome-popup", helper.attrs);
}else{
return null;
}
});
</script>
Noch eine Sache: Wir verwenden die Bootbox-Version 5.4.1, indem wir das folgende Skript in unsere Theme-Komponente einbinden, da Discourse derzeit die bootbox-Methode mit mehreren Parametern nicht unterstützt. Ist das in Ordnung?
Ich habe es lokal getestet und keine Probleme festgestellt. Ich habe ein paar kleinere Änderungen vorgenommen.
<script
src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.1/bootbox.min.js"
integrity="sha512-eoo3vw71DUo5NRvDXP/26LFXjSFE1n5GQ+jZJhHz+oOTR4Bwt7QBCjsgGvuVMQUMMMqeEvKrQrNEI4xQMXp3uA=="
crossorigin="anonymous"
></script>
<script type="text/discourse-plugin" version="0.8">
const user = api.getCurrentUser();
if (!user || user.read_first_notification || user.enforcedSecondFactor) {
return;
}
const bootboxTitle = `<div class="first-login-bootbox-title">Du bist jetzt dabei. Willkommen an Bord!</div>`;
const bootboxBody = `<div class="first-login-bootbox-body">Jetzt kannst du: </br> <ol class="user-suggestions"><li><a href="/new-topic" target="_blank ">Eine Frage stellen oder eine Diskussion starten</a></li> <li><a href="/my/preferences/tags" target="_blank">Deine Benachrichtigungseinstellungen konfigurieren</a></li></ol></div>`;
/* Neue Methode zum Header-Widget hinzufügen, die nach Anzeige des Willkommens-Popups aufgerufen wird */
api.reopenWidget("header", {
closeFirstNotificationMask() {
this.state.ringBackdrop = false;
this.state.userVisible = !this.state.userVisible;
}
});
/* Neues Widget "welcome-popup" erstellt. Dieses Widget wird nur gerendert, wenn sich der Benutzer zum ersten Mal anmeldet */
api.createWidget("welcome-popup", {
tagName: "div.welcome-popup",
html(attrs) {
// Aufruf der closeFirstNotificationMask-Aktionsmethode des Header-Widgets
this.sendWidgetAction("closeFirstNotificationMask", attrs);
bootbox.alert({
title: bootboxTitle,
message: bootboxBody
});
}
});
/* Der folgende Code rendert das "welcome-popup"-Widget nach dem Rendern des "header-notifications"-Widgets, wenn sich der Benutzer zum ersten Mal anmeldet */
api.decorateWidget("header-notifications:before", helper => {
if (!helper.attrs.active && helper.attrs.ringBackdrop) {
return helper.attach("welcome-popup", helper.attrs);
}
});
</script>
Ja, das ist in Ordnung. Discourse lädt die von uns verwendete Bootbox-Version als Shim, sodass das Laden einer anderen Version in deiner Theme-Komponente nichts am Kern ändert. Die neue Version wird nur in deiner Theme-Komponente verwendet. Der einzige Nachteil ist, dass dies eine zusätzliche Anfrage hinzufügt und etwa 4 KB zur initialen Seitenladung beiträgt.
Hallo @Johani, da du das Widget welcome-popup vor dem Widget header-notifications geladen hast, scheint es, dass die Discobot-Benachrichtigung nicht geladen wird. Zudem wird nach dem Klicken auf die Links innerhalb von welcome-popup erneut das welcome-popup für den Benutzer angezeigt.
Ich habe es getestet, indem ich das Widget welcome-popup nach dem Widget header-notifications geladen habe; das funktioniert einwandfrei. Kann ich es also in “header-notifications:after” ändern?
Ich habe den gleichen Code gerade erneut mit drei verschiedenen neuen Benutzern ausprobiert und jedes Mal das erwartete Ergebnis erhalten. Ich sehe das Popup beim ersten Seitenaufruf, und die Discobot-Begrüßungsnachricht wird gesendet. Bei nachfolgenden Seitenaufrufen erscheint das Popup nicht.
Klar, wenn es bei dir funktioniert, sollte der Dekorationsort keine Rolle spielen.