posts: rewrite tag counter widget in React.
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.
This commit is contained in:
@@ -43,6 +43,7 @@ export { default as PostTooltip } from '../src/javascripts/post_tooltips.js';
|
||||
export { default as PostVersion } from '../src/javascripts/post_version.js';
|
||||
export { default as RelatedTag } from '../src/javascripts/related_tag.js';
|
||||
export { default as Shortcuts } from '../src/javascripts/shortcuts.js';
|
||||
export { default as TagCounter } from '../src/javascripts/tag_counter.js';
|
||||
export { default as Upload } from '../src/javascripts/uploads.js.erb';
|
||||
export { default as UserTooltip } from '../src/javascripts/user_tooltips.js';
|
||||
export { default as Utility } from '../src/javascripts/utility.js';
|
||||
|
||||
@@ -42,8 +42,6 @@ Post.initialize_all = function() {
|
||||
}
|
||||
|
||||
var $fields_multiple = $('[data-autocomplete="tag-edit"]');
|
||||
$fields_multiple.on("keypress.danbooru", Post.update_tag_count);
|
||||
$fields_multiple.on("click", Post.update_tag_count);
|
||||
|
||||
$(window).on('danbooru:initialize_saved_seraches', () => {
|
||||
Post.initialize_saved_searches();
|
||||
@@ -402,7 +400,6 @@ Post.initialize_post_sections = function() {
|
||||
$("#post_tag_string").focus().selectEnd().height($("#post_tag_string")[0].scrollHeight);
|
||||
$("#recommended").hide();
|
||||
$(document).trigger("danbooru:open-post-edit-tab");
|
||||
Post.update_tag_count({target: $("#post_tag_string")});
|
||||
} else if (e.target.hash === "#recommended") {
|
||||
$("#comments").hide();
|
||||
$("#edit").hide();
|
||||
@@ -513,32 +510,6 @@ Post.initialize_recommended = function() {
|
||||
});
|
||||
};
|
||||
|
||||
Post.update_tag_count = function(event) {
|
||||
let string = "0 tags";
|
||||
let count = 0;
|
||||
|
||||
if (event) {
|
||||
let tags = Utility.regexp_split($(event.target).val());
|
||||
if (tags.length) {
|
||||
count = tags.length;
|
||||
string = (count === 1) ? (count + " tag") : (count + " tags")
|
||||
}
|
||||
}
|
||||
|
||||
$("#tags-container .count").html(string);
|
||||
let klass = "";
|
||||
|
||||
if (count < Post.LOW_TAG_COUNT) {
|
||||
klass = "frown";
|
||||
} else if (count >= Post.LOW_TAG_COUNT && count < Post.HIGH_TAG_COUNT) {
|
||||
klass = "meh";
|
||||
} else {
|
||||
klass = "smile";
|
||||
}
|
||||
|
||||
$("#tags-container .options #face").removeClass().addClass(`far fa-${klass}`);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
Post.initialize_all();
|
||||
});
|
||||
|
||||
49
app/javascript/src/javascripts/tag_counter.js
Normal file
49
app/javascript/src/javascripts/tag_counter.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import { h, Component, render } from "preact";
|
||||
import { observable, computed, action } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
import Utility from "./utility";
|
||||
|
||||
export default @observer class TagCounter extends Component {
|
||||
static lowCount = 10;
|
||||
static highCount = 20;
|
||||
|
||||
@observable tagCount = 0;
|
||||
|
||||
componentDidMount() {
|
||||
$(this.props.tags).on("input", this.updateCount);
|
||||
this.updateCount();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span class="tag-counter">
|
||||
<span class="tag-count">{this.tagCount}</span> / {TagCounter.highCount} tags
|
||||
<i class={`far fa-${this.emoji}`}></i>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@action.bound updateCount() {
|
||||
this.tagCount = Utility.regexp_split($(this.props.tags).val()).length;
|
||||
}
|
||||
|
||||
@computed get emoji() {
|
||||
if (this.tagCount < TagCounter.lowCount) {
|
||||
return "frown";
|
||||
} else if (this.tagCount >= TagCounter.lowCount && this.tagCount < TagCounter.highCount) {
|
||||
return "meh";
|
||||
} else {
|
||||
return "smile";
|
||||
}
|
||||
}
|
||||
|
||||
static initialize() {
|
||||
$("[data-tag-counter]").toArray().forEach(element => {
|
||||
let target = $($(element).attr("data-for")).get(0);
|
||||
render(h(TagCounter, { tags: target }), element);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(TagCounter.initialize);
|
||||
@@ -50,8 +50,7 @@
|
||||
<%= f.label :tag_string, "Tags" %>
|
||||
|
||||
<span class="options">
|
||||
<i id="face" class="fas"></i>
|
||||
<span class="count"></span>
|
||||
<span data-tag-counter data-for="#post_tag_string"></span>
|
||||
<a href="javascript:void(0)"><i id="open-edit-dialog" class="fas fa-arrows-alt" title="detach" data-shortcut="shift+e"></i></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -66,8 +66,7 @@
|
||||
<%= f.label :tag_string, "Tags" %>
|
||||
|
||||
<span class="options">
|
||||
<i id="face" class="fas"></i>
|
||||
<span class="count"></span>
|
||||
<span data-tag-counter data-for="#upload_tag_string"></span>
|
||||
<a href="javascript:void(0)"><i id="open-edit-dialog" class="fas fa-arrows-alt" title="detach" data-shortcut="shift+e"></i></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -41,6 +41,13 @@ module.exports = function(api) {
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
isTestEnv && 'babel-plugin-dynamic-import-node',
|
||||
'@babel/plugin-transform-destructuring',
|
||||
["@babel/plugin-proposal-decorators", {
|
||||
legacy: true
|
||||
}],
|
||||
["@babel/plugin-transform-react-jsx", {
|
||||
pragma: "h",
|
||||
pragmaFrag: "Fragment",
|
||||
}],
|
||||
[
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
{
|
||||
|
||||
@@ -7,7 +7,9 @@ environment.loaders.append('erb', erb);
|
||||
environment.config.output.library = ["Danbooru"];
|
||||
|
||||
environment.config.set("resolve.alias", {
|
||||
"jquery": "jquery/src/jquery.js"
|
||||
"jquery": "jquery/src/jquery.js",
|
||||
"react": "preact/compat",
|
||||
"react-dom": "preact/compat",
|
||||
});
|
||||
|
||||
module.exports = environment
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-decorators": "^7.10.5",
|
||||
"@babel/plugin-transform-react-jsx": "^7.10.4",
|
||||
"@fortawesome/fontawesome-free": "^5.11.2",
|
||||
"@rails/ujs": "^6.0.2-1",
|
||||
"@rails/webpacker": "^5.0.0",
|
||||
@@ -9,6 +11,9 @@
|
||||
"jquery": "3.5.1",
|
||||
"jquery-hotkeys": "^0.2.2",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"mobx": "^5.15.4",
|
||||
"mobx-react": "^6.2.5",
|
||||
"preact": "^10.4.6",
|
||||
"rails-erb-loader": "^5.5.0",
|
||||
"spark-md5": "^3.0.0",
|
||||
"tippy.js": "^6.2.3",
|
||||
|
||||
102
yarn.lock
102
yarn.lock
@@ -65,6 +65,23 @@
|
||||
"@babel/helper-explode-assignable-expression" "^7.10.4"
|
||||
"@babel/types" "^7.10.4"
|
||||
|
||||
"@babel/helper-builder-react-jsx-experimental@^7.10.4":
|
||||
version "7.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b"
|
||||
integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.10.4"
|
||||
"@babel/helper-module-imports" "^7.10.4"
|
||||
"@babel/types" "^7.10.5"
|
||||
|
||||
"@babel/helper-builder-react-jsx@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d"
|
||||
integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.10.4"
|
||||
"@babel/types" "^7.10.4"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2"
|
||||
@@ -88,6 +105,18 @@
|
||||
"@babel/helper-replace-supers" "^7.10.4"
|
||||
"@babel/helper-split-export-declaration" "^7.10.4"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.10.5":
|
||||
version "7.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d"
|
||||
integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==
|
||||
dependencies:
|
||||
"@babel/helper-function-name" "^7.10.4"
|
||||
"@babel/helper-member-expression-to-functions" "^7.10.5"
|
||||
"@babel/helper-optimise-call-expression" "^7.10.4"
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
"@babel/helper-replace-supers" "^7.10.4"
|
||||
"@babel/helper-split-export-declaration" "^7.10.4"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8"
|
||||
@@ -144,6 +173,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.10.4"
|
||||
|
||||
"@babel/helper-member-expression-to-functions@^7.10.5":
|
||||
version "7.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df"
|
||||
integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==
|
||||
dependencies:
|
||||
"@babel/types" "^7.11.0"
|
||||
|
||||
"@babel/helper-module-imports@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620"
|
||||
@@ -274,6 +310,15 @@
|
||||
"@babel/helper-create-class-features-plugin" "^7.10.4"
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-proposal-decorators@^7.10.5":
|
||||
version "7.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.5.tgz#42898bba478bc4b1ae242a703a953a7ad350ffb4"
|
||||
integrity sha512-Sc5TAQSZuLzgY0664mMDn24Vw2P8g/VhyLyGPaWiHahhgLqeZvcGeyBZOrJW0oSKIK2mvQ22a1ENXBIQLhrEiQ==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.10.5"
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
"@babel/plugin-syntax-decorators" "^7.10.4"
|
||||
|
||||
"@babel/plugin-proposal-dynamic-import@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e"
|
||||
@@ -361,6 +406,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-syntax-decorators@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz#6853085b2c429f9d322d02f5a635018cdeb2360c"
|
||||
integrity sha512-2NaoC6fAk2VMdhY1eerkfHV+lVYC1u8b+jmRJISqANCJlTxYy19HGdIkkQtix2UtkcPuPu+IlDgrVseZnU03bw==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
|
||||
@@ -375,6 +427,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.8.0"
|
||||
|
||||
"@babel/plugin-syntax-jsx@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c"
|
||||
integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
|
||||
@@ -602,6 +661,16 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-transform-react-jsx@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2"
|
||||
integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A==
|
||||
dependencies:
|
||||
"@babel/helper-builder-react-jsx" "^7.10.4"
|
||||
"@babel/helper-builder-react-jsx-experimental" "^7.10.4"
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
"@babel/plugin-syntax-jsx" "^7.10.4"
|
||||
|
||||
"@babel/plugin-transform-regenerator@^7.10.4", "@babel/plugin-transform-regenerator@^7.8.7":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63"
|
||||
@@ -799,6 +868,15 @@
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.10.5", "@babel/types@^7.11.0":
|
||||
version "7.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d"
|
||||
integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.10.4"
|
||||
lodash "^4.17.19"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@csstools/convert-colors@^1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
|
||||
@@ -4969,7 +5047,7 @@ lodash.uniq@^4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||
|
||||
lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5, lodash@~4.17.10:
|
||||
lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5, lodash@~4.17.10:
|
||||
version "4.17.19"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
|
||||
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
|
||||
@@ -5374,6 +5452,23 @@ mixin-deep@^1.2.0:
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mobx-react-lite@>=2.0.6:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-2.0.7.tgz#1bfb3b4272668e288047cf0c7940b14e91cba284"
|
||||
integrity sha512-YKAh2gThC6WooPnVZCoC+rV1bODAKFwkhxikzgH18wpBjkgTkkR9Sb0IesQAH5QrAEH/JQVmy47jcpQkf2Au3Q==
|
||||
|
||||
mobx-react@^6.2.5:
|
||||
version "6.2.5"
|
||||
resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.2.5.tgz#9020a17b79cc6dc3d124ad89ab36eb9ea540a45b"
|
||||
integrity sha512-LxtXXW0GkOAO6VOIg2m/6WL6ZuKlzOWwESIFdrWelI0ZMIvtKCMZVUuulcO5GAWSDsH0ApaMkGLoaPqKjzyziQ==
|
||||
dependencies:
|
||||
mobx-react-lite ">=2.0.6"
|
||||
|
||||
mobx@^5.15.4:
|
||||
version "5.15.4"
|
||||
resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.15.4.tgz#9da1a84e97ba624622f4e55a0bf3300fb931c2ab"
|
||||
integrity sha512-xRFJxSU2Im3nrGCdjSuOTFmxVDGeqOHL+TyADCGbT0k4HHqGmx5u2yaHNryvoORpI4DfbzjJ5jPmuv+d7sioFw==
|
||||
|
||||
move-concurrently@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
||||
@@ -6851,6 +6946,11 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.1
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
preact@^10.4.6:
|
||||
version "10.4.6"
|
||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.6.tgz#86cc43396e4bdd755726a2b4b1f0529e78067cd3"
|
||||
integrity sha512-80WJfXH53yyINig5Wza/8MD9n4lMg9G6aN00ws0ptsAaY/Fu/M7xW4zICf7OLfocVltxS30wvNQ8oIbUyZS1tw==
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
|
||||
Reference in New Issue
Block a user