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.cms {
margin-bottom: 3em;
div.wrapper {
overflow: hidden;
}
//margin: 0.5em auto;
section {
margin-top: 3em;
div.wrapper {
margin: 0 auto;
padding: 0 0.5em;
}
fieldset {
padding: 2em;
margin-bottom: 2em;
border: 0.5px solid black;
border-radius: 3px;
border: 0.5px solid #ccc;
clear: both;
margin: 0.5em 0em;
padding: 0.5em;
border-radius: 0.25em;
}
legend {
font-size: 1.15em;
}
img {
display: block;
clear: both;
width: 50px;
cursor: pointer;
}
div.formfield {

Wyświetl plik

@ -183,97 +183,115 @@ section.contact div#message {
display: none; }
/* Form elements */
form.cms {
margin-bottom: 3em; }
form.cms div.wrapper {
overflow: hidden; }
form.cms section {
margin-top: 3em; }
form.cms fieldset {
padding: 2em;
margin-bottom: 2em;
border: 0.5px solid black;
border-radius: 3px; }
form.cms fieldset legend {
font-size: 1.15em; }
form.cms div.formfield {
margin-bottom: 10px;
clear: both;
box-sizing: border-box; }
form.cms div.formfield.type, form.cms div.formfield.number, form.cms div.formfield.slug {
width: 77%;
clear: none;
float: left; }
form.cms div.formfield.number {
width: 20%;
float: right; }
form.cms div.formfield.error {
border: 2px dotted red;
padding: 10px;
margin: 10px -10px;
background: #f001; }
form.cms div.formfield.required div.label {
font-weight: 700; }
form.cms div.label, form.cms label {
font-size: 0.7rem;
font-weight: 400;
text-align: left;
margin-bottom: 2px; }
form.cms div.input {
overflow: hidden; }
form.cms div.helptext, form.cms span.required {
color: #666;
font-size: 12px !important;
font-weight: 400 !important; }
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;
form.cms div.wrapper {
margin: 0 auto;
padding: 0 0.5em; }
form.cms fieldset {
border: 0.5px solid #ccc;
clear: both;
margin: 0.5em 0em;
padding: 0.5em;
border-radius: 0.25em; }
form.cms img {
display: block;
clear: both;
width: 50px;
cursor: pointer; }
form.cms div.formfield {
margin-bottom: 10px;
clear: both;
box-sizing: border-box; }
form.cms div.formfield.type, form.cms div.formfield.number, form.cms div.formfield.slug {
width: 77%;
clear: none;
float: left; }
form.cms div.formfield.number {
width: 20%;
float: right; }
form.cms div.formfield.error {
border: 2px dotted red;
padding: 10px;
margin: 10px -10px;
background: #f001; }
form.cms div.formfield.required div.label {
font-weight: 700; }
form.cms div.label, form.cms label {
font-size: 0.7rem;
font-weight: 400;
text-align: left;
margin-bottom: 2px; }
form.cms div.input {
overflow: hidden; }
form.cms div.helptext, form.cms span.required {
color: #666;
font-size: 12px !important;
font-weight: 400 !important; }
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;
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 {
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;
margin-bottom: 1em;
padding: 0;
list-style: none;
color: red;
font-size: 12px; }
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; }
font-size: inherit; }
form.cms .errors {
color: red;
font-weight: bold; }
/*# 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 content %}
<div class="wrapper">
<form method="POST" enctype="multipart/form-data" class="cms">
<form method="POST" enctype="multipart/form-data" class="cms">
<div class="wrapper">
{% csrf_token %}
{{form.media}}
{% if form.errors or formset.errors %}
{% if form.errors %}
<div class="global_error">
{% trans 'Please correct the error(s) below and save again' %}
</div>
{% endif %}
{% for field in form %}
{% include 'cms/formfield.html' with field=field %}
{% endfor %}
<div id="{{formset.prefix}}">
{{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>
{% include 'cms/form.html' %}
<div class="edit page">
<button><img src="{% static 'cms/save.png' %}"></button>
</div>
</form>
</div>
</div>
</form>
{% endblock %}
{% block extrabody %}
<script type="text/javascript" src="/static/admin/js/urlify.js"></script>
<script>
NodeList.prototype.last = function() {
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) {
function addForm(node) {
let base = node.previousElementSibling;
let parent = document.getElementById(parent_id);
let parent = node.parentNode;
let counter = parent.firstElementChild;
let extra_form = base.cloneNode(true);
let inputs = extra_form.querySelectorAll("input, select, textarea");
for (input of inputs) {
updateIndex(input);
let prefix = extra_form.id
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';
node.remove();
parent.appendChild(extra_form);
@ -99,6 +56,19 @@
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() {
let tx = document.getElementsByTagName('textarea');
for (let i = 0; i < tx.length; i++) {
@ -112,12 +82,16 @@
}
function showRelevantFields(form, type) {
console.log(form, type);
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';
}
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 field of form.querySelectorAll('div.field.' + name)) {
for (let field of form.querySelectorAll(`fieldset#${form.id} > div.${name}`)) {
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):
context = super().get_context_data(**kwargs)
# context['formset'] = SectionFormSet(instance=self.object, form_kwargs={'label_suffix': ''})
context['form'].formsets = [context['formset']]
fields_per_type = {}
for model, _ in Section.TYPES:
ctype = ContentType.objects.get(