Remove the ability to skip secondary validations when creating a BUR.
The only skippable validation that still existed was the requirement
that both tags in an implication must have wiki pages. It's now
mandatory to write wiki pages for tags before you can request an
implication. This doesn't apply to empty tags.
Remove the `processing` state from aliases and implications. This state
was used to mark when an alias or implication had been approved but the
alias or implication was still being processed. Aliases in the
processing state were still considered active, so there was no
functional difference between the active state and the processing state.
This fixes a problem where it was possible for implications to get stuck
in the processing state. This happened when a BUR contained a duplicate
implication. Transitioning from the processing state to the active state
failed in this case because we used `update` instead of `update!`, which
meant validation errors were silently ignored.
Bug: if a BUR contained a mass update followed by an alias, then the
alias would become active before the mass update, which could cause
the mass update to return incorrect results if both the alias and mass
update touched the same tags.
This happened because all aliases and implications in the BUR were set
to a queued state before the mass update was processed, but putting an
alias in the queued state effectively made it active.
The fix is to remove the queued state. This was only used anyway as a
debugging tool anyway to monitor the state of BURs as they were being
processed.
* Only show the current pending flag on flagged posts. Don't show old flags.
* Don't show both the "This post was flagged for review" and the "This
post was flagged and is pending" notices.
* Only show the current pending appeal in the "This post was appealed"
notice. Don't show old appeals.
* Don't show both the "This post was deleted" and the "This post was
appealed" notice on appealed posts. Only show the "This post was
appealed" notice.
* Show "no reason" if no appeal reason was given.
Fix broken links on various pages:
* The 'History' link in the sidebar on the post index page.
* The 'History' links on the tags index page.
* The 'Tag History' link in the sidebar on the wiki show page.
Replace references to the `is_resolved` field with the `status` field.
Post flags were marked as resolved when a post was approved (but not
when the post was deleted because it went unapproved). The status field
supercedes the resolved field.
* Include appealed posts in the modqueue.
* Add `status` field to appeals. Appeals start out as `pending`, then
become `rejected` if the post isn't approved within three days. If the
post is approved, the appeal's status becomes `succeeded`.
* Add `status` field to flags. Flags start out as `pending` then become
`rejected` if the post is approved within three days. If the post
isn't approved, the flag's status becomes `succeeded`.
* Leave behind a "Unapproved in three days" dummy flag when an appeal
goes unapproved, just like when a pending post is unapproved.
* Only allow deleted posts to be appealed. Don't allow flagged posts to be appealed.
* Add `status:appealed` metatag. `status:appealed` is separate from `status:pending`.
* Include appealed posts in `status:modqueue`. Search `status:modqueue order:modqueue`
to view the modqueue as a normal search.
* Retroactively set old flags and appeals as succeeded or rejected. This
may not be correct for posts that were appealed or flagged multiple
times. This is difficult to set correctly because we don't have
approval records for old posts, so we can't tell the actual outcome of
old flags and appeals.
* Deprecate the `is_resolved` field on post flags. A resolved flag is a
flag that isn't pending.
* Known bug: appealed posts have a black border instead of a blue
border. Checking whether a post has been appealed would require either
an extra query on the posts/index page, or an is_appealed flag on
posts, neither of which are very desirable.
* Known bug: you can't use `status:appealed` in blacklists, for the same
reason as above.
Rework post deletion from using a separate page to using a dialog box,
like flagging.
* Add `DELETE /posts/:id` endpoint.
* Remove `POST /moderator/post/posts/:id/delete` endpoint.
Rewrite the tag counter widget (the one above the tag edit box) to use
React. This is a trial run for using React elsewhere.
We actually use Preact instead of React because it's lighter weight.
We use Mobx for state management because it's cleaner than React's
setState or useState.
This incidentally fixes a couple bugs:
* The tag counter wasn't updated when deleting tags with backspace
* The tag counter wasn't updated when pasting in new tags.
* Show a banner if the user is restricted because they signed up from a
proxy or VPN.
* Add an option to resend the confirmation email if your account has an
unverified email address.
Rewrite the notes Javascript from a procedural style to an
object-oriented style.
Before the notes Javascript had a lot of problems:
* There was hidden state everywhere, both locally and globally. We had
state in global variables, in <meta> tags, in DOM data-* attributes
(on multiple elements), and in jQuery .data() properties (which are
different from data-* attributes, because they aren't visible in the
DOM).
* Local state was hard to reason about. There was lots of direct DOM
manipulation in random places. Functions had to constantly pass around
note ids and look up elements in the DOM to get the state. State was
invisible because it was stored as jQuery .data() properties. It was
hard to follow where state was stored, how it was initialized, and how
it changed.
* Global state was also a mess. There were a lot of global flags and
variables only used in specific situations. Almost all of this state was
unnecessary. Global state also prevented us from doing things like
loading or unloading posts dynamically, or showing multiple posts with
notes on the same page.
* There was a lot of duplication of code, especially for placing notes,
and for loading or saving new notes versus saved notes.
Now the code is organized in an object-oriented fashion:
* The Note class represents a single note. A post has a list of notes,
and each note object has a Note.Box and a Note.Body. Together these
objects encapsulate the note's state.
* Notes have methods for doing things like placing note boxes, or showing
and hiding note bodies, or creating, saving, or deleting notes. This
makes the JS API cleaner.
* Global state is kept to a minimum.
This is one big patch because it was too hard to make these changes
incrementally. There are a couple minor bugfixes, but the actual
behavior of notes should remain unchanged.
Bugfixes:
* It was possible to enter translation mode, start dragging a new note,
then press N to leave translation mode while still dragging the note.
If you did this, then you would be stuck in translation mode and you
couldn't stop dragging the note.
* Placement of new notes is now pixel-perfect. Before when placing a
note, the note would shift by 1-2 pixels.
* Previewing an empty note didn't show the "Click to edit" message.
Other noteworthy changes:
* Most global state has been eliminated. There were a lot of flags and
variables stored as global variables on `Danbooru.Note`. Most of these
turned out to be either unnecessary or even unused.
* Notes now have an explicit minimum size of 10x10 pixels. Before this
limit was hardcoded and undocumented.
* A lot of the note placement and note creation code has been simplified.
* `Note.add()` and `Note.create()` have been refactored into `new Note()`.
Before `Note.add` was used to load an existing note, while `Note.create`
was used to create a new note. These did the same thing, but had
slightly different behavior.
* `Note.Box.scale()` and `Note.box.update_data_attributes` have been
refactored into `Note.Box.place_note()`. Contrary to their names,
these functions were actually both used to place notes.
This will facilitate users being able to monitor tag changes from
a list of tags they are interested in. Currently, the only way to
do this is 2 separate queries on the added_tags and removed_tags.
When Tippy is delegated to the same element more than once, that
prevents the destroy method from working, which makes it so that
users cannot change the settings and then reinitialize the tooltips.
To this end, each delegate() call is now given a different selector.
Additionally, the tooltips are given their own separate <div>'s so
that something like the second delegate() call in the UserTooltips
module can be given its own unique selector.
Standardize font sizes and heading tags (<h1>-<h6>) to be more
consistent across the site.
Changes:
* Introduce font size CSS variables and start replacing hardcoded font
sizes with standard sizes.
* Change header tags to use only one <h1> per page. One <h1> per page is
recommended for SEO purposes. Usually this is for the page title, like
in forum threads or wiki pages.
* Standardize on <h2> for section headers in sidebars and <h3> for
smaller subsection headers. Don't use <h4>-<h6>.
* In DText, make h1-h4 headers all the same size. Standard wiki style is
to ignore h1-h3 and start at h4.
* In DText, make h4-h6 the same size as the h1-h3 tags outside of DText.
* In the tag list, change the <h1> and <h2> tag category headers to <h3>.
* Make usernames in comments and forum posts smaller. Also change the
<h4> tag for the commenter name to <div class="author-name">.
* Make the tag list, paginator, and nav menu smaller on mobile.
* Change h1#app-name-header to a#app-name-header.
* Show completed uploads to other users.
* Don't show failed or incomplete uploads to other users.
* Don't show tags to other users.
* Delete completed uploads after 1 hour.
* Delete incomplete uploads after 1 day.
* Delete failed uploads after 3 days.
Rework sitemaps to provide more coverage of the site. We want every
important page on the site - including every post, tag, and wiki page -
to be indexed by Google. We do this by generating sitemaps and sitemap
indexes that contain links to every important page on the site.