Add RTF/Rich Text Editor to CustomUserCreationForm/CustomUserEditForm - django

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!

Related

Django {{data|escapejs}} from a js static file

I use {{data|escapejs}} django banner to import some data in my the javascript of my page.
Simple example :
<script>
console.log({{data|escapejs}})
</script>
But it doesn't work if I place this line in a .js static file
<script src = "{% static 'mycode.js' %}>
In mycode.js :
console.log({{data|escapejs}})
How to make it work ?
Okeeyy ... finally, it was easy.
<script>
var myvar = {{data|escapejs}}
</script>
<script src = "{% static 'mycode.js' %}">

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 %}

Django oembed URLs for embedded tweets

I have a list of a few hundred Twitter oembed URLs but I don't know how to implement the GET requests of a list of ids in a view.
Edited - OP was using URLS, not ids.
<div class="tweets">
{% for id in ids %}
<script language="JavaScript" type="text/javascript">
$(".tweets").append(<div id="tweet" tweetID={{ id }}>)
</script>
<script sync src="https://platform.twitter.com/widgets.js"></script>
<script>
window.onload = (function(){
var tweet = document.getElementById("tweet");
var id = tweet.getAttribute("tweetID");
twttr.widgets.createTweet(
id, tweet,
{
conversation : 'none', // or all
cards : 'hidden', // or visible
linkColor : '#cc5443', // default is blue
theme : 'light' // or dark
})
.then (function (el) {
el.contentDocument.querySelector(".footer").style.display = "none";
});
});
</script>
{% endfor %}
</div>
I'm trying to loop through a list of tweet ids and embed them. How do I make the JQuery loop through to create a div for each list item?
RapydML and Rapydscript
are what I was looking for. First, I created a nodeenv env. Now, I'm rewriting the above code in pythonic javascript and pythonic html.

How to get django_hitcount app working with Mezzanine blog

Been trying for several hours now.
I set up according to instructions but I can't get it to count hits on a blog post.
/blog/blog_post_detail.html
{% load .. .. .. hitcount_tags %}
.
.
.
.
{% block blog_post_detail_content %}
<script type="text/javascript">
$(document).ready(function() {
{% get_hit_count_javascript for blog_post %}
});
</script>
{% get_hit_count for blog_post %}
.
.
.
{% endblock %}
And in my urls.py I added:
url(r'^blog/ajax/hit/$', update_hit_count_ajax, name='hitcount_update_ajax'),
Looking at page source in browser the javascript does appear to run.
$(document).ready(function() {
var csrf = $('input[name=csrfmiddlewaretoken]').val();
$.post( '/blog/ajax/hit/',
{ csrfmiddlewaretoken: csrf, hitcount_pk : '1' },
function(data, status) {
if (data.status == 'error') {
// do something for error?
}
},
'json');
});
But it's not counting. So I'm not quite sure why it doesn't count a page hit.
Figured it out. In Mezzanine you have to put custom url patterns above the
("^", include("mezzanine.urls")),
pattern otherwise they will be ignored.

Play template don't evaluates a variable starting with #

Hello I will start by presenting my code.
#defining("addPostForm"){formId =>
#main("Add a blog post.") {
<h1>Add a blog post</h1>
#errors
#form(routes.Application.addPost, 'id -> "#formId") {
#inputText(name = "content", required = true)
<input type="submit" value="Create">
}
<script type="text/javascript">
$("##formId").validator();
</script>
}
}
Why is it that the #fromId in the #form won't be evaluated by play? This is a snippet of the generated html page.
<form action="/addPost" method="POST" id="#formId">
But later in the page it is working fine as this is generated.
<script type="text/javascript">
$("#addPostForm").validator();
</script>
I think it does not work because you already in a Scala code section, try this :
#form(routes.Application.addPost, 'id -> formId)
The later code is not included in a code section, so it works as expected.