Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

search and replace matching strings across all pages in a project #79

Merged
merged 1 commit into from
Mar 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ test: py-venv-check
coverage:
pytest --cov=ambuda --cov-report=html test/

coverage-report: coverage
coverage report --fail-under=80

# Generate Ambuda's technical documentation.
# After the command completes, open "docs/_build/index.html".
docs: py-venv-check
Expand Down Expand Up @@ -275,6 +278,8 @@ babel-update: py-venv-check
babel-compile: py-venv-check
pybabel compile -d ambuda/translations

# Clean up
# ===============================================
clean:
@rm -rf deploy/data/
@rm -rf ambuda/translations/*
44 changes: 44 additions & 0 deletions ambuda/templates/proofing/projects/confirm_changes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{% extends 'proofing/base.html' %}
{% from "macros/forms.html" import field %}
{% import "macros/proofing.html" as m %}

{% block title %} Search and Replace | {{ project.title }}{% endblock %}

{% block content %}

{{ m.project_header_nested('Review and Confirm Changes', project) }}
{{ m.project_nav(project=project, active='edit') }}

<div class="prose">
<h1>Confirm Changes</h1>
{% macro sp(s, p, n) %}{% if n == 1 %}{{ s }}{% else %}{{ p }}{% endif %}{% endmacro %}
<p>Please carefully review and confirm the changes you selected:</p>
<form method="POST" action="{{ url_for('proofing.project.confirm_changes', slug=project.slug) }}" class="bg-slate-100 p-4 my-4">
{{ form.csrf_token }}
<input type="hidden" name="query" value="{{ query }}">
<input type="hidden" name="replace" value="{{ replace }}">

{% set match_counts = results|map(attribute='matches')|map('length')|list %}
{% set nr = match_counts|sum %}
<p>Confirm changes on {{ nr }} {{ sp("match", "matches", nr) }} that {{ sp("contains", "contain", nr) }} <span style="color: red;"><kbd>{{ query }}</kbd></span> to be replaced by <span style="color: green;"><kbd>{{ replace }}</kbd></span>.</p>

{% for result in results %}
{% set page = result.page %}
{% set page_url = url_for("proofing.page.edit", project_slug=project.slug, page_slug=page.slug) %}
{% set matches = result.matches %}
{% for match in matches %}
<div class="match" style="background-color: rgb(243, 239, 239);">
<p>Page <a href="{{ page_url }}">{{ project.title }}/{{ page.slug }}:</a> Line {{ match.line_num }}</p>
<label for="match{{ page.slug }}-{{ match.line_num }}">{{ match.query }}</label>
<input type="hidden" name="match{{ page.slug }}-{{ match.line_num }}-query" value="{{ match.query }}">
<br>
<label for="match{{ page.slug }}-{{ match.line_num }}-replace" style="color: rgb(97, 86, 66); background-color: rgb(219, 215, 215);"> {{ match.replace }} </label>
<input type="hidden" name="match{{ page.slug }}-{{ match.line_num }}-replace" value="{{ match.replace }}">
</div>
{% endfor %}
{% endfor %}
<button class="btn btn-submit" type="submit" name="cancel" value="cancel">Cancel</button>
<button class="btn btn-submit" type="submit" name="confirm" value="confirm">Confirm</button>
</form>
</div>
{% endblock %}
111 changes: 84 additions & 27 deletions ambuda/templates/proofing/projects/replace.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,95 @@
{{ m.project_nav(project=project, active='edit') }}

<div class="prose">
<h1>Replace</h1>
<p>Use this simple search and replace form to make edits across this project.</p>
<form method="POST" class="bg-slate-100 p-4 my-4">

{{ field(form.query) }}
{{ field(form.replace) }}
<input class="btn btn-submit" type="submit" name="search" value="Project-wide Search & Replace">
</form>
</div>

<form method="GET" class="bg-slate-100 p-4 my-4">
{{ field(form.query) }}
{{ field(form.replace) }}
<input class="btn btn-submit" type="submit" value="Project-wide Search & Replace">
</form>

{% if query %}
{% if results %}
<div class="prose">
<h1>Matches</h1>
{% macro sp(s, p, n) %}{% if n == 1 %}{{ s }}{% else %}{{ p }}{% endif %}{% endmacro %}
<form method="POST" action="{{ url_for('proofing.project.submit_changes', slug=project.slug) }}" class="bg-slate-100 p-4 my-4">
{{ submit_changes_form.csrf_token }}
<input type="hidden" name="query" value="{{ query }}">
<input type="hidden" name="replace" value="{{ replace }}">

{% macro sp(s, p, n) %}{% if n == 1 %}{{ s }}{% else %}{{ p }}{% endif %}{% endmacro %}

{% set nr = results|length %}
<p>Found {{ nr }} {{ sp("page", "pages", nr) }} that {{ sp("contains", "contain", nr) }} <kbd>{{ query }}</kbd>.</p>

<ul>
{% for page in results %}
{% set page_url = url_for("proofing.page.edit", project_slug=project.slug, page_slug=page.slug) %}
<li>
<a href="{{ page_url }}">{{ project.title }}/{{ page.slug }}</a>
<div class="p-2 border-l my-2">
{% for match in page.matches %}
<pre class="p-0.5">{{ match.query }}</pre>
<pre class="p-0.5">{{ match.update }}</pre>
{%- endfor %}
{% set nr = results|length %}
<p>Found {{ nr }} {{ sp("page", "pages", nr) }} that {{ sp("contains", "contain", nr) }} <kbd>{{ query }}</kbd>.</p>
<ul>
<div class="match">
<input type="checkbox" name="check-all" id="check-all">
<label for="check-all">Select all in this page </label>
</div>
</li>
{% endfor %}
</ul>

{% for page in results %}
{% set page_url = url_for("proofing.page.edit", project_slug=project.slug, page_slug=page.slug) %}
<li>
<a href="{{ page_url }}">{{ project.title }}/{{ page.slug }}</a>
<div class="p-2 border-l my-2">
{% for match in page.matches %}
<div class="match" style="background-color: rgb(243, 239, 239);">
<input type="checkbox" name="match{{ page.slug }}-{{ match.line_num }}" id="match{{ page.slug }}-{{ match.line_num }}" value="selected">
<p>Page <a href="{{ page_url }}">{{ project.title }}/{{ page.slug }}:</a> Line {{ match.line_num }}</p>
<label for="match{{ page.slug }}-{{ match.line_num }}">{{ match.query }}</label>
<br>
<label for="match{{ page.slug }}-{{ match.line_num }}-replace" style="color: rgb(97, 86, 66); background-color: rgb(219, 215, 215);"> {{ match.replace }} </label>
<input type="hidden" name="match{{ page.slug }}-{{ match.line_num }}-replace" id="match{{ page.slug }}-{{ match.line_num }}-replace" value="{{ match.replace }}">
</div>
<br>
{% endfor %}
</div>
</li>
{% endfor %}
{% if submit_changes_form %}
{{ submit_changes_form.submit(class="btn btn-submit") }}
{% else %}
<input class="btn btn-submit" type="submit" name="submit" value="Submit Changes">
{% endif %}
</form>
</ul>
<input type="hidden" name="form_submitted" value="1">
{% endif %}

<script>
// Get references to the "check-all" checkbox and all the other checkboxes
const checkAll = document.querySelector('#check-all');
const checkboxes = document.querySelectorAll('input[type="checkbox"][name$="selected"]');

// Add a change event listener to the "check-all" checkbox
checkAll.addEventListener('change', function(event) {
// If the "check-all" checkbox is checked, check all the other checkboxes
if (event.target.checked) {
checkboxes.forEach(function(checkbox) {
checkbox.checked = true;
});
}
// If the "check-all" checkbox is not checked, uncheck all the other checkboxes
else {
checkboxes.forEach(function(checkbox) {
checkbox.checked = false;
});
}
});

// Add change event listeners to each individual checkbox
checkboxes.forEach(function(checkbox) {
checkbox.addEventListener('change', function(event) {
const replaceField = document.querySelector(`#${event.target.id}-replace`);
if (event.target.checked) {
replaceField.style.display = '';
} else {
replaceField.style.display = 'none';
}
});
});
</script>

</div>
{% endif %}

{% endblock %}
Loading