Adonis.js WebSocket Room doen't get socket - adonis.js

I'm starting with Adonis.js framework and I don't undestand how works websocket service. I follow the documentation about this, and try to make a room.
I Let you see :
// app/Ws/Controllers/ChatController.js
'use strict'
class ChatController {
constructor (socket, request) {
this.socket = socket
this.request = request
}
* joinRoom (room) {
console.log(this.socket) <---- get undefined
}
}
module.exports = ChatController
// resources/views/welcome.njk
{% extends 'master' %}
{% block content %}
<script src="https://unpkg.com/adonis-websocket-
client#1.0.2/dist/ws.js" charset="utf-8"></script>
<script type="text/javascript">
const io = ws('', {})
const client = io.channel('chat').connect(console.log)
client.joinRoom('index', {}, console.log)
</script>
{% endblock %}
When I load the welcome page, I get "undefined" in console. I don't understand my mistake.
Thank's.
Beru

Hope I am not late.
Update adonis-websocket to 1.0.4 then in the controller modify:
* joinRoom (room, payload, socket) {
console.log(socket)
}
Payload is what you send as custom data:
client.joinRoom('index', {data}, console.log)
Hope it helps.
Let me know if you need any more clarifications.

Related

Django with Vue, detect form validation error

I have a Django ModelForm which is displayed in the template by using using crispy forms. After the user fills out the fields and presses a Submit button, an email is sent at the backend using Django's core send_email.
The problem is that the call to send_email is synchronous, so the user has to wait for the next page to load (success/failure page) but in this time the user might press the Submit button again and this generates multiple POSTs, making multiple emails.
I want to use Vue.js to make the button inactive once the user presses it but only if it passes Django's form validation. Is there a way to detect this?
Add to your button :disabled="!readyToSend" where readyToSend can be returned by your data function or a computed propoerty.
Before submitting the form set this variable to false, afater receiving data from your API, reset it to true.
In the following example I've choosen to make readyToSend a computed proporty where it will return true if the form is valid and if the process is not waiting for the API response.
The complete Code Pen example is here
html file :
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>example</title>
</head>
<body>
<div id="app">
<h2>{{ message }}</h2>
<form #submit.prevent>
<input type="text" v-model="dataToSend" placeholder="Something to send">
<button type="button" :disabled="!readyToSend" #click="send">Send</button>
</form>
</div>
</body>
</html>
javascript:
var vm = new Vue({
el: '#app',
data: function(){
return {
message: "please enter your message and click on send.",
dataToSend: "",
sentAndWaiting: false,
}
},
methods:{
send: async function(){
this.sentAndWaiting = true;
// Send Data Here
this.message = "sending....";
try{
let response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
let jsonResponse = await response.json();
}
catch(e){
this.message = e.message;
}
// reponse received ... do Something with it
this.reponseReceived();
},
reponseReceived: function(){
this.sentAndWaiting = false;
this.message = "Ok. Got The response.";
}
},
computed:{
readyToSend: function(){
return this.dataToSend.length > 0 && !this.sentAndWaiting;
}
},
});
in my browser I had to test this by going to the developper tools and limit my internet connexion to the GPRS and disabling cache:
Screenshot DevTools

In flask admin, add confirmation prompt when Save new record

Our users have the usual CRUD actions in various flask pages.
For one scenario, the Create action can be an intensive process, with lots of domain logic performed, and on occasion, items have been created accidentally.
Our users would now like to add a simple "Are you sure you want to create this Account?" prompt when they click the "Save" button. The next response would simply be Yes and No buttons.
It's not apparent how to add this - are we missing something obvious?
Override the Flask-Admin create template for the particular view and add a JavaScript confirmation to the form's onSubmit event. Adding the confirm to the submit event handles the three submit buttons; 'Save', 'Save and Add Another' and 'Save and Continue'.
For example:
class UserView(ModelView):
create_template = 'create_user.html'
# ...
In the /templates/admin folder add html file 'create_user.html':
{% extends 'admin/model/create.html' %}
{% block tail %}
{{ super() }}
<script src="{{ admin_static.url(filename='admin/js/helpers.js', v='1.0.0') }}" type="text/javascript"></script>
<script>
(function ($) {
$('form:first').on('submit', function() {
return faHelpers.safeConfirm('{{ _gettext('Are you sure you want to save this record?') }}');
});
})(jQuery);
</script>
{% endblock %}
Note there's a bug in Flask-Admin 1.5.3, helpers.js is missing from the distribution and you will need to add the safeConfirm function.
{% extends 'admin/model/create.html' %}
{% block tail %}
{{ super() }}
<script>
(function ($) {
function safeConfirm(msg) {
try {
var isconfirmed = confirm(msg);
if (isconfirmed == true) {
return true;
}
else {
return false;
}
}
catch (err) {
return false;
}
}
$('form:first').on('submit', function () {
return safeConfirm('{{ _gettext('Are you sure you want to save this record?') }}');
});
})(jQuery);
</script>
{% endblock %}

Simple Cognito User Authentication With Code Grant Not working

I am trying to create a simple static website that uses AWS Cognito to authenticate users. That means I'm not using any advanced libraries but basing my code on the AWS example here.
If I use the default 'token' flow then the example works for my domain. However, as recommended by Amazon themselves in several places e.g. here I want to used 'code grant' flow, and as state in the example above I just uncomment line 221:
auth.useCodeGrantFlow();
However this fails causing the onFailure function to be called although oddly I do see the URL bar containing code=xxxxx. It appears there are more steps I need to do but all examples I find demonstrate the less favourable 'token flow'.
This is my specific index.html based on the above example:
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Cognito Auth JS SDK Sample</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="stylesheets/styleSheetStart.css">
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="dist/amazon-cognito-auth.min.js"></script>
<!-- To enable the advanced security feature -->
<!-- <script src="https://amazon-cognito-assets.<region>.amazoncognito.com/amazon-cognito-advanced-security-data.min.js">
</script> -->
<!-- E.g. -->
<!-- <script src="https://amazon-cognito-assets.us-east-1.amazoncognito.com/amazon-cognito-advanced-security-data.min.js">
</script> -->
</head>
<body onload="onLoad()">
<ul>
<li><a href="https://aws.amazon.com/cognito/" target="_blank"
title="Go to AWS Cognito Console">Cognito Console</a></li>
<li><a href="http://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html"
target="_blank" title="See Cognito developer docs">Docs</a>
</li>
</ul>
<h1>
<a href="http://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html" target="_blank">
<img src="img/MobileServices_AmazonCognito.png" alt="Amazon Cognito" title="Amazon Cognito"
style="width:144px;height:144px;"></a><br>
Amazon Cognito Auth Demo
</h1>
<!--removed for brevity -->
<div><br></div>
<div>
<p id="statusNotAuth" title="Status">
Sign-In to Continue
</p>
<p id="statusAuth" title="Status">
You have Signed-In
</p>
</div>
<div class="tabsWell">
<div id="startButtons">
<div class="button">
<a class="nav-tabs" id="signInButton" href="javascript:void(0)" title="Sign in">Sign In</a>
</div>
</div>
<div class="tab-content">
<div class="tab-pane" id="userdetails">
<p class="text-icon" title="Minimize" id="tabIcon" onclick="toggleTab('usertab');">_</p>
<br>
<h2 id="usertabtitle">Tokens</h2>
<div class="user-form" id="usertab">
<pre id="idtoken"> ... </pre>
<pre id="acctoken"> ... </pre>
<pre id="reftoken"> ... </pre>
</div>
</div>
</div>
</div>
<script>
// Operations when the web page is loaded.
function onLoad() {
var i, items, tabs;
items = document.getElementsByClassName("tab-pane");
for (i = 0; i < items.length; i++) {
items[i].style.display = 'none';
}
document.getElementById("statusNotAuth").style.display = 'block';
document.getElementById("statusAuth").style.display = 'none';
// Initiatlize CognitoAuth object
var auth = initCognitoSDK();
document.getElementById("signInButton").addEventListener("click",
function() {
userButton(auth);
});
var curUrl = window.location.href;
auth.parseCognitoWebResponse(curUrl);
}
// Operation when tab is closed.
function closeTab(tabName) {
document.getElementById(tabName).style.display = 'none';
}
// Operation when tab is opened.
function openTab(tabName) {
document.getElementById(tabName).style.display = 'block';
}
// Operations about toggle tab.
function toggleTab(tabName) {
if (document.getElementById("usertab").style.display == 'none') {
document.getElementById("usertab").style.display = 'block';
document.getElementById("tabIcon").innerHTML = '_';
} else {
document.getElementById("usertab").style.display = 'none';
document.getElementById("tabIcon").innerHTML = '+';
}
}
// Operations when showing message.
function showMessage(msgTitle, msgText, msgDetail) {
var msgTab = document.getElementById('message');
document.getElementById('messageTitle').innerHTML = msgTitle;
document.getElementById('messageText').innerHTML = msgText;
document.getElementById('messageDetail').innerHTML = msgDetail;
msgTab.style.display = "block";
}
// Perform user operations.
function userButton(auth) {
var state = document.getElementById('signInButton').innerHTML;
if (state === "Sign Out") {
document.getElementById("signInButton").innerHTML = "Sign In";
auth.signOut();
showSignedOut();
} else {
auth.getSession();
}
}
// Operations when signed in.
function showSignedIn(session) {
document.getElementById("statusNotAuth").style.display = 'none';
document.getElementById("statusAuth").style.display = 'block';
document.getElementById("signInButton").innerHTML = "Sign Out";
/* Removed for brevity */
openTab("userdetails");
}
// Operations when signed out.
function showSignedOut() {
document.getElementById("statusNotAuth").style.display = 'block';
document.getElementById("statusAuth").style.display = 'none';
document.getElementById('idtoken').innerHTML = " ... ";
document.getElementById('acctoken').innerHTML = " ... ";
document.getElementById('reftoken').innerHTML = " ... ";
closeTab("userdetails");
}
// Initialize a cognito auth object.
function initCognitoSDK() {
var authData = {
ClientId : '<Removed>', // Your client id here
AppWebDomain : '<Removed>', // Exclude the "https://" part.
TokenScopesArray : [<removed>], // like ['openid','email','phone']...
RedirectUriSignIn : '<domain removed>/index.html',
RedirectUriSignOut : '<domain removed>/index.html'
};
var auth = new AmazonCognitoIdentity.CognitoAuth(authData);
// You can also set state parameter - do I need to set this?
auth.setState('ABCDXYZ');
auth.userhandler = {
onSuccess: function(result) {
alert("Sign in success");
showSignedIn(result);
},
onFailure: function(err) {
alert("Error!" + err);
}
};
// The default response_type is "token", uncomment the next line will make it be "code".
auth.useCodeGrantFlow();
return auth;
}
</script>
</body>
</html>
In dev tools I do see a call to https://<domain-name-removed>/oauth2/token but looks like it comes back with a 400 error.The response text is "error":"invalid_client".
Is there some additional configuration I need to do, or as suggested in the AWS docs for authorisation code grant flow I need to implement additional BE code? I feel the example code is lacking a full description for code grant flow.
According to
It turns out that when I created the the app client for the user pool I created it with a secret key. This key must be returned in the header as part of the authentication process which I wasn't doing; the aws example doesn't indicate how this is achieved. Instead direction is given to create the app client without an app secret key
If I understand your use case correctly you should not use an app client secret for this. The AWS example is indeed correct, the code you get in the url is meant to be used in another request in the process of acquiring the real code aka access_token.

Add RTF/Rich Text Editor to CustomUserCreationForm/CustomUserEditForm

I try to extend my custom User model as described here.
This works fine for the shown fields like ModelChoiceField and CharField.
My goal now is to add a RTF field (the control like the one shown in the Page model). I have looked through the source code of wagtail and found the method get_rich_text_editor_widget which is being used in conjunction with a CharField. Sadly I get a JavaScript error:
Uncaught TypeError: Cannot read property 'initEditor' of undefined
My guess now is that I somehow need to include or modify a hook for the widget. Or is it sufficient to override the JavaScript block in a template? It feels a bit hacky right now and I am stuck with including the required JS, that's why I am posting the question. Maybe I am missing something trivial.
# ...
from wagtail.admin.rich_text import get_rich_text_editor_widget
class CustomUserEditForm(UserEditForm):
position = forms.ModelChoiceField(queryset=Position.objects, required=True, label=_('Position'))
# biography = forms.Textarea()
biography = forms.CharField(widget=get_rich_text_editor_widget())
Update:
Updating my template (maybe not the right approach):
{% block js %}
{{ block.super }}
<script type="text/javascript" src="/static/wagtailadmin/js/draftail.js"></script>
{% endblock js %}
Results in:
I've written my solution up as an issue for draftail
https://github.com/springload/draftail/issues/450
I've got a wagtail site with this awesome RichText Editor (called Draftail) but trying to use it on a non Wagtail Admin page makes me feel dirty. I wanted a biography field that people could write about themselves and I wanted the blog authors to be able to use it as well. BUT to do that I've had to do some things that make me cringe.
Not bad:
{% block extra_css %}
<link href="{% static 'wagtailadmin/css/panels/draftail.css' %}" type="text/css" media="all" rel="stylesheet">
{% endblock extra_css %}
WTF???? why aren't we just using Favicons for things like Bold
<div data-sprite></div>
<script>
function loadIconSprite() {
var spriteURL = '{% url "wagtailadmin_sprite" %}';
var revisionKey = 'wagtail:spriteRevision';
var dataKey = 'wagtail:spriteData';
var isLocalStorage = 'localStorage' in window && typeof window.localStorage !== 'undefined';
var insertIt = function (data) {
var spriteContainer = document.body.querySelector('[data-sprite]');
spriteContainer.innerHTML = data;
}
var insert = function (data) {
if (document.body) {
insertIt(data)
} else {
document.addEventListener('DOMContentLoaded', insertIt.bind(null, data));
}
}
if (isLocalStorage && localStorage.getItem(revisionKey) === spriteURL) {
var data = localStorage.getItem(dataKey);
if (data) {
insert(data);
return true;
}
}
try {
var request = new XMLHttpRequest();
request.open('GET', spriteURL, true);
request.onload = function () {
if (request.status >= 200 && request.status < 400) {
data = request.responseText;
insert(data);
if (isLocalStorage) {
localStorage.setItem(dataKey, data);
localStorage.setItem(revisionKey, spriteURL);
}
}
}
request.send();
} catch (e) {
console.error(e);
}
}
loadIconSprite();
</script>
Because wagtail comments.js somehow needs wagtailConfig.ADMIN_API and draftail won't initialize without comments.js
<script>
(function(document, window) {
window.wagtailConfig = window.wagtailConfig || {};
wagtailConfig.ADMIN_API = {
PAGES: '',
DOCUMENTS: '',
IMAGES: '',
{# // Use this to add an extra query string on all API requests. #}
{# // Example value: '&order=-id' #}
EXTRA_CHILDREN_PARAMETERS: '',
};
{% i18n_enabled as i18n_enabled %}
{% locales as locales %}
wagtailConfig.I18N_ENABLED = {% if i18n_enabled %}true{% else %}false{% endif %};
wagtailConfig.LOCALES = {{ locales|safe }};
wagtailConfig.STRINGS = {% js_translation_strings %};
wagtailConfig.ADMIN_URLS = {
PAGES: ''
};
})(document, window);
</script>
<script src="{% static 'wagtailadmin/js/vendor/jquery-3.5.1.min.js' %}"></script>
<!-- <script src="{% static 'wagtailadmin/js/core.js' %}"></script> strangely not needed -->
<script src="{% static 'wagtailadmin/js/vendor.js' %}"></script>
<script src="{% static 'wagtailadmin/js/comments.js' %}"></script>
{{ form.media.js }}
All of this just to get the draftail editor on a non wagtail admin page!

how to load correctly addthis widget js?

I'm development a blog using django and I have included the addthis tool for include the share buttons. I'm including the addthis buttons in the posts detail page. I need to get the facebook shares count for the current blog post deetail. I'm using these steps, but I'm gettin this error in the console: ReferenceError: addthis is not defined.
The addthis code is loaded remotely then, I think that my js is not running because it runs before the addthis script load is complete. How can I fix it?
{% block js %}
<script type="text/javascript"src="//s7.addthis.com/js/300/addthis_widget.js#pubid=fdfs" async="async"></script>
<script src="{% static 'js/blog/blog_list.js' %}"></script>
<script>
$(function () {
addthis.sharecounters.getShareCounts('facebook', function(obj) {
console.log(obj);
});
})
</script>
{% endblock %}
You can wrap your function around window.load like below
$(window).load(function() {
addthis.sharecounters.getShareCounts('facebook', function(obj) {
console.log(obj);
});
})
This will ensure that the code will get executed once entire window is loaded. For further reading read this.