Alright, this is much better! Client side javascript much cleaner, plus the

templates are now truly recursive! Moving on to implementing the server side
code.
main
Jaap Joris Vens 2020-03-10 15:17:46 +01:00
rodzic 3cabdda617
commit e47d35a578
6 zmienionych plików z 188 dodań i 173 usunięć

Wyświetl plik

@ -262,24 +262,26 @@ section.contact {
/* Form elements */ /* Form elements */
form.cms { form.cms {
margin-bottom: 3em; //margin: 0.5em auto;
div.wrapper {
overflow: hidden;
}
section { div.wrapper {
margin-top: 3em; margin: 0 auto;
padding: 0 0.5em;
} }
fieldset { fieldset {
padding: 2em; border: 0.5px solid #ccc;
margin-bottom: 2em; clear: both;
border: 0.5px solid black; margin: 0.5em 0em;
border-radius: 3px; padding: 0.5em;
border-radius: 0.25em;
}
legend { img {
font-size: 1.15em; display: block;
} clear: both;
width: 50px;
cursor: pointer;
} }
div.formfield { div.formfield {

Wyświetl plik

@ -183,97 +183,115 @@ section.contact div#message {
display: none; } display: none; }
/* Form elements */ /* Form elements */
form.cms { form.cms div.wrapper {
margin-bottom: 3em; } margin: 0 auto;
form.cms div.wrapper { padding: 0 0.5em; }
overflow: hidden; }
form.cms section { form.cms fieldset {
margin-top: 3em; } border: 0.5px solid #ccc;
form.cms fieldset { clear: both;
padding: 2em; margin: 0.5em 0em;
margin-bottom: 2em; padding: 0.5em;
border: 0.5px solid black; border-radius: 0.25em; }
border-radius: 3px; }
form.cms fieldset legend { form.cms img {
font-size: 1.15em; } display: block;
form.cms div.formfield { clear: both;
margin-bottom: 10px; width: 50px;
clear: both; cursor: pointer; }
box-sizing: border-box; }
form.cms div.formfield.type, form.cms div.formfield.number, form.cms div.formfield.slug { form.cms div.formfield {
width: 77%; margin-bottom: 10px;
clear: none; clear: both;
float: left; } box-sizing: border-box; }
form.cms div.formfield.number { form.cms div.formfield.type, form.cms div.formfield.number, form.cms div.formfield.slug {
width: 20%; width: 77%;
float: right; } clear: none;
form.cms div.formfield.error { float: left; }
border: 2px dotted red; form.cms div.formfield.number {
padding: 10px; width: 20%;
margin: 10px -10px; float: right; }
background: #f001; }
form.cms div.formfield.required div.label { form.cms div.formfield.error {
font-weight: 700; } border: 2px dotted red;
form.cms div.label, form.cms label { padding: 10px;
font-size: 0.7rem; margin: 10px -10px;
font-weight: 400; background: #f001; }
text-align: left;
margin-bottom: 2px; } form.cms div.formfield.required div.label {
form.cms div.input { font-weight: 700; }
overflow: hidden; }
form.cms div.helptext, form.cms span.required { form.cms div.label, form.cms label {
color: #666; font-size: 0.7rem;
font-size: 12px !important; font-weight: 400;
font-weight: 400 !important; } text-align: left;
form.cms span.required { margin-bottom: 2px; }
font-style: italic; }
form.cms input, form.cms select, form.cms textarea { form.cms div.input {
background: white; overflow: hidden; }
color: black;
border: 0.5px solid #ccc; form.cms div.helptext, form.cms span.required {
border-radius: 3px; color: #666;
font-size: 1rem; font-size: 12px !important;
display: block; font-weight: 400 !important; }
width: 100%;
box-sizing: border-box; form.cms span.required {
font-style: italic; }
form.cms input, form.cms select, form.cms textarea {
background: white;
color: black;
border: 0.5px solid #ccc;
border-radius: 3px;
font-size: 1rem;
display: block;
width: 100%;
box-sizing: border-box;
margin: 0;
padding: 5px 8px;
font-family: inherit; }
form.cms input[type=checkbox] {
width: auto;
display: inline-block;
vertical-align: middle; }
form.cms input[name$=title] {
font-weight: bold; }
form.cms textarea {
font-size: 1rem;
height: 15em;
line-height: 1.5; }
form.cms select {
background: white;
padding-left: 3px; }
form.cms ul.errorlist {
margin: 0;
margin-bottom: 1em;
padding: 0;
list-style: none;
color: red;
font-size: 12px; }
form.cms ul.errorlist li {
margin: 0; margin: 0;
padding: 5px 8px; padding: 0; }
font-family: inherit; }
form.cms input[type=checkbox] { form.cms div.global_error {
width: auto; border: 2px dotted red;
display: inline-block; padding: 10px;
vertical-align: middle; } margin: 1em -10px;
form.cms input[name$=title] { background: #f001;
font-weight: bold; } color: red;
form.cms textarea { font-weight: bold; }
font-size: 1rem; form.cms div.global_error ul.errorlist {
height: 15em;
line-height: 1.5; }
form.cms select {
background: white;
padding-left: 3px; }
form.cms ul.errorlist {
margin: 0; margin: 0;
margin-bottom: 1em; font-size: inherit; }
padding: 0;
list-style: none; form.cms .errors {
color: red; color: red;
font-size: 12px; } font-weight: bold; }
form.cms ul.errorlist li {
margin: 0;
padding: 0; }
form.cms div.global_error {
border: 2px dotted red;
padding: 10px;
margin: 1em -10px;
background: #f001;
color: red;
font-weight: bold; }
form.cms div.global_error ul.errorlist {
margin: 0;
font-size: inherit; }
form.cms .errors {
color: red;
font-weight: bold; }
/*# sourceMappingURL=cms.scss.css.map */ /*# sourceMappingURL=cms.scss.css.map */

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -4,92 +4,49 @@
{% block title %}{% trans 'Edit' %} {{form.instance}}{% endblock %} {% block title %}{% trans 'Edit' %} {{form.instance}}{% endblock %}
{% block content %} {% block content %}
<div class="wrapper"> <form method="POST" enctype="multipart/form-data" class="cms">
<div class="wrapper">
<form method="POST" enctype="multipart/form-data" class="cms">
{% csrf_token %} {% csrf_token %}
{{form.media}}
{% if form.errors or formset.errors %} {% if form.errors %}
<div class="global_error"> <div class="global_error">
{% trans 'Please correct the error(s) below and save again' %} {% trans 'Please correct the error(s) below and save again' %}
</div> </div>
{% endif %} {% endif %}
{% for field in form %}
{% include 'cms/formfield.html' with field=field %}
{% endfor %}
<div id="{{formset.prefix}}"> {% include 'cms/form.html' %}
{{formset.management_form}}
{% for form in formset %}
<div class="formset_form" id="{{form.prefix}}" {% if forloop.last %}style="display:none"{% endif %}>
{{form.media}}
{% for field in form.hidden_fields %}
{{field}}
{% endfor %}
{% for field in form.visible_fields %}
<div class="field {{field.name}}">
{% include 'cms/formfield.html' with field=field %}
</div>
{% endfor %}
{% for formset in form.formsets %}
<div class="field {{formset.name}}" id="{{formset.prefix}}">
{{formset.management_form}}
{% for form in formset %}
<div class="subform">
{{form.media}}
{% for field in form.hidden_fields %}
{{field}}
{% endfor %}
{% for field in form.visible_fields %}
{% include 'cms/formfield.html' with field=field %}
{% endfor %}
</div>
{% endfor %}
<img onclick="addForm(this, '{{formset.prefix}}')" src="{% static 'cms/add_small.png' %}" width="50">
</div>
{% endfor %}
</div>
{% endfor %}
<img onclick="addForm(this, '{{formset.prefix}}')" src="{% static 'cms/add.png' %}" width="75" style="display:block;clear:both">
</div>
<div class="edit page"> <div class="edit page">
<button><img src="{% static 'cms/save.png' %}"></button> <button><img src="{% static 'cms/save.png' %}"></button>
</div> </div>
</form> </div>
</div> </form>
{% endblock %} {% endblock %}
{% block extrabody %} {% block extrabody %}
<script type="text/javascript" src="/static/admin/js/urlify.js"></script> <script type="text/javascript" src="/static/admin/js/urlify.js"></script>
<script> <script>
NodeList.prototype.last = function() { function addForm(node) {
return this[this.length - 1];
};
function updateIndex(el) {
let re = /^(.+)-(\d)-(.+)$/;
let matches = el.name.match(re);
if (matches) {
let prefix = matches[1];
let suffix = matches[3];
let index = parseInt(matches[2]) + 1;
el.name = `${prefix}-${index}-${suffix}`;
}
}
function addForm(node, parent_id) {
let base = node.previousElementSibling; let base = node.previousElementSibling;
let parent = document.getElementById(parent_id); let parent = node.parentNode;
let counter = parent.firstElementChild; let counter = parent.firstElementChild;
let extra_form = base.cloneNode(true); let extra_form = base.cloneNode(true);
let inputs = extra_form.querySelectorAll("input, select, textarea"); let prefix = extra_form.id
for (input of inputs) {
updateIndex(input); increment(extra_form, prefix, 'id');
for (let el of extra_form.querySelectorAll(`*[id^=${prefix}]`)) {
increment(el, prefix, 'id');
} }
for (let el of extra_form.querySelectorAll(`*[name^=${prefix}]`)) {
increment(el, prefix, 'name');
}
for (let el of extra_form.querySelectorAll(`*[id^=id_${prefix}]`)) {
increment(el, 'id_' + prefix, 'id');
}
for (let el of extra_form.querySelectorAll(`*[for^=id_${prefix}]`)) {
increment(el, 'id_' + prefix, 'for');
}
extra_form.style.display = 'block'; extra_form.style.display = 'block';
node.remove(); node.remove();
parent.appendChild(extra_form); parent.appendChild(extra_form);
@ -99,6 +56,19 @@
resizeTextareas(); resizeTextareas();
} }
function increment(node, prefix, attr) {
let re = RegExp(`${prefix}(.*)`);
let matches = node.getAttribute(attr).match(re);
if (matches) {
let suffix = matches[1];
let name = prefix.replace(/-\d+$/, '');
let index = parseInt(prefix.replace(/.*-/, ''));
index++;
let new_prefix = `${name}-${index}`;
node.setAttribute(attr, new_prefix + suffix);
}
}
function resizeTextareas() { function resizeTextareas() {
let tx = document.getElementsByTagName('textarea'); let tx = document.getElementsByTagName('textarea');
for (let i = 0; i < tx.length; i++) { for (let i = 0; i < tx.length; i++) {
@ -112,12 +82,16 @@
} }
function showRelevantFields(form, type) { function showRelevantFields(form, type) {
console.log(form, type);
let fields_per_type = {{fields_per_type|safe}}; let fields_per_type = {{fields_per_type|safe}};
for (let field of form.querySelectorAll('div.field')) { for (let field of form.querySelectorAll(`fieldset#${form.id} > div`)) {
field.style.display = 'none'; field.style.display = 'none';
} }
for (let field of form.querySelectorAll(`fieldset#${form.id} > div.DELETE`)) {
field.style.display = 'block';
}
for (let name of fields_per_type[type]) { for (let name of fields_per_type[type]) {
for (let field of form.querySelectorAll('div.field.' + name)) { for (let field of form.querySelectorAll(`fieldset#${form.id} > div.${name}`)) {
field.style.display = 'block'; field.style.display = 'block';
} }
} }

Wyświetl plik

@ -0,0 +1,21 @@
{% load static %}
<fieldset id="{{form.prefix}}" class="form">
{{form.media}}
{% for field in form.hidden_fields %}
{{field}}
{% endfor %}
{% for field in form.visible_fields %}
{% include 'cms/formfield.html' with field=field %}
{% endfor %}
{% for formset in form.formsets %}
<div id="{{formset.prefix}}" class="formset {{formset.name}}">
{{formset.management_form}}
{% for form in formset %}
{% include 'cms/form.html' %}
{% endfor %}
<img onclick="addForm(this, '{{formset.prefix}}')" src="{% static 'cms/add.png' %}">
</div>
{% endfor %}
</fieldset>

Wyświetl plik

@ -157,7 +157,7 @@ class EditPage(UserPassesTestMixin, edit.ModelFormMixin, base.TemplateResponseMi
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
# context['formset'] = SectionFormSet(instance=self.object, form_kwargs={'label_suffix': ''}) context['form'].formsets = [context['formset']]
fields_per_type = {} fields_per_type = {}
for model, _ in Section.TYPES: for model, _ in Section.TYPES:
ctype = ContentType.objects.get( ctype = ContentType.objects.get(