Skip to content

Commit

Permalink
[proofing] Add partial work for search+replace
Browse files Browse the repository at this point in the history
## Tests

1. built container with make docker-start
2. checked Texts, Dictionaries, and Proofing pages.
3. tested `proofing > project > edit > search` page
4. tested `proofing > project > edit > search and replace` page

## To do

1. Test actual `search and replace`. I could not find a pre-existing
text in db to test this feature.
2. add support in translation files
  • Loading branch information
kvchitrapu authored Feb 22, 2023
1 parent 52d970a commit 10cf5fd
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ambuda/templates/proofing/projects/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
{{ m.project_nav(project=project, active='edit') }}

{% set search_url = url_for("proofing.project.search", slug=project.slug) %}
{% set replace_url = url_for("proofing.project.replace", slug=project.slug) %}
{% set ocr_url = url_for("proofing.project.batch_ocr", slug=project.slug) %}

<div class="prose">

<ul>
<li><a href="{{ search_url }}">{{ _('Search the project') }}</a></li>
<li><a href="{{ replace_url }}">{{ _('Search & replace in the project') }}</a></li>
<li><a href="{{ ocr_url }}">{{ _('Run batch OCR') }}</a></p>
</ul>

Expand Down
47 changes: 47 additions & 0 deletions ambuda/templates/proofing/projects/replace.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{% extends 'proofing/base.html' %}
{% from "macros/forms.html" import field %}
{% import "macros/proofing.html" as m %}

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

{% block content %}

{{ m.project_header_nested('Search and Replace', project) }}
{{ m.project_nav(project=project, active='edit') }}

<div class="prose">
<p>Use this simple search and replace form to make edits across this project.</p>
</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 %}
<div class="prose">

{% 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 %}
</div>
</li>
{% endfor %}
</ul>

</div>
{% endif %}
{% endblock %}
65 changes: 65 additions & 0 deletions ambuda/views/proofing/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ class DeleteProjectForm(FlaskForm):
slug = StringField("Slug", validators=[DataRequired()])


class ReplaceForm(SearchForm):
class Meta:
csrf = False

replace = StringField(_l("Replace"), validators=[DataRequired()])


@bp.route("/<slug>/")
def summary(slug):
"""Show basic information about the project."""
Expand Down Expand Up @@ -279,6 +286,64 @@ def search(slug):
)


@bp.route("/<slug>/replace")
@login_required
def replace(slug):
"""Search and replace a string across all of the project's pages.
This is useful to replace a string across the project in one shot.
"""
project_ = q.project(slug)
if project_ is None:
abort(404)

form = ReplaceForm(request.args)
if not form.validate():
return render_template(
"proofing/projects/replace.html", project=project_, form=form
)

# search for "query" string and replace with "update" string
query = form.query.data
update = form.replace.data

results = []
for page_ in project_.pages:
if not page_.revisions:
continue

matches = []

latest = page_.revisions[-1]
for line in latest.content.splitlines():
if query in line:
matches.append(
{
"query": escape(line).replace(
query, Markup(f"<mark>{escape(query)}</mark>")
),
"update": escape(line).replace(
query, Markup(f"<mark>{escape(update)}</mark>")
),
}
)
if matches:
results.append(
{
"slug": page_.slug,
"matches": matches,
}
)
return render_template(
"proofing/projects/replace.html",
project=project_,
form=form,
query=query,
update=update,
results=results,
)


@bp.route("/<slug>/batch-ocr", methods=["GET", "POST"])
@p2_required
def batch_ocr(slug):
Expand Down

0 comments on commit 10cf5fd

Please sign in to comment.