atr/templates/project-add-project.html (118 lines of code) (raw):
{% extends "layouts/base.html" %}
{% block title %}
Add a new project ~ ATR
{% endblock title %}
{% block description %}
Add a new project based on an existing one.
{% endblock description %}
{% block content %}
<h1>
Add a new <strong>{{ project_name.removesuffix(" (Incubating)") }}</strong> sub-project
</h1>
<p>New projects can only be derived from existing projects, by adding a suffix.</p>
<form method="post" class="atr-canary py-4">
{{ form.hidden_tag() }}
<div class="mb-3 pb-3 row border-bottom">
<label for="{{ form.derived_project_name.id }}"
class="col-sm-3 col-form-label text-sm-end">{{ form.derived_project_name.label.text }}:</label>
<div class="col-sm-8">
{{ form.derived_project_name(class_="form-control") }}
{% if form.derived_project_name.errors -%}
<span class="text-danger small">{{ form.derived_project_name.errors[0] }}</span>{%- endif %}
<p class="text-muted mt-1">The desired suffix for the full project name.</p>
<p id="capitalisation-warning" class="text-danger small mt-1 d-none">
<i class="bi bi-exclamation-triangle"></i>
Warning: Ensure all words in the derived name start with a capital for proper display.
</p>
</div>
</div>
<div class="mb-3 pb-3 row border-bottom">
<label id="new-project-name-label"
for="new-project-name-display"
class="col-sm-3 col-form-label text-sm-end">Project name preview:</label>
<div class="col-sm-8">
<code id="new-project-name-display"
class="form-control-plaintext bg-light p-2 rounded d-block"></code>
<p class="text-muted small mt-1">This will be the full display name for the derived project.</p>
</div>
</div>
<div class="mb-3 pb-3 row border-bottom">
<label id="new-project-label-label"
for="new-project-label-display"
class="col-sm-3 col-form-label text-sm-end">Project label preview:</label>
<div class="col-sm-8">
<code id="new-project-label-display"
class="form-control-plaintext bg-light p-2 rounded d-block"></code>
<p class="text-muted small mt-1">This will be the short label used in URLs and identifiers.</p>
</div>
</div>
<div class="row">
<div class="col-sm-9 offset-sm-3">{{ form.submit(class_="btn btn-primary mt-3") }}</div>
</div>
</form>
{% endblock content %}
{% block javascripts %}
{{ super() }}
<script>
document.addEventListener("DOMContentLoaded", () => {
const projectLabel = document.getElementById("{{ form.project_name.id }}");
const projectSelect = "{{ project_name }}";
const derivedNameInput = document.getElementById("{{ form.derived_project_name.id }}");
const newNameDisplay = document.getElementById("new-project-name-display");
const newLabelDisplay = document.getElementById("new-project-label-display");
const capitalisationWarning = document.getElementById("capitalisation-warning");
if (!projectSelect || !derivedNameInput || !newNameDisplay || !newLabelDisplay || !capitalisationWarning) return;
function generateSlug(text) {
return text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
}
function updatePreview() {
const selectedOption = projectSelect;
const baseLabel = projectLabel.value;
const baseFullName = selectedOption;
const derivedNameValue = derivedNameInput.value.trim();
let hasCapitalisationIssue = false;
if (derivedNameValue) {
const words = derivedNameValue.split(/\s+/);
for (const word of words) {
if (word.length > 0 && !/^[A-Z]/.test(word)) {
hasCapitalisationIssue = true;
break;
}
}
}
if (hasCapitalisationIssue) {
capitalisationWarning.classList.remove("d-none");
} else {
capitalisationWarning.classList.add("d-none");
}
let newFullName = baseFullName;
if (derivedNameValue) {
const match = baseFullName.match(/^(.*?)\s*(\(.*\))?$/);
let mainPart = baseFullName.trim();
let suffixPart = null;
if (match) {
mainPart = match[1] ? match[1].trim() : mainPart;
suffixPart = match[2];
}
if (suffixPart) {
newFullName = `${mainPart} ${derivedNameValue} ${suffixPart}`;
} else {
newFullName = `${mainPart} ${derivedNameValue}`;
}
newFullName = newFullName.replace(/\s{2,}/g, " ").trim();
}
newNameDisplay.textContent = newFullName || "(Select base project)";
let newLabel = baseLabel;
if (derivedNameValue) {
const derivedSlug = generateSlug(derivedNameValue);
if (derivedSlug) {
newLabel = `${baseLabel}-${derivedSlug}`;
}
}
newLabelDisplay.textContent = newLabel || "(Enter derived project name)";
}
derivedNameInput.addEventListener("input", updatePreview);
updatePreview();
});
</script>
{% endblock javascripts %}