mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-01 01:59:56 +00:00
Compare commits
291 commits
0.19.4-bet
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
8ba9bd22e0 | ||
|
05362c8733 | ||
|
c4b42d32b9 | ||
|
9fd5bd5319 | ||
|
2c5b1f2ced | ||
|
3a331f65e7 | ||
|
6bbae080d7 | ||
|
bfa6354a11 | ||
|
cb5f1b36f5 | ||
|
1125d2a615 | ||
|
61ebe0a32b | ||
|
83a1e924ce | ||
|
e560fe6b7f | ||
|
727a1eced5 | ||
|
492b235cd5 | ||
|
c8e717acb5 | ||
|
863b3e2546 | ||
|
68e88ba9ec | ||
|
1650d1ec70 | ||
|
9beffed143 | ||
|
7f9281e62a | ||
|
5659cb05a1 | ||
407d1dd6b4 | |||
|
0b3720f981 | ||
b05363beb5 | |||
|
f97df0198b | ||
|
4c6f05a7fa | ||
|
6552a69aab | ||
|
e401c274eb | ||
|
a3754d8cf2 | ||
|
567935c684 | ||
|
e3266c6535 | ||
|
f2b2a20637 | ||
|
e91d9fa659 | ||
|
22ca14c13b | ||
|
7fa8bda2dc | ||
|
611e7f2cdf | ||
|
277bc6f77c | ||
|
eee2358348 | ||
|
0757c05308 | ||
|
f00014da97 | ||
8b7a4e72af | |||
|
6b5da8cfb1 | ||
|
6057c96f0c | ||
|
8a500f3ddf | ||
|
7be8d1d8eb | ||
|
3823e38081 | ||
|
17ac216e4b | ||
|
43e03219fa | ||
|
c804e107e9 | ||
|
131907b8b5 | ||
|
1789fb371f | ||
|
017df0f2d0 | ||
|
626b18d478 | ||
|
9ff0b93560 | ||
|
aee7145bc2 | ||
|
b1b82c3d6b | ||
|
bc7f83faf0 | ||
|
f5c48bb6bf | ||
|
ee35fae3fa | ||
|
c8b617b403 | ||
|
5e719c8cec | ||
|
f2c1c20efa | ||
|
f9183bf0dc | ||
|
223d29e419 | ||
|
6176d718dc | ||
|
eb6b407060 | ||
|
3d45dab69f | ||
|
c187cd34c3 | ||
|
f7bf658a60 | ||
|
8a44c4d38f | ||
|
5f535e7dad | ||
|
10f22f07c7 | ||
|
6340419c47 | ||
|
ca16a3121e | ||
|
267126bd35 | ||
|
827deb4e01 | ||
|
550cdbfaf1 | ||
|
e263f7d716 | ||
|
43aea06bec | ||
|
66c1376ac0 | ||
|
22eda995d3 | ||
631c2cda4a | |||
6580e1aaed | |||
|
2fdd42087a | ||
|
8c68ee450e | ||
|
d4b6f29729 | ||
|
d69dd1531b | ||
|
f456610930 | ||
|
76219b9067 | ||
|
c7f10f1efb | ||
|
8c0878e8c3 | ||
|
0d795581b5 | ||
252695ea6a | |||
|
42637b96d3 | ||
fbcb6b55c5 | |||
|
5a1878c482 | ||
|
a3ea569b33 | ||
|
a141871f4a | ||
|
202dc7c6df | ||
b5c6caef47 | |||
ba959c5cae | |||
|
2b726b51b5 | ||
|
19177bdacf | ||
1a084a964d | |||
|
9c4424f792 | ||
62c62bf038 | |||
7fc6216a2a | |||
|
0651b216d2 | ||
|
8d5e7de18e | ||
|
999b083545 | ||
|
bee4395706 | ||
6754c08902 | |||
|
fa3b2488fd | ||
24ddec4ee0 | |||
9db79c49d6 | |||
|
0763fb688a | ||
|
7718ee7a80 | ||
|
66277e6ece | ||
|
e09127467c | ||
|
876d892f8c | ||
|
f4accddbda | ||
|
72a3a3dbb9 | ||
|
a5a696e54f | ||
|
e9c6e99165 | ||
|
e9ba38dedf | ||
|
9f54a25e26 | ||
|
0ab51cf52b | ||
|
ef3b35393f | ||
|
8abae1973b | ||
|
036e925593 | ||
|
81dc9a2511 | ||
|
37f4944dc2 | ||
|
4a65fd888d | ||
|
c73345f07e | ||
|
966faede3b | ||
|
a024e3301a | ||
|
5c3da58366 | ||
|
5d124a3e14 | ||
|
cd15d3c132 | ||
|
c4d0a06f9e | ||
|
01c095d269 | ||
|
ab51245ca5 | ||
|
d67b43a043 | ||
|
5cd66bb037 | ||
|
c1e22bd7d5 | ||
|
67a591a08c | ||
|
d517abd597 | ||
|
71f6856329 | ||
|
40c4269703 | ||
|
7329db55f3 | ||
|
0f1e1a3dd6 | ||
d6a31ec46f | |||
|
492d86457c | ||
|
a53aba545b | ||
|
df58dcc6ad | ||
|
6790fbac32 | ||
|
7a30476d89 | ||
|
02a70beeef | ||
|
7b97cf9177 | ||
|
f51b03ed79 | ||
|
c1b94f5c21 | ||
|
85cbc5bc71 | ||
|
cf3e506a8c | ||
|
7746ee3c2e | ||
|
d02962b17a | ||
|
be3f631edc | ||
|
5cd399a4b1 | ||
|
e324252963 | ||
|
834b7e4a69 | ||
|
318d61e7cf | ||
|
ecb2637bdc | ||
|
eaa337eef3 | ||
|
f4aa9b22a1 | ||
|
4d4b18d9c5 | ||
|
2d3d434873 | ||
|
acd4e5a7f4 | ||
|
75b5852aa6 | ||
|
790fef60cc | ||
|
1016d379be | ||
|
98fc9e2c66 | ||
|
0ede7b3d13 | ||
|
c2356cda3a | ||
|
b677179317 | ||
|
680488b51f | ||
|
b1604e9c9f | ||
|
3bcb12eff9 | ||
|
1299f7ce07 | ||
253f0d9b18 | |||
|
ede761f6c8 | ||
4f37a3bee3 | |||
|
24adbf71bb | ||
|
ab5d45199b | ||
a4f1777014 | |||
|
fbbe66a2af | ||
|
4293c5a6c3 | ||
|
1ee1bdeaa9 | ||
|
415d303b93 | ||
|
bcce1ecda9 | ||
|
1a9e317412 | ||
|
1109e23dd5 | ||
|
0bd5939a7e | ||
|
06aae28094 | ||
a09e1e1d8e | |||
|
2f91700074 | ||
|
35b3cec2d4 | ||
|
f984acaa5c | ||
|
30b228ef0f | ||
|
d44e257163 | ||
|
7c789e9213 | ||
|
c5cf6d1c7b | ||
|
7e215cb2b5 | ||
|
dd3e286ef8 | ||
|
661a8000cd | ||
|
761cd7aa4e | ||
|
300ed5fe03 | ||
66c60d9f14 | |||
99df628f55 | |||
205adad8ba | |||
425a6fc36c | |||
77aa0c0753 | |||
11f9a35abf | |||
|
c9b7f66925 | ||
46fd196019 | |||
f79995a80d | |||
|
7003b564a3 | ||
06b5925e85 | |||
|
3075185a7a | ||
|
9a72a48c6b | ||
|
3bc4302ef0 | ||
|
ed12fb5fe0 | ||
6dd3f707c3 | |||
|
e9850bb22e | ||
c567977205 | |||
|
8a6b074509 | ||
8354132677 | |||
9335ade6c4 | |||
|
51cbd2e8bb | ||
|
4d07ca7662 | ||
|
68ce9b17fe | ||
|
d1540db533 | ||
|
66121ec7a9 | ||
d1053e4b8a | |||
|
f33711acb0 | ||
|
18c3f3975f | ||
|
e3a11648c9 | ||
|
a02a2341d1 | ||
|
02fcfa26ee | ||
|
14ae45fe95 | ||
|
cdd902abde | ||
|
8e68524d15 | ||
|
22397879ce | ||
|
28dfb69c9a | ||
|
1c246c85e7 | ||
|
e3c19c947e | ||
50cd984ae4 | |||
|
1994618a21 | ||
|
9fa4d59f10 | ||
|
83ea77e0fb | ||
|
2668533196 | ||
16b72778cd | |||
f2302145ec | |||
e3814064a7 | |||
7d93959009 | |||
|
b7fe70d8c1 | ||
937fd3eb4e | |||
31ff759929 | |||
|
ed3f280c48 | ||
|
57d01928b3 | ||
|
2069566ab9 | ||
|
1f7c8dd1b0 | ||
|
139514cac8 | ||
|
7875a793b3 | ||
c6d1e06fe9 | |||
|
9e94d404f8 | ||
|
67dd5d164f | ||
|
d07ed0a90a | ||
|
e7bc05a446 | ||
|
3d65ff6c02 | ||
|
52b814945e | ||
|
44ca1d14b7 | ||
|
007fdb3e85 | ||
|
8599afcd11 | ||
|
51aa169ca3 | ||
|
633a83cc7c | ||
|
a6882ce693 | ||
|
403b5292e5 | ||
|
2146883168 | ||
|
da5a740fd4 | ||
|
b793697f68 | ||
|
d705f3685f |
129 changed files with 24153 additions and 6619 deletions
|
@ -1,9 +0,0 @@
|
||||||
generate_translations.js
|
|
||||||
webpack.config.js
|
|
||||||
src/shared/build-config.js
|
|
||||||
src/api_tests
|
|
||||||
**/*.png
|
|
||||||
**/*.css
|
|
||||||
**/*.scss
|
|
||||||
**/*.svg
|
|
||||||
src/shared/translations/**
|
|
|
@ -1,55 +0,0 @@
|
||||||
{
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"browser": true
|
|
||||||
},
|
|
||||||
"plugins": ["@typescript-eslint", "jsx-a11y", "prettier"],
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"plugin:inferno/recommended",
|
|
||||||
"plugin:jsx-a11y/recommended"
|
|
||||||
],
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"project": "./tsconfig.json",
|
|
||||||
"warnOnUnsupportedTypeScriptVersion": false
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"@typescript-eslint/ban-ts-comment": 0,
|
|
||||||
"@typescript-eslint/no-explicit-any": 0,
|
|
||||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
|
||||||
"@typescript-eslint/no-empty-function": 0,
|
|
||||||
"@typescript-eslint/no-non-null-assertion": 0,
|
|
||||||
"@typescript-eslint/no-unused-vars": [
|
|
||||||
"error",
|
|
||||||
{ "argsIgnorePattern": "^_" }
|
|
||||||
],
|
|
||||||
"arrow-body-style": 0,
|
|
||||||
"curly": 0,
|
|
||||||
"eol-last": 0,
|
|
||||||
"eqeqeq": "error",
|
|
||||||
"func-style": 0,
|
|
||||||
"import/no-duplicates": 0,
|
|
||||||
"max-statements": 0,
|
|
||||||
"max-params": 0,
|
|
||||||
"new-cap": 0,
|
|
||||||
"no-console": 0,
|
|
||||||
"no-duplicate-imports": 0,
|
|
||||||
"no-extra-parens": 0,
|
|
||||||
"no-return-assign": 0,
|
|
||||||
"no-throw-literal": 0,
|
|
||||||
"no-trailing-spaces": 0,
|
|
||||||
"no-unused-expressions": 0,
|
|
||||||
"no-useless-constructor": 0,
|
|
||||||
"no-useless-escape": 0,
|
|
||||||
"no-var": 0,
|
|
||||||
"prefer-const": "error",
|
|
||||||
"prefer-rest-params": 0,
|
|
||||||
"prettier/prettier": "error",
|
|
||||||
"quote-props": 0,
|
|
||||||
"unicorn/filename-case": 0,
|
|
||||||
"jsx-a11y/media-has-caption": 0,
|
|
||||||
"jsx-a11y/label-has-associated-control": 0
|
|
||||||
}
|
|
||||||
}
|
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
@ -1 +1 @@
|
||||||
* @dessalines @SleeplessOne1917
|
* @dessalines @SleeplessOne1917 @matc-pub
|
||||||
|
|
|
@ -38,10 +38,13 @@ steps:
|
||||||
|
|
||||||
publish_release_docker:
|
publish_release_docker:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
secrets: [docker_username, docker_password]
|
|
||||||
settings:
|
settings:
|
||||||
repo: dessalines/lemmy-ui
|
repo: dessalines/lemmy-ui
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
platforms: linux/amd64, linux/arm64
|
platforms: linux/amd64, linux/arm64
|
||||||
tag: ${CI_COMMIT_TAG}
|
tag: ${CI_COMMIT_TAG}
|
||||||
when:
|
when:
|
||||||
|
@ -49,10 +52,13 @@ steps:
|
||||||
|
|
||||||
nightly_build:
|
nightly_build:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
secrets: [docker_username, docker_password]
|
|
||||||
settings:
|
settings:
|
||||||
repo: dessalines/lemmy-ui
|
repo: dessalines/lemmy-ui
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
platforms: linux/amd64, linux/arm64
|
platforms: linux/amd64, linux/arm64
|
||||||
tag: dev
|
tag: dev
|
||||||
when:
|
when:
|
||||||
|
|
3342
CHANGELOG.md
Normal file
3342
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load diff
26
cliff.toml
26
cliff.toml
|
@ -14,18 +14,19 @@ body = """
|
||||||
|
|
||||||
{%- if version %} in {{ version }}{%- endif -%}
|
{%- if version %} in {{ version }}{%- endif -%}
|
||||||
{% for commit in commits %}
|
{% for commit in commits %}
|
||||||
{% if commit.github.pr_title -%}
|
{% if commit.remote.pr_title -%}
|
||||||
{%- set commit_message = commit.github.pr_title -%}
|
{%- set commit_message = commit.remote.pr_title -%}
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
{%- set commit_message = commit.message -%}
|
{%- set commit_message = commit.message -%}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
* {{ commit_message | split(pat="\n") | first | trim }}\
|
* {{ commit_message | split(pat="\n") | first | trim }}\
|
||||||
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif -%}
|
{% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%}
|
||||||
{% if commit.github.pr_number %} in \
|
{% if commit.remote.pr_number %} in \
|
||||||
[#{{ commit.github.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.github.pr_number }}) \
|
[#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
|
||||||
|
{%- if github -%}
|
||||||
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
|
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
|
||||||
{% raw %}\n{% endraw -%}
|
{% raw %}\n{% endraw -%}
|
||||||
## New Contributors
|
## New Contributors
|
||||||
|
@ -36,6 +37,7 @@ body = """
|
||||||
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
|
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
{% if version %}
|
{% if version %}
|
||||||
{% if previous.version %}
|
{% if previous.version %}
|
||||||
|
@ -51,7 +53,7 @@ body = """
|
||||||
"""
|
"""
|
||||||
# remove the leading and trailing whitespace from the template
|
# remove the leading and trailing whitespace from the template
|
||||||
trim = true
|
trim = true
|
||||||
# changelog footer
|
# template for the changelog footer
|
||||||
footer = """
|
footer = """
|
||||||
<!-- generated by git-cliff -->
|
<!-- generated by git-cliff -->
|
||||||
"""
|
"""
|
||||||
|
@ -70,16 +72,12 @@ commit_preprocessors = [
|
||||||
# remove issue numbers from commits
|
# remove issue numbers from commits
|
||||||
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
|
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
|
||||||
]
|
]
|
||||||
# protect breaking changes from being skipped due to matching a skipping commit_parser
|
commit_parsers = [
|
||||||
protect_breaking_commits = false
|
{ field = "author.name", pattern = "renovate", skip = true },
|
||||||
|
{ field = "message", pattern = "Upping version", skip = true },
|
||||||
|
]
|
||||||
# filter out the commits that are not matched by commit parsers
|
# filter out the commits that are not matched by commit parsers
|
||||||
filter_commits = false
|
filter_commits = false
|
||||||
# regex for matching git tags
|
|
||||||
tag_pattern = "v[0-9].*"
|
|
||||||
# regex for skipping tags
|
|
||||||
skip_tags = "beta|alpha"
|
|
||||||
# regex for ignoring tags
|
|
||||||
ignore_tags = "rc"
|
|
||||||
# sort the tags topologically
|
# sort the tags topologically
|
||||||
topo_order = false
|
topo_order = false
|
||||||
# sort the commits inside sections by oldest/newest order
|
# sort the commits inside sections by oldest/newest order
|
||||||
|
|
95
eslint.config.mjs
Normal file
95
eslint.config.mjs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
import pluginJs from "@eslint/js";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
import prettier from "eslint-plugin-prettier/recommended";
|
||||||
|
import jsxa11y from "eslint-plugin-jsx-a11y";
|
||||||
|
import inferno from "eslint-plugin-inferno";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
pluginJs.configs.recommended,
|
||||||
|
...tseslint.configs.recommended,
|
||||||
|
prettier,
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
inferno: inferno,
|
||||||
|
rules: inferno.configs.recommended,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
"jsx-a11y": jsxa11y,
|
||||||
|
},
|
||||||
|
rules: jsxa11y.configs.recommended.rules,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
parser: tseslint.parser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// For some reason this has to be in its own block
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
"generate_translations.js",
|
||||||
|
"webpack.config.js",
|
||||||
|
"src/shared/build-config.js",
|
||||||
|
"src/api_tests",
|
||||||
|
"**/*.png",
|
||||||
|
"**/*.css",
|
||||||
|
"**/*.scss",
|
||||||
|
"**/*.svg",
|
||||||
|
"src/shared/translations/**",
|
||||||
|
"dist/*",
|
||||||
|
".yalc/*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["src/**/*.js", "src/**/*.mjs", "src/**/*.ts", "src/**/*.tsx"],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/ban-ts-comment": 0,
|
||||||
|
"@typescript-eslint/no-explicit-any": 0,
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{ argsIgnorePattern: "^_" },
|
||||||
|
],
|
||||||
|
"explicit-module-boundary-types": 0,
|
||||||
|
"no-empty-function": 0,
|
||||||
|
"no-non-null-assertion": 0,
|
||||||
|
"arrow-body-style": 0,
|
||||||
|
curly: 0,
|
||||||
|
"eol-last": 0,
|
||||||
|
eqeqeq: "error",
|
||||||
|
"func-style": 0,
|
||||||
|
"import/no-duplicates": 0,
|
||||||
|
"max-statements": 0,
|
||||||
|
"max-params": 0,
|
||||||
|
"new-cap": 0,
|
||||||
|
"no-console": 0,
|
||||||
|
"no-duplicate-imports": 0,
|
||||||
|
"no-extra-parens": 0,
|
||||||
|
"no-return-assign": 0,
|
||||||
|
"no-throw-literal": 0,
|
||||||
|
"no-trailing-spaces": 0,
|
||||||
|
"no-unused-expressions": 0,
|
||||||
|
"no-useless-constructor": 0,
|
||||||
|
"no-useless-escape": 0,
|
||||||
|
"no-var": 0,
|
||||||
|
"prefer-const": "error",
|
||||||
|
"prefer-rest-params": 0,
|
||||||
|
"prettier/prettier": "error",
|
||||||
|
"quote-props": 0,
|
||||||
|
"unicorn/filename-case": 0,
|
||||||
|
"jsx-a11y/media-has-caption": 0,
|
||||||
|
"jsx-a11y/label-has-associated-control": 0,
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
group: ["assets/*", "client/*", "server/*", "shared/*"],
|
||||||
|
message: "Use relative import instead.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
6
generate_changelog.sh
Executable file
6
generate_changelog.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Adding to CHANGELOG.md
|
||||||
|
git cliff --output CHANGELOG.md
|
||||||
|
prettier -w CHANGELOG.md
|
|
@ -1 +1 @@
|
||||||
Subproject commit f0ab81deea347c433277a90ae752b10f68473719
|
Subproject commit 2bde7acef9807d28cb13b6584fc63d7b8a457005
|
108
package.json
108
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "lemmy-ui",
|
"name": "lemmy-ui",
|
||||||
"description": "An isomorphic UI for lemmy",
|
"description": "An isomorphic UI for lemmy",
|
||||||
"version": "0.19.4-beta.7",
|
"version": "0.19.6-beta.7",
|
||||||
"author": "Dessalines <tyhou13@gmx.com>",
|
"author": "Dessalines <tyhou13@gmx.com>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
"build:prod": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=production",
|
"build:prod": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=production",
|
||||||
"clean": "pnpm rimraf dist",
|
"clean": "pnpm rimraf dist",
|
||||||
"dev": "node generate_translations.js && pnpm build:dev --watch",
|
"dev": "node generate_translations.js && pnpm build:dev --watch",
|
||||||
"lint": "pnpm translations:generate && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx \"src/**\" && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"",
|
"lint": "pnpm translations:generate && tsc --noEmit && pnpm eslint --report-unused-disable-directives && pnpm prettier --check \"src/**/*.{ts,tsx,js,mjs,css,scss}\"",
|
||||||
"prebuild:dev": "pnpm clean && node generate_translations.js",
|
"prebuild:dev": "pnpm clean && node generate_translations.js",
|
||||||
"prebuild:prod": "pnpm clean && node generate_translations.js",
|
"prebuild:prod": "pnpm clean && node generate_translations.js",
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
|
@ -25,15 +25,14 @@
|
||||||
"node": ">=8.9.0"
|
"node": ">=8.9.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/plugin-proposal-decorators": "^7.24.1",
|
"@babel/plugin-proposal-decorators": "^7.24.7",
|
||||||
"@babel/plugin-transform-class-properties": "^7.24.1",
|
"@babel/plugin-transform-class-properties": "^7.25.4",
|
||||||
"@babel/plugin-transform-runtime": "^7.24.3",
|
"@babel/plugin-transform-runtime": "^7.25.4",
|
||||||
"@babel/plugin-transform-typescript": "^7.24.1",
|
"@babel/plugin-transform-typescript": "^7.25.2",
|
||||||
"@babel/preset-env": "^7.24.3",
|
"@babel/preset-env": "^7.25.4",
|
||||||
"@babel/preset-typescript": "^7.24.1",
|
"@babel/preset-typescript": "^7.24.7",
|
||||||
"@babel/runtime": "^7.24.1",
|
"@babel/runtime": "^7.25.4",
|
||||||
"@emoji-mart/data": "^1.1.2",
|
"@emoji-mart/data": "^1.2.1",
|
||||||
"@shortcm/qr-image": "^9.0.4",
|
|
||||||
"autosize": "^6.0.1",
|
"autosize": "^6.0.1",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"babel-plugin-inferno": "^6.7.1",
|
"babel-plugin-inferno": "^6.7.1",
|
||||||
|
@ -41,18 +40,18 @@
|
||||||
"check-password-strength": "^2.0.10",
|
"check-password-strength": "^2.0.10",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"cookie": "^0.6.0",
|
"cookie": "^1.0.0",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"copy-webpack-plugin": "^12.0.2",
|
"copy-webpack-plugin": "^12.0.2",
|
||||||
"css-loader": "^6.10.0",
|
"css-loader": "^7.1.2",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^4.0.0",
|
||||||
"emoji-mart": "^5.5.2",
|
"emoji-mart": "^5.6.0",
|
||||||
"emoji-short-name": "^2.0.0",
|
"emoji-short-name": "^2.0.0",
|
||||||
"express": "~4.19.2",
|
"express": "~4.21.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.10.0",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
"i18next": "^23.10.1",
|
"i18next": "^23.14.0",
|
||||||
"inferno": "^8.2.3",
|
"inferno": "^8.2.3",
|
||||||
"inferno-create-element": "^8.2.3",
|
"inferno-create-element": "^8.2.3",
|
||||||
"inferno-helmet": "^5.2.1",
|
"inferno-helmet": "^5.2.1",
|
||||||
|
@ -61,37 +60,39 @@
|
||||||
"inferno-router": "^8.2.3",
|
"inferno-router": "^8.2.3",
|
||||||
"inferno-server": "^8.2.3",
|
"inferno-server": "^8.2.3",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"lemmy-js-client": "0.19.4-alpha.18",
|
"lemmy-js-client": "0.20.0-alpha.17",
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"markdown-it-bidi": "^0.1.0",
|
"markdown-it-bidi": "^0.2.0",
|
||||||
"markdown-it-container": "^4.0.0",
|
"markdown-it-container": "^4.0.0",
|
||||||
"markdown-it-emoji": "^3.0.0",
|
"markdown-it-emoji": "^3.0.0",
|
||||||
"markdown-it-footnote": "^4.0.0",
|
"markdown-it-footnote": "^4.0.0",
|
||||||
"markdown-it-highlightjs": "^4.0.1",
|
"markdown-it-highlightjs": "^4.1.0",
|
||||||
"markdown-it-html5-embed": "^1.0.0",
|
"markdown-it-html5-embed": "^1.0.0",
|
||||||
"markdown-it-ruby": "^0.1.1",
|
"markdown-it-ruby": "^1.0.0",
|
||||||
"markdown-it-sub": "^2.0.0",
|
"markdown-it-sub": "^2.0.0",
|
||||||
"markdown-it-sup": "^2.0.0",
|
"markdown-it-sup": "^2.0.0",
|
||||||
"mini-css-extract-plugin": "^2.8.1",
|
"mini-css-extract-plugin": "^2.9.1",
|
||||||
|
"qreator": "^9.3.0",
|
||||||
"register-service-worker": "^1.7.2",
|
"register-service-worker": "^1.7.2",
|
||||||
"run-node-webpack-plugin": "^1.3.0",
|
"run-node-webpack-plugin": "^1.3.0",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"sanitize-html": "^2.13.0",
|
"sanitize-html": "^2.13.0",
|
||||||
"sass": "^1.72.0",
|
"sass": "^1.77.8",
|
||||||
"sass-loader": "^14.1.1",
|
"sass-loader": "^16.0.1",
|
||||||
"serialize-javascript": "^6.0.2",
|
"serialize-javascript": "^6.0.2",
|
||||||
"service-worker-webpack": "^1.0.0",
|
"service-worker-webpack": "^1.0.0",
|
||||||
"sharp": "0.33.3",
|
"sharp": "0.33.5",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"toastify-js": "^1.12.0",
|
"toastify-js": "^1.12.0",
|
||||||
"tributejs": "^5.1.3",
|
"tributejs": "^5.1.3",
|
||||||
"webpack": "^5.91.0",
|
"webpack": "^5.94.0",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack-node-externals": "^3.0.0"
|
"webpack-node-externals": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.3",
|
"@babel/core": "^7.25.2",
|
||||||
|
"@eslint/js": "^9.9.1",
|
||||||
"@types/autosize": "^4.0.3",
|
"@types/autosize": "^4.0.3",
|
||||||
"@types/bootstrap": "^5.2.10",
|
"@types/bootstrap": "^5.2.10",
|
||||||
"@types/cookie": "^0.6.0",
|
"@types/cookie": "^0.6.0",
|
||||||
|
@ -99,35 +100,38 @@
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/html-to-text": "^9.0.4",
|
"@types/html-to-text": "^9.0.4",
|
||||||
"@types/lodash.isequal": "^4.5.8",
|
"@types/lodash.isequal": "^4.5.8",
|
||||||
"@types/markdown-it": "^13.0.7",
|
"@types/markdown-it": "^14.1.2",
|
||||||
"@types/markdown-it-container": "^2.0.9",
|
"@types/markdown-it-container": "^2.0.10",
|
||||||
"@types/node": "^20.11.30",
|
"@types/node": "^22.5.0",
|
||||||
"@types/path-browserify": "^1.0.2",
|
"@types/path-browserify": "^1.0.3",
|
||||||
"@types/sanitize-html": "^2.11.0",
|
"@types/sanitize-html": "^2.13.0",
|
||||||
"@types/serialize-javascript": "^5.0.4",
|
"@types/serialize-javascript": "^5.0.4",
|
||||||
"@types/toastify-js": "^1.12.3",
|
"@types/toastify-js": "^1.12.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
"@typescript-eslint/eslint-plugin": "^8.3.0",
|
||||||
"@typescript-eslint/parser": "^7.4.0",
|
"@typescript-eslint/parser": "^8.3.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-inferno": "^7.33.3",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-inferno": "^7.34.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-jsx-a11y": "^6.9.0",
|
||||||
"husky": "^9.0.11",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
|
"globals": "^15.9.0",
|
||||||
|
"husky": "^9.1.5",
|
||||||
"import-sort-style-module": "^6.0.0",
|
"import-sort-style-module": "^6.0.0",
|
||||||
"lint-staged": "^15.2.2",
|
"lint-staged": "^15.2.9",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.3.3",
|
||||||
"prettier-plugin-import-sort": "^0.0.7",
|
"prettier-plugin-import-sort": "^0.0.7",
|
||||||
"prettier-plugin-organize-imports": "^3.2.4",
|
"prettier-plugin-organize-imports": "^4.0.0",
|
||||||
"prettier-plugin-packagejson": "^2.4.12",
|
"prettier-plugin-packagejson": "^2.5.2",
|
||||||
"qs": "^6.12.0",
|
"qs": "^6.13.0",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^6.0.1",
|
||||||
"sortpack": "^2.4.0",
|
"sortpack": "^2.4.0",
|
||||||
"style-loader": "^3.3.4",
|
"style-loader": "^4.0.0",
|
||||||
"terser": "^5.29.2",
|
"terser": "^5.31.6",
|
||||||
"typescript": "^5.4.3",
|
"typescript": "^5.5.4",
|
||||||
|
"typescript-eslint": "^8.3.0",
|
||||||
"typescript-language-server": "^4.3.3",
|
"typescript-language-server": "^4.3.3",
|
||||||
"webpack-bundle-analyzer": "^4.10.1",
|
"webpack-bundle-analyzer": "^4.10.2",
|
||||||
"webpack-dev-server": "5.0.4"
|
"webpack-dev-server": "5.1.0"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{css, scss}": [
|
"*.{css, scss}": [
|
||||||
|
@ -141,7 +145,7 @@
|
||||||
"sortpack"
|
"sortpack"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.1.0+sha512.67f5879916a9293e5cf059c23853d571beaf4f753c707f40cb22bed5fb1578c6aad3b6c4107ccb3ba0b35be003eb621a16471ac836c87beb53f9d54bb4612724",
|
"packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee",
|
||||||
"engineStrict": true,
|
"engineStrict": true,
|
||||||
"importSort": {
|
"importSort": {
|
||||||
".js, .jsx, .ts, .tsx": {
|
".js, .jsx, .ts, .tsx": {
|
||||||
|
|
5024
pnpm-lock.yaml
5024
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
7
renovate.json
Normal file
7
renovate.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": ["config:recommended"],
|
||||||
|
"schedule": ["every weekend"],
|
||||||
|
"automerge": true,
|
||||||
|
"ignoreDeps": ["lemmy-js-client"]
|
||||||
|
}
|
|
@ -461,3 +461,15 @@ br.big {
|
||||||
.totp-link {
|
.totp-link {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.oauth-item details[open] .oauth-item-caret {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-oauth-providers-section > ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
em-emoji-picker {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
|
@ -40,8 +40,8 @@ hr.my-3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -85,28 +85,28 @@ hr.my-3 {
|
||||||
--bs-danger-rgb: 231, 76, 60;
|
--bs-danger-rgb: 231, 76, 60;
|
||||||
--bs-light-rgb: 48, 48, 48;
|
--bs-light-rgb: 48, 48, 48;
|
||||||
--bs-dark-rgb: 222, 226, 230;
|
--bs-dark-rgb: 222, 226, 230;
|
||||||
--bs-primary-text-emphasis: #004b38;
|
--bs-primary-text-emphasis: rgb(0, 75.2, 56);
|
||||||
--bs-secondary-text-emphasis: #45484c;
|
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6);
|
||||||
--bs-success-text-emphasis: #004b38;
|
--bs-success-text-emphasis: rgb(0, 75.2, 56);
|
||||||
--bs-info-text-emphasis: #153d58;
|
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
|
||||||
--bs-warning-text-emphasis: #613e07;
|
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
|
||||||
--bs-danger-text-emphasis: #5c1e18;
|
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
|
||||||
--bs-light-text-emphasis: #444;
|
--bs-light-text-emphasis: #444;
|
||||||
--bs-dark-text-emphasis: #444;
|
--bs-dark-text-emphasis: #444;
|
||||||
--bs-primary-bg-subtle: #ccf2e8;
|
--bs-primary-bg-subtle: rgb(204, 241.6, 232);
|
||||||
--bs-secondary-bg-subtle: #eff0f2;
|
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8);
|
||||||
--bs-success-bg-subtle: #ccf2e8;
|
--bs-success-bg-subtle: rgb(204, 241.6, 232);
|
||||||
--bs-info-bg-subtle: #d6eaf8;
|
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-warning-bg-subtle: #fdebd0;
|
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-danger-bg-subtle: #fadbd8;
|
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #99e4d1;
|
--bs-primary-border-subtle: rgb(153, 228.2, 209);
|
||||||
--bs-secondary-border-subtle: #dee1e5;
|
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6);
|
||||||
--bs-success-border-subtle: #99e4d1;
|
--bs-success-border-subtle: rgb(153, 228.2, 209);
|
||||||
--bs-info-border-subtle: #aed6f1;
|
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
|
||||||
--bs-warning-border-subtle: #fad7a0;
|
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
|
||||||
--bs-danger-border-subtle: #f5b7b1;
|
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
|
||||||
--bs-light-border-subtle: #ebebeb;
|
--bs-light-border-subtle: #ebebeb;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
--bs-white-rgb: 255, 255, 255;
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
@ -137,7 +137,7 @@ hr.my-3 {
|
||||||
--bs-link-color: #00bc8c;
|
--bs-link-color: #00bc8c;
|
||||||
--bs-link-color-rgb: 0, 188, 140;
|
--bs-link-color-rgb: 0, 188, 140;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #009670;
|
--bs-link-hover-color: rgb(0, 150.4, 112);
|
||||||
--bs-link-hover-color-rgb: 0, 150, 112;
|
--bs-link-hover-color-rgb: 0, 150, 112;
|
||||||
--bs-code-color: #d63384;
|
--bs-code-color: #d63384;
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
|
@ -182,44 +182,44 @@ hr.my-3 {
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #292929;
|
--bs-tertiary-bg: #292929;
|
||||||
--bs-tertiary-bg-rgb: 41, 41, 41;
|
--bs-tertiary-bg-rgb: 41, 41, 41;
|
||||||
--bs-primary-text-emphasis: #66d7ba;
|
--bs-primary-text-emphasis: rgb(102, 214.8, 186);
|
||||||
--bs-secondary-text-emphasis: #ced3d7;
|
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4);
|
||||||
--bs-success-text-emphasis: #66d7ba;
|
--bs-success-text-emphasis: rgb(102, 214.8, 186);
|
||||||
--bs-info-text-emphasis: #85c1e9;
|
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
|
||||||
--bs-warning-text-emphasis: #f8c471;
|
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
|
||||||
--bs-danger-text-emphasis: #f1948a;
|
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #00261c;
|
--bs-primary-bg-subtle: rgb(0, 37.6, 28);
|
||||||
--bs-secondary-bg-subtle: #232426;
|
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8);
|
||||||
--bs-success-bg-subtle: #00261c;
|
--bs-success-bg-subtle: rgb(0, 37.6, 28);
|
||||||
--bs-info-bg-subtle: #0a1e2c;
|
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
|
||||||
--bs-warning-bg-subtle: #311f04;
|
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
|
||||||
--bs-danger-bg-subtle: #2e0f0c;
|
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
|
||||||
--bs-light-bg-subtle: #303030;
|
--bs-light-bg-subtle: #303030;
|
||||||
--bs-dark-bg-subtle: #181818;
|
--bs-dark-bg-subtle: #181818;
|
||||||
--bs-primary-border-subtle: #007154;
|
--bs-primary-border-subtle: rgb(0, 112.8, 84);
|
||||||
--bs-secondary-border-subtle: #686d71;
|
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4);
|
||||||
--bs-success-border-subtle: #007154;
|
--bs-success-border-subtle: rgb(0, 112.8, 84);
|
||||||
--bs-info-border-subtle: #1f5b83;
|
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
|
||||||
--bs-warning-border-subtle: #925e0b;
|
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
|
||||||
--bs-danger-border-subtle: #8b2e24;
|
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
|
||||||
--bs-light-border-subtle: #444;
|
--bs-light-border-subtle: #444;
|
||||||
--bs-dark-border-subtle: #303030;
|
--bs-dark-border-subtle: #303030;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #66d7ba;
|
--bs-link-color: rgb(102, 214.8, 186);
|
||||||
--bs-link-hover-color: #85dfc8;
|
--bs-link-hover-color: rgb(132.6, 222.84, 199.8);
|
||||||
--bs-link-color-rgb: 102, 215, 186;
|
--bs-link-color-rgb: 102, 215, 186;
|
||||||
--bs-link-hover-color-rgb: 133, 223, 200;
|
--bs-link-hover-color-rgb: 133, 223, 200;
|
||||||
--bs-code-color: #e685b5;
|
--bs-code-color: rgb(230.4, 132.6, 181.2);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #333;
|
--bs-highlight-bg: #333;
|
||||||
--bs-border-color: #444;
|
--bs-border-color: #444;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #66d7ba;
|
--bs-form-valid-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-valid-border-color: #66d7ba;
|
--bs-form-valid-border-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-invalid-color: #f1948a;
|
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
|
||||||
--bs-form-invalid-border-color: #f1948a;
|
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -1951,13 +1951,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf2e8;
|
--bs-table-bg: rgb(204, 241.6, 232);
|
||||||
--bs-table-border-color: #a3c2ba;
|
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
|
||||||
--bs-table-striped-bg: #c2e6dc;
|
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dad1;
|
--bs-table-active-bg: rgb(183.6, 217.44, 208.8);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde0d7;
|
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1965,13 +1965,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #eff0f2;
|
--bs-table-bg: rgb(238.6, 240.2, 241.8);
|
||||||
--bs-table-border-color: #bfc0c2;
|
--bs-table-border-color: rgb(190.88, 192.16, 193.44);
|
||||||
--bs-table-striped-bg: #e3e4e6;
|
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #d7d8da;
|
--bs-table-active-bg: rgb(214.74, 216.18, 217.62);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #dddee0;
|
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1979,13 +1979,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf2e8;
|
--bs-table-bg: rgb(204, 241.6, 232);
|
||||||
--bs-table-border-color: #a3c2ba;
|
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
|
||||||
--bs-table-striped-bg: #c2e6dc;
|
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dad1;
|
--bs-table-active-bg: rgb(183.6, 217.44, 208.8);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde0d7;
|
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1993,13 +1993,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #d6eaf8;
|
--bs-table-bg: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-table-border-color: #abbbc6;
|
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
|
||||||
--bs-table-striped-bg: #cbdeec;
|
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c1d3df;
|
--bs-table-active-bg: rgb(192.96, 210.96, 223.02);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #c6d8e5;
|
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2007,13 +2007,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fdebd0;
|
--bs-table-bg: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-table-border-color: #cabca6;
|
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
|
||||||
--bs-table-striped-bg: #f0dfc6;
|
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e4d4bb;
|
--bs-table-active-bg: rgb(227.34, 211.68, 186.84);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ead9c0;
|
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2021,13 +2021,13 @@ progress {
|
||||||
|
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fadbd8;
|
--bs-table-bg: rgb(250.2, 219.2, 216);
|
||||||
--bs-table-border-color: #c8afad;
|
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
|
||||||
--bs-table-striped-bg: #eed0cd;
|
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e1c5c2;
|
--bs-table-active-bg: rgb(225.18, 197.28, 194.4);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #e7cbc8;
|
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2036,12 +2036,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #303030;
|
--bs-table-bg: #303030;
|
||||||
--bs-table-border-color: #595959;
|
--bs-table-border-color: rgb(89.4, 89.4, 89.4);
|
||||||
--bs-table-striped-bg: #3a3a3a;
|
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #454545;
|
--bs-table-active-bg: rgb(68.7, 68.7, 68.7);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #404040;
|
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2050,12 +2050,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #dee2e6;
|
--bs-table-bg: #dee2e6;
|
||||||
--bs-table-border-color: #b2b5b8;
|
--bs-table-border-color: rgb(177.6, 180.8, 184);
|
||||||
--bs-table-striped-bg: #d3d7db;
|
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c8cbcf;
|
--bs-table-active-bg: rgb(199.8, 203.4, 207);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #cdd1d5;
|
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2155,7 +2155,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2173,7 +2173,7 @@ progress {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.form-control:disabled {
|
.form-control:disabled {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.form-control::file-selector-button {
|
.form-control::file-selector-button {
|
||||||
|
@ -2300,7 +2300,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2309,7 +2309,7 @@ textarea.form-control-lg {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
.form-select:disabled {
|
.form-select:disabled {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
}
|
}
|
||||||
.form-select:-moz-focusring {
|
.form-select:-moz-focusring {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
@ -2384,7 +2384,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2431,7 +2431,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2380dec6'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 221.5, 197.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2501,7 +2501,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #b3ebdd;
|
background-color: rgb(178.5, 234.9, 220.5);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2527,7 +2527,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #b3ebdd;
|
background-color: rgb(178.5, 234.9, 220.5);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2634,7 +2634,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.form-floating > :disabled ~ label::after,
|
.form-floating > :disabled ~ label::after,
|
||||||
.form-floating > .form-control:disabled ~ label::after {
|
.form-floating > .form-control:disabled ~ label::after {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group {
|
.input-group {
|
||||||
|
@ -2975,6 +2975,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2988,12 +2991,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00bc8c;
|
--bs-btn-bg: #00bc8c;
|
||||||
--bs-btn-border-color: #00bc8c;
|
--bs-btn-border-color: #00bc8c;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #26c69d;
|
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
|
||||||
--bs-btn-hover-border-color: #1ac398;
|
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #33c9a3;
|
--bs-btn-active-bg: rgb(51, 201.4, 163);
|
||||||
--bs-btn-active-border-color: #1ac398;
|
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #00bc8c;
|
--bs-btn-disabled-bg: #00bc8c;
|
||||||
|
@ -3005,12 +3008,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #adb5bd;
|
--bs-btn-bg: #adb5bd;
|
||||||
--bs-btn-border-color: #adb5bd;
|
--bs-btn-border-color: #adb5bd;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #b9c0c7;
|
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9);
|
||||||
--bs-btn-hover-border-color: #b5bcc4;
|
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6);
|
||||||
--bs-btn-focus-shadow-rgb: 147, 154, 161;
|
--bs-btn-focus-shadow-rgb: 147, 154, 161;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #bdc4ca;
|
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2);
|
||||||
--bs-btn-active-border-color: #b5bcc4;
|
--bs-btn-active-border-color: rgb(181.2, 188.4, 195.6);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #adb5bd;
|
--bs-btn-disabled-bg: #adb5bd;
|
||||||
|
@ -3022,12 +3025,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00bc8c;
|
--bs-btn-bg: #00bc8c;
|
||||||
--bs-btn-border-color: #00bc8c;
|
--bs-btn-border-color: #00bc8c;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #26c69d;
|
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
|
||||||
--bs-btn-hover-border-color: #1ac398;
|
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #33c9a3;
|
--bs-btn-active-bg: rgb(51, 201.4, 163);
|
||||||
--bs-btn-active-border-color: #1ac398;
|
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #00bc8c;
|
--bs-btn-disabled-bg: #00bc8c;
|
||||||
|
@ -3039,12 +3042,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #3498db;
|
--bs-btn-bg: #3498db;
|
||||||
--bs-btn-border-color: #3498db;
|
--bs-btn-border-color: #3498db;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #2c81ba;
|
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15);
|
||||||
--bs-btn-hover-border-color: #2a7aaf;
|
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2);
|
||||||
--bs-btn-focus-shadow-rgb: 82, 167, 224;
|
--bs-btn-focus-shadow-rgb: 82, 167, 224;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #2a7aaf;
|
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2);
|
||||||
--bs-btn-active-border-color: #2772a4;
|
--bs-btn-active-border-color: rgb(39, 114, 164.25);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #3498db;
|
--bs-btn-disabled-bg: #3498db;
|
||||||
|
@ -3056,12 +3059,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f39c12;
|
--bs-btn-bg: #f39c12;
|
||||||
--bs-btn-border-color: #f39c12;
|
--bs-btn-border-color: #f39c12;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #f5ab36;
|
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
|
||||||
--bs-btn-hover-border-color: #f4a62a;
|
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #f5b041;
|
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
|
||||||
--bs-btn-active-border-color: #f4a62a;
|
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #f39c12;
|
--bs-btn-disabled-bg: #f39c12;
|
||||||
|
@ -3073,12 +3076,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #e74c3c;
|
--bs-btn-bg: #e74c3c;
|
||||||
--bs-btn-border-color: #e74c3c;
|
--bs-btn-border-color: #e74c3c;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #c44133;
|
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
|
||||||
--bs-btn-hover-border-color: #b93d30;
|
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-focus-shadow-rgb: 235, 103, 89;
|
--bs-btn-focus-shadow-rgb: 235, 103, 89;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #b93d30;
|
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-active-border-color: #ad392d;
|
--bs-btn-active-border-color: rgb(173.25, 57, 45);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #e74c3c;
|
--bs-btn-disabled-bg: #e74c3c;
|
||||||
|
@ -3090,11 +3093,11 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #303030;
|
--bs-btn-bg: #303030;
|
||||||
--bs-btn-border-color: #303030;
|
--bs-btn-border-color: #303030;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #292929;
|
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8);
|
||||||
--bs-btn-hover-border-color: #262626;
|
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4);
|
||||||
--bs-btn-focus-shadow-rgb: 79, 79, 79;
|
--bs-btn-focus-shadow-rgb: 79, 79, 79;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #262626;
|
--bs-btn-active-bg: rgb(38.4, 38.4, 38.4);
|
||||||
--bs-btn-active-border-color: #242424;
|
--bs-btn-active-border-color: #242424;
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
|
@ -3107,12 +3110,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #dee2e6;
|
--bs-btn-bg: #dee2e6;
|
||||||
--bs-btn-border-color: #dee2e6;
|
--bs-btn-border-color: #dee2e6;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #e3e6ea;
|
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
|
||||||
--bs-btn-hover-border-color: #e1e5e9;
|
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #e5e8eb;
|
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
|
||||||
--bs-btn-active-border-color: #e1e5e9;
|
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #dee2e6;
|
--bs-btn-disabled-bg: #dee2e6;
|
||||||
|
@ -4499,12 +4502,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23dee2e6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23004b38'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%280, 75.2, 56%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #80dec6;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4562,7 +4564,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4580,7 +4581,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4591,11 +4592,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4604,27 +4605,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -4669,16 +4670,16 @@ textarea.form-control-lg {
|
||||||
--bs-pagination-border-color: transparent;
|
--bs-pagination-border-color: transparent;
|
||||||
--bs-pagination-border-radius: var(--bs-border-radius);
|
--bs-pagination-border-radius: var(--bs-border-radius);
|
||||||
--bs-pagination-hover-color: #fff;
|
--bs-pagination-hover-color: #fff;
|
||||||
--bs-pagination-hover-bg: #00efb2;
|
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-hover-border-color: transparent;
|
--bs-pagination-hover-border-color: transparent;
|
||||||
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
||||||
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
||||||
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
--bs-pagination-active-color: #fff;
|
--bs-pagination-active-color: #fff;
|
||||||
--bs-pagination-active-bg: #00efb2;
|
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-active-border-color: transparent;
|
--bs-pagination-active-border-color: transparent;
|
||||||
--bs-pagination-disabled-color: #fff;
|
--bs-pagination-disabled-color: #fff;
|
||||||
--bs-pagination-disabled-bg: #007053;
|
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
|
||||||
--bs-pagination-disabled-border-color: transparent;
|
--bs-pagination-disabled-border-color: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
@ -5498,7 +5499,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6063,20 +6063,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6696,14 +6688,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -45,28 +45,28 @@
|
||||||
--bs-danger-rgb: 231, 76, 60;
|
--bs-danger-rgb: 231, 76, 60;
|
||||||
--bs-light-rgb: 17, 17, 17;
|
--bs-light-rgb: 17, 17, 17;
|
||||||
--bs-dark-rgb: 222, 226, 230;
|
--bs-dark-rgb: 222, 226, 230;
|
||||||
--bs-primary-text-emphasis: #004b38;
|
--bs-primary-text-emphasis: rgb(0, 75.2, 56);
|
||||||
--bs-secondary-text-emphasis: #292929;
|
--bs-secondary-text-emphasis: rgb(40.8, 40.8, 40.8);
|
||||||
--bs-success-text-emphasis: #004b38;
|
--bs-success-text-emphasis: rgb(0, 75.2, 56);
|
||||||
--bs-info-text-emphasis: #153d58;
|
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
|
||||||
--bs-warning-text-emphasis: #613e07;
|
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
|
||||||
--bs-danger-text-emphasis: #5c1e18;
|
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
|
||||||
--bs-light-text-emphasis: #333;
|
--bs-light-text-emphasis: #333;
|
||||||
--bs-dark-text-emphasis: #333;
|
--bs-dark-text-emphasis: #333;
|
||||||
--bs-primary-bg-subtle: #ccf2e8;
|
--bs-primary-bg-subtle: rgb(204, 241.6, 232);
|
||||||
--bs-secondary-bg-subtle: #e0e0e0;
|
--bs-secondary-bg-subtle: rgb(224.4, 224.4, 224.4);
|
||||||
--bs-success-bg-subtle: #ccf2e8;
|
--bs-success-bg-subtle: rgb(204, 241.6, 232);
|
||||||
--bs-info-bg-subtle: #d6eaf8;
|
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-warning-bg-subtle: #fdebd0;
|
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-danger-bg-subtle: #fadbd8;
|
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
|
||||||
--bs-light-bg-subtle: #f6f6f7;
|
--bs-light-bg-subtle: rgb(245.5, 246, 246.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #99e4d1;
|
--bs-primary-border-subtle: rgb(153, 228.2, 209);
|
||||||
--bs-secondary-border-subtle: #c2c2c2;
|
--bs-secondary-border-subtle: rgb(193.8, 193.8, 193.8);
|
||||||
--bs-success-border-subtle: #99e4d1;
|
--bs-success-border-subtle: rgb(153, 228.2, 209);
|
||||||
--bs-info-border-subtle: #aed6f1;
|
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
|
||||||
--bs-warning-border-subtle: #fad7a0;
|
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
|
||||||
--bs-danger-border-subtle: #f5b7b1;
|
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
|
||||||
--bs-light-border-subtle: #ebebeb;
|
--bs-light-border-subtle: #ebebeb;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
--bs-white-rgb: 243, 243, 243;
|
--bs-white-rgb: 243, 243, 243;
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
--bs-link-color: #00bc8c;
|
--bs-link-color: #00bc8c;
|
||||||
--bs-link-color-rgb: 0, 188, 140;
|
--bs-link-color-rgb: 0, 188, 140;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #009670;
|
--bs-link-hover-color: rgb(0, 150.4, 112);
|
||||||
--bs-link-hover-color-rgb: 0, 150, 112;
|
--bs-link-hover-color-rgb: 0, 150, 112;
|
||||||
--bs-code-color: #d63384;
|
--bs-code-color: #d63384;
|
||||||
--bs-highlight-color: #ebebeb;
|
--bs-highlight-color: #ebebeb;
|
||||||
|
@ -140,46 +140,46 @@
|
||||||
--bs-secondary-bg-rgb: 32, 32, 32;
|
--bs-secondary-bg-rgb: 32, 32, 32;
|
||||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #191919;
|
--bs-tertiary-bg: rgb(24.5, 24.5, 24.5);
|
||||||
--bs-tertiary-bg-rgb: 25, 25, 25;
|
--bs-tertiary-bg-rgb: 25, 25, 25;
|
||||||
--bs-primary-text-emphasis: #66d7ba;
|
--bs-primary-text-emphasis: rgb(102, 214.8, 186);
|
||||||
--bs-secondary-text-emphasis: #a3a3a3;
|
--bs-secondary-text-emphasis: rgb(163.2, 163.2, 163.2);
|
||||||
--bs-success-text-emphasis: #66d7ba;
|
--bs-success-text-emphasis: rgb(102, 214.8, 186);
|
||||||
--bs-info-text-emphasis: #85c1e9;
|
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
|
||||||
--bs-warning-text-emphasis: #f8c471;
|
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
|
||||||
--bs-danger-text-emphasis: #f1948a;
|
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #00261c;
|
--bs-primary-bg-subtle: rgb(0, 37.6, 28);
|
||||||
--bs-secondary-bg-subtle: #141414;
|
--bs-secondary-bg-subtle: rgb(20.4, 20.4, 20.4);
|
||||||
--bs-success-bg-subtle: #00261c;
|
--bs-success-bg-subtle: rgb(0, 37.6, 28);
|
||||||
--bs-info-bg-subtle: #0a1e2c;
|
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
|
||||||
--bs-warning-bg-subtle: #311f04;
|
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
|
||||||
--bs-danger-bg-subtle: #2e0f0c;
|
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
|
||||||
--bs-light-bg-subtle: #202020;
|
--bs-light-bg-subtle: #202020;
|
||||||
--bs-dark-bg-subtle: #101010;
|
--bs-dark-bg-subtle: #101010;
|
||||||
--bs-primary-border-subtle: #007154;
|
--bs-primary-border-subtle: rgb(0, 112.8, 84);
|
||||||
--bs-secondary-border-subtle: #3d3d3d;
|
--bs-secondary-border-subtle: rgb(61.2, 61.2, 61.2);
|
||||||
--bs-success-border-subtle: #007154;
|
--bs-success-border-subtle: rgb(0, 112.8, 84);
|
||||||
--bs-info-border-subtle: #1f5b83;
|
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
|
||||||
--bs-warning-border-subtle: #925e0b;
|
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
|
||||||
--bs-danger-border-subtle: #8b2e24;
|
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
|
||||||
--bs-light-border-subtle: #333;
|
--bs-light-border-subtle: #333;
|
||||||
--bs-dark-border-subtle: #202020;
|
--bs-dark-border-subtle: #202020;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #66d7ba;
|
--bs-link-color: rgb(102, 214.8, 186);
|
||||||
--bs-link-hover-color: #85dfc8;
|
--bs-link-hover-color: rgb(132.6, 222.84, 199.8);
|
||||||
--bs-link-color-rgb: 102, 215, 186;
|
--bs-link-color-rgb: 102, 215, 186;
|
||||||
--bs-link-hover-color-rgb: 133, 223, 200;
|
--bs-link-hover-color-rgb: 133, 223, 200;
|
||||||
--bs-code-color: #e685b5;
|
--bs-code-color: rgb(230.4, 132.6, 181.2);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #111;
|
--bs-highlight-bg: #111;
|
||||||
--bs-border-color: #333;
|
--bs-border-color: #333;
|
||||||
--bs-border-color-translucent: rgba(243, 243, 243, 0.15);
|
--bs-border-color-translucent: rgba(243, 243, 243, 0.15);
|
||||||
--bs-form-valid-color: #66d7ba;
|
--bs-form-valid-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-valid-border-color: #66d7ba;
|
--bs-form-valid-border-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-invalid-color: #f1948a;
|
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
|
||||||
--bs-form-invalid-border-color: #f1948a;
|
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -1935,13 +1935,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf2e8;
|
--bs-table-bg: rgb(204, 241.6, 232);
|
||||||
--bs-table-border-color: #a3c2ba;
|
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
|
||||||
--bs-table-striped-bg: #c2e6dc;
|
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dad1;
|
--bs-table-active-bg: rgb(183.6, 217.44, 208.8);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde0d7;
|
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1949,13 +1949,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #e0e0e0;
|
--bs-table-bg: rgb(224.4, 224.4, 224.4);
|
||||||
--bs-table-border-color: #b3b3b3;
|
--bs-table-border-color: rgb(179.52, 179.52, 179.52);
|
||||||
--bs-table-striped-bg: #d5d5d5;
|
--bs-table-striped-bg: rgb(213.18, 213.18, 213.18);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #cacaca;
|
--bs-table-active-bg: rgb(201.96, 201.96, 201.96);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #cfcfcf;
|
--bs-table-hover-bg: rgb(207.57, 207.57, 207.57);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1963,13 +1963,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf2e8;
|
--bs-table-bg: rgb(204, 241.6, 232);
|
||||||
--bs-table-border-color: #a3c2ba;
|
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
|
||||||
--bs-table-striped-bg: #c2e6dc;
|
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dad1;
|
--bs-table-active-bg: rgb(183.6, 217.44, 208.8);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde0d7;
|
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1977,13 +1977,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #d6eaf8;
|
--bs-table-bg: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-table-border-color: #abbbc6;
|
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
|
||||||
--bs-table-striped-bg: #cbdeec;
|
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c1d3df;
|
--bs-table-active-bg: rgb(192.96, 210.96, 223.02);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #c6d8e5;
|
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1991,13 +1991,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fdebd0;
|
--bs-table-bg: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-table-border-color: #cabca6;
|
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
|
||||||
--bs-table-striped-bg: #f0dfc6;
|
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e4d4bb;
|
--bs-table-active-bg: rgb(227.34, 211.68, 186.84);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ead9c0;
|
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2005,13 +2005,13 @@ progress {
|
||||||
|
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fadbd8;
|
--bs-table-bg: rgb(250.2, 219.2, 216);
|
||||||
--bs-table-border-color: #c8afad;
|
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
|
||||||
--bs-table-striped-bg: #eed0cd;
|
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e1c5c2;
|
--bs-table-active-bg: rgb(225.18, 197.28, 194.4);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #e7cbc8;
|
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2020,12 +2020,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #f3f3f3;
|
--bs-table-color: #f3f3f3;
|
||||||
--bs-table-bg: #111;
|
--bs-table-bg: #111;
|
||||||
--bs-table-border-color: #3e3e3e;
|
--bs-table-border-color: rgb(62.2, 62.2, 62.2);
|
||||||
--bs-table-striped-bg: #1c1c1c;
|
--bs-table-striped-bg: rgb(28.3, 28.3, 28.3);
|
||||||
--bs-table-striped-color: #f3f3f3;
|
--bs-table-striped-color: #f3f3f3;
|
||||||
--bs-table-active-bg: #282828;
|
--bs-table-active-bg: rgb(39.6, 39.6, 39.6);
|
||||||
--bs-table-active-color: #f3f3f3;
|
--bs-table-active-color: #f3f3f3;
|
||||||
--bs-table-hover-bg: #222222;
|
--bs-table-hover-bg: rgb(33.95, 33.95, 33.95);
|
||||||
--bs-table-hover-color: #f3f3f3;
|
--bs-table-hover-color: #f3f3f3;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2034,12 +2034,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #dee2e6;
|
--bs-table-bg: #dee2e6;
|
||||||
--bs-table-border-color: #b2b5b8;
|
--bs-table-border-color: rgb(177.6, 180.8, 184);
|
||||||
--bs-table-striped-bg: #d3d7db;
|
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c8cbcf;
|
--bs-table-active-bg: rgb(199.8, 203.4, 207);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #cdd1d5;
|
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2139,7 +2139,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: #f3f3f3;
|
color: #f3f3f3;
|
||||||
background-color: #111;
|
background-color: #111;
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2415,7 +2415,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2380dec6'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 221.5, 197.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #b3ebdd;
|
background-color: rgb(178.5, 234.9, 220.5);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #b3ebdd;
|
background-color: rgb(178.5, 234.9, 220.5);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2959,6 +2959,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2972,12 +2975,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00bc8c;
|
--bs-btn-bg: #00bc8c;
|
||||||
--bs-btn-border-color: #00bc8c;
|
--bs-btn-border-color: #00bc8c;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #26c69d;
|
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
|
||||||
--bs-btn-hover-border-color: #1ac398;
|
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #33c9a3;
|
--bs-btn-active-bg: rgb(51, 201.4, 163);
|
||||||
--bs-btn-active-border-color: #1ac398;
|
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #00bc8c;
|
--bs-btn-disabled-bg: #00bc8c;
|
||||||
|
@ -2989,12 +2992,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #666;
|
--bs-btn-bg: #666;
|
||||||
--bs-btn-border-color: #666;
|
--bs-btn-border-color: #666;
|
||||||
--bs-btn-hover-color: #f3f3f3;
|
--bs-btn-hover-color: #f3f3f3;
|
||||||
--bs-btn-hover-bg: #575757;
|
--bs-btn-hover-bg: rgb(86.7, 86.7, 86.7);
|
||||||
--bs-btn-hover-border-color: #525252;
|
--bs-btn-hover-border-color: rgb(81.6, 81.6, 81.6);
|
||||||
--bs-btn-focus-shadow-rgb: 123, 123, 123;
|
--bs-btn-focus-shadow-rgb: 123, 123, 123;
|
||||||
--bs-btn-active-color: #f3f3f3;
|
--bs-btn-active-color: #f3f3f3;
|
||||||
--bs-btn-active-bg: #525252;
|
--bs-btn-active-bg: rgb(81.6, 81.6, 81.6);
|
||||||
--bs-btn-active-border-color: #4d4d4d;
|
--bs-btn-active-border-color: rgb(76.5, 76.5, 76.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #f3f3f3;
|
--bs-btn-disabled-color: #f3f3f3;
|
||||||
--bs-btn-disabled-bg: #666;
|
--bs-btn-disabled-bg: #666;
|
||||||
|
@ -3006,12 +3009,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00bc8c;
|
--bs-btn-bg: #00bc8c;
|
||||||
--bs-btn-border-color: #00bc8c;
|
--bs-btn-border-color: #00bc8c;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #26c69d;
|
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
|
||||||
--bs-btn-hover-border-color: #1ac398;
|
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #33c9a3;
|
--bs-btn-active-bg: rgb(51, 201.4, 163);
|
||||||
--bs-btn-active-border-color: #1ac398;
|
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #00bc8c;
|
--bs-btn-disabled-bg: #00bc8c;
|
||||||
|
@ -3023,12 +3026,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #3498db;
|
--bs-btn-bg: #3498db;
|
||||||
--bs-btn-border-color: #3498db;
|
--bs-btn-border-color: #3498db;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #52a7e0;
|
--bs-btn-hover-bg: rgb(82.45, 167.45, 224.4);
|
||||||
--bs-btn-hover-border-color: #48a2df;
|
--bs-btn-hover-border-color: rgb(72.3, 162.3, 222.6);
|
||||||
--bs-btn-focus-shadow-rgb: 44, 129, 186;
|
--bs-btn-focus-shadow-rgb: 44, 129, 186;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #5dade2;
|
--bs-btn-active-bg: rgb(92.6, 172.6, 226.2);
|
||||||
--bs-btn-active-border-color: #48a2df;
|
--bs-btn-active-border-color: rgb(72.3, 162.3, 222.6);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #3498db;
|
--bs-btn-disabled-bg: #3498db;
|
||||||
|
@ -3040,12 +3043,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f39c12;
|
--bs-btn-bg: #f39c12;
|
||||||
--bs-btn-border-color: #f39c12;
|
--bs-btn-border-color: #f39c12;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #f5ab36;
|
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
|
||||||
--bs-btn-hover-border-color: #f4a62a;
|
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #f5b041;
|
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
|
||||||
--bs-btn-active-border-color: #f4a62a;
|
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #f39c12;
|
--bs-btn-disabled-bg: #f39c12;
|
||||||
|
@ -3057,12 +3060,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #e74c3c;
|
--bs-btn-bg: #e74c3c;
|
||||||
--bs-btn-border-color: #e74c3c;
|
--bs-btn-border-color: #e74c3c;
|
||||||
--bs-btn-hover-color: #f3f3f3;
|
--bs-btn-hover-color: #f3f3f3;
|
||||||
--bs-btn-hover-bg: #c44133;
|
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
|
||||||
--bs-btn-hover-border-color: #b93d30;
|
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-focus-shadow-rgb: 233, 101, 87;
|
--bs-btn-focus-shadow-rgb: 233, 101, 87;
|
||||||
--bs-btn-active-color: #f3f3f3;
|
--bs-btn-active-color: #f3f3f3;
|
||||||
--bs-btn-active-bg: #b93d30;
|
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-active-border-color: #ad392d;
|
--bs-btn-active-border-color: rgb(173.25, 57, 45);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #f3f3f3;
|
--bs-btn-disabled-color: #f3f3f3;
|
||||||
--bs-btn-disabled-bg: #e74c3c;
|
--bs-btn-disabled-bg: #e74c3c;
|
||||||
|
@ -3074,12 +3077,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #111;
|
--bs-btn-bg: #111;
|
||||||
--bs-btn-border-color: #111;
|
--bs-btn-border-color: #111;
|
||||||
--bs-btn-hover-color: #f3f3f3;
|
--bs-btn-hover-color: #f3f3f3;
|
||||||
--bs-btn-hover-bg: #0e0e0e;
|
--bs-btn-hover-bg: rgb(14.45, 14.45, 14.45);
|
||||||
--bs-btn-hover-border-color: #0e0e0e;
|
--bs-btn-hover-border-color: rgb(13.6, 13.6, 13.6);
|
||||||
--bs-btn-focus-shadow-rgb: 51, 51, 51;
|
--bs-btn-focus-shadow-rgb: 51, 51, 51;
|
||||||
--bs-btn-active-color: #f3f3f3;
|
--bs-btn-active-color: #f3f3f3;
|
||||||
--bs-btn-active-bg: #0e0e0e;
|
--bs-btn-active-bg: rgb(13.6, 13.6, 13.6);
|
||||||
--bs-btn-active-border-color: #0d0d0d;
|
--bs-btn-active-border-color: rgb(12.75, 12.75, 12.75);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #f3f3f3;
|
--bs-btn-disabled-color: #f3f3f3;
|
||||||
--bs-btn-disabled-bg: #111;
|
--bs-btn-disabled-bg: #111;
|
||||||
|
@ -3091,12 +3094,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #dee2e6;
|
--bs-btn-bg: #dee2e6;
|
||||||
--bs-btn-border-color: #dee2e6;
|
--bs-btn-border-color: #dee2e6;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #e3e6ea;
|
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
|
||||||
--bs-btn-hover-border-color: #e1e5e9;
|
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #e5e8eb;
|
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
|
||||||
--bs-btn-active-border-color: #e1e5e9;
|
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #dee2e6;
|
--bs-btn-disabled-bg: #dee2e6;
|
||||||
|
@ -4487,12 +4490,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ebebeb'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ebebeb' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23004b38'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%280, 75.2, 56%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #80dec6;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4550,7 +4552,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4568,7 +4569,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4579,11 +4580,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4592,27 +4593,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -4657,16 +4658,16 @@ textarea.form-control-lg {
|
||||||
--bs-pagination-border-color: transparent;
|
--bs-pagination-border-color: transparent;
|
||||||
--bs-pagination-border-radius: var(--bs-border-radius);
|
--bs-pagination-border-radius: var(--bs-border-radius);
|
||||||
--bs-pagination-hover-color: #f3f3f3;
|
--bs-pagination-hover-color: #f3f3f3;
|
||||||
--bs-pagination-hover-bg: #00efb2;
|
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-hover-border-color: transparent;
|
--bs-pagination-hover-border-color: transparent;
|
||||||
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
||||||
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
||||||
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
--bs-pagination-active-color: #f3f3f3;
|
--bs-pagination-active-color: #f3f3f3;
|
||||||
--bs-pagination-active-bg: #00efb2;
|
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-active-border-color: transparent;
|
--bs-pagination-active-border-color: transparent;
|
||||||
--bs-pagination-disabled-color: #f3f3f3;
|
--bs-pagination-disabled-color: #f3f3f3;
|
||||||
--bs-pagination-disabled-bg: #007053;
|
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
|
||||||
--bs-pagination-disabled-border-color: transparent;
|
--bs-pagination-disabled-border-color: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
@ -5486,7 +5487,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6051,20 +6051,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6684,14 +6676,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -45,28 +45,28 @@
|
||||||
--bs-danger-rgb: 231, 76, 60;
|
--bs-danger-rgb: 231, 76, 60;
|
||||||
--bs-light-rgb: 48, 48, 48;
|
--bs-light-rgb: 48, 48, 48;
|
||||||
--bs-dark-rgb: 222, 226, 230;
|
--bs-dark-rgb: 222, 226, 230;
|
||||||
--bs-primary-text-emphasis: #162433;
|
--bs-primary-text-emphasis: rgb(22, 36, 50.8);
|
||||||
--bs-secondary-text-emphasis: #45484c;
|
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6);
|
||||||
--bs-success-text-emphasis: #004b38;
|
--bs-success-text-emphasis: rgb(0, 75.2, 56);
|
||||||
--bs-info-text-emphasis: #153d58;
|
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
|
||||||
--bs-warning-text-emphasis: #613e07;
|
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
|
||||||
--bs-danger-text-emphasis: #5c1e18;
|
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
|
||||||
--bs-light-text-emphasis: #444;
|
--bs-light-text-emphasis: #444;
|
||||||
--bs-dark-text-emphasis: #444;
|
--bs-dark-text-emphasis: #444;
|
||||||
--bs-primary-bg-subtle: #d7dee5;
|
--bs-primary-bg-subtle: rgb(215, 222, 229.4);
|
||||||
--bs-secondary-bg-subtle: #eff0f2;
|
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8);
|
||||||
--bs-success-bg-subtle: #ccf2e8;
|
--bs-success-bg-subtle: rgb(204, 241.6, 232);
|
||||||
--bs-info-bg-subtle: #d6eaf8;
|
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-warning-bg-subtle: #fdebd0;
|
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-danger-bg-subtle: #fadbd8;
|
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #afbdcc;
|
--bs-primary-border-subtle: rgb(175, 189, 203.8);
|
||||||
--bs-secondary-border-subtle: #dee1e5;
|
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6);
|
||||||
--bs-success-border-subtle: #99e4d1;
|
--bs-success-border-subtle: rgb(153, 228.2, 209);
|
||||||
--bs-info-border-subtle: #aed6f1;
|
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
|
||||||
--bs-warning-border-subtle: #fad7a0;
|
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
|
||||||
--bs-danger-border-subtle: #f5b7b1;
|
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
|
||||||
--bs-light-border-subtle: #ebebeb;
|
--bs-light-border-subtle: #ebebeb;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
--bs-white-rgb: 255, 255, 255;
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
--bs-link-color: #e74c3c;
|
--bs-link-color: #e74c3c;
|
||||||
--bs-link-color-rgb: 231, 76, 60;
|
--bs-link-color-rgb: 231, 76, 60;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #b93d30;
|
--bs-link-hover-color: rgb(184.8, 60.8, 48);
|
||||||
--bs-link-hover-color-rgb: 185, 61, 48;
|
--bs-link-hover-color-rgb: 185, 61, 48;
|
||||||
--bs-code-color: #d63384;
|
--bs-code-color: #d63384;
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
|
@ -142,44 +142,44 @@
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #292929;
|
--bs-tertiary-bg: #292929;
|
||||||
--bs-tertiary-bg-rgb: 41, 41, 41;
|
--bs-tertiary-bg-rgb: 41, 41, 41;
|
||||||
--bs-primary-text-emphasis: #879cb2;
|
--bs-primary-text-emphasis: rgb(135, 156, 178.2);
|
||||||
--bs-secondary-text-emphasis: #ced3d7;
|
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4);
|
||||||
--bs-success-text-emphasis: #66d7ba;
|
--bs-success-text-emphasis: rgb(102, 214.8, 186);
|
||||||
--bs-info-text-emphasis: #85c1e9;
|
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
|
||||||
--bs-warning-text-emphasis: #f8c471;
|
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
|
||||||
--bs-danger-text-emphasis: #f1948a;
|
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #0b1219;
|
--bs-primary-bg-subtle: rgb(11, 18, 25.4);
|
||||||
--bs-secondary-bg-subtle: #232426;
|
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8);
|
||||||
--bs-success-bg-subtle: #00261c;
|
--bs-success-bg-subtle: rgb(0, 37.6, 28);
|
||||||
--bs-info-bg-subtle: #0a1e2c;
|
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
|
||||||
--bs-warning-bg-subtle: #311f04;
|
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
|
||||||
--bs-danger-bg-subtle: #2e0f0c;
|
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
|
||||||
--bs-light-bg-subtle: #303030;
|
--bs-light-bg-subtle: #303030;
|
||||||
--bs-dark-bg-subtle: #181818;
|
--bs-dark-bg-subtle: #181818;
|
||||||
--bs-primary-border-subtle: #21364c;
|
--bs-primary-border-subtle: rgb(33, 54, 76.2);
|
||||||
--bs-secondary-border-subtle: #686d71;
|
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4);
|
||||||
--bs-success-border-subtle: #007154;
|
--bs-success-border-subtle: rgb(0, 112.8, 84);
|
||||||
--bs-info-border-subtle: #1f5b83;
|
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
|
||||||
--bs-warning-border-subtle: #925e0b;
|
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
|
||||||
--bs-danger-border-subtle: #8b2e24;
|
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
|
||||||
--bs-light-border-subtle: #444;
|
--bs-light-border-subtle: #444;
|
||||||
--bs-dark-border-subtle: #303030;
|
--bs-dark-border-subtle: #303030;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #879cb2;
|
--bs-link-color: rgb(135, 156, 178.2);
|
||||||
--bs-link-hover-color: #9fb0c1;
|
--bs-link-hover-color: rgb(159, 175.8, 193.56);
|
||||||
--bs-link-color-rgb: 135, 156, 178;
|
--bs-link-color-rgb: 135, 156, 178;
|
||||||
--bs-link-hover-color-rgb: 159, 176, 193;
|
--bs-link-hover-color-rgb: 159, 176, 194;
|
||||||
--bs-code-color: #e685b5;
|
--bs-code-color: rgb(230.4, 132.6, 181.2);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #333;
|
--bs-highlight-bg: #333;
|
||||||
--bs-border-color: #444;
|
--bs-border-color: #444;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #66d7ba;
|
--bs-form-valid-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-valid-border-color: #66d7ba;
|
--bs-form-valid-border-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-invalid-color: #f1948a;
|
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
|
||||||
--bs-form-invalid-border-color: #f1948a;
|
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -1935,13 +1935,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #d7dee5;
|
--bs-table-bg: rgb(215, 222, 229.4);
|
||||||
--bs-table-border-color: #acb2b7;
|
--bs-table-border-color: rgb(172, 177.6, 183.52);
|
||||||
--bs-table-striped-bg: #ccd3da;
|
--bs-table-striped-bg: rgb(204.25, 210.9, 217.93);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c2c8ce;
|
--bs-table-active-bg: rgb(193.5, 199.8, 206.46);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #c7cdd4;
|
--bs-table-hover-bg: rgb(198.875, 205.35, 212.195);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1949,13 +1949,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #eff0f2;
|
--bs-table-bg: rgb(238.6, 240.2, 241.8);
|
||||||
--bs-table-border-color: #bfc0c2;
|
--bs-table-border-color: rgb(190.88, 192.16, 193.44);
|
||||||
--bs-table-striped-bg: #e3e4e6;
|
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #d7d8da;
|
--bs-table-active-bg: rgb(214.74, 216.18, 217.62);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #dddee0;
|
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1963,13 +1963,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf2e8;
|
--bs-table-bg: rgb(204, 241.6, 232);
|
||||||
--bs-table-border-color: #a3c2ba;
|
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
|
||||||
--bs-table-striped-bg: #c2e6dc;
|
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dad1;
|
--bs-table-active-bg: rgb(183.6, 217.44, 208.8);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde0d7;
|
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1977,13 +1977,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #d6eaf8;
|
--bs-table-bg: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-table-border-color: #abbbc6;
|
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
|
||||||
--bs-table-striped-bg: #cbdeec;
|
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c1d3df;
|
--bs-table-active-bg: rgb(192.96, 210.96, 223.02);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #c6d8e5;
|
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1991,13 +1991,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fdebd0;
|
--bs-table-bg: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-table-border-color: #cabca6;
|
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
|
||||||
--bs-table-striped-bg: #f0dfc6;
|
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e4d4bb;
|
--bs-table-active-bg: rgb(227.34, 211.68, 186.84);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ead9c0;
|
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2005,13 +2005,13 @@ progress {
|
||||||
|
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fadbd8;
|
--bs-table-bg: rgb(250.2, 219.2, 216);
|
||||||
--bs-table-border-color: #c8afad;
|
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
|
||||||
--bs-table-striped-bg: #eed0cd;
|
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e1c5c2;
|
--bs-table-active-bg: rgb(225.18, 197.28, 194.4);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #e7cbc8;
|
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2020,12 +2020,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #303030;
|
--bs-table-bg: #303030;
|
||||||
--bs-table-border-color: #595959;
|
--bs-table-border-color: rgb(89.4, 89.4, 89.4);
|
||||||
--bs-table-striped-bg: #3a3a3a;
|
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #454545;
|
--bs-table-active-bg: rgb(68.7, 68.7, 68.7);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #404040;
|
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2034,12 +2034,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #dee2e6;
|
--bs-table-bg: #dee2e6;
|
||||||
--bs-table-border-color: #b2b5b8;
|
--bs-table-border-color: rgb(177.6, 180.8, 184);
|
||||||
--bs-table-striped-bg: #d3d7db;
|
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c8cbcf;
|
--bs-table-active-bg: rgb(199.8, 203.4, 207);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #cdd1d5;
|
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2139,7 +2139,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
border-color: #9badbf;
|
border-color: rgb(155, 172.5, 191);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2157,7 +2157,7 @@ progress {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.form-control:disabled {
|
.form-control:disabled {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.form-control::file-selector-button {
|
.form-control::file-selector-button {
|
||||||
|
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #9badbf;
|
border-color: rgb(155, 172.5, 191);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2293,7 +2293,7 @@ textarea.form-control-lg {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
.form-select:disabled {
|
.form-select:disabled {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
}
|
}
|
||||||
.form-select:-moz-focusring {
|
.form-select:-moz-focusring {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #9badbf;
|
border-color: rgb(155, 172.5, 191);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2415,7 +2415,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%239badbf'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28155, 172.5, 191%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #c3ced9;
|
background-color: rgb(195, 205.5, 216.6);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #c3ced9;
|
background-color: rgb(195, 205.5, 216.6);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2618,7 +2618,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.form-floating > :disabled ~ label::after,
|
.form-floating > :disabled ~ label::after,
|
||||||
.form-floating > .form-control:disabled ~ label::after {
|
.form-floating > .form-control:disabled ~ label::after {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group {
|
.input-group {
|
||||||
|
@ -2959,6 +2959,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2972,12 +2975,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #375a7f;
|
--bs-btn-bg: #375a7f;
|
||||||
--bs-btn-border-color: #375a7f;
|
--bs-btn-border-color: #375a7f;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #2f4d6c;
|
--bs-btn-hover-bg: rgb(46.75, 76.5, 107.95);
|
||||||
--bs-btn-hover-border-color: #2c4866;
|
--bs-btn-hover-border-color: rgb(44, 72, 101.6);
|
||||||
--bs-btn-focus-shadow-rgb: 85, 115, 146;
|
--bs-btn-focus-shadow-rgb: 85, 115, 146;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #2c4866;
|
--bs-btn-active-bg: rgb(44, 72, 101.6);
|
||||||
--bs-btn-active-border-color: #29445f;
|
--bs-btn-active-border-color: rgb(41.25, 67.5, 95.25);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #375a7f;
|
--bs-btn-disabled-bg: #375a7f;
|
||||||
|
@ -2989,12 +2992,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #adb5bd;
|
--bs-btn-bg: #adb5bd;
|
||||||
--bs-btn-border-color: #adb5bd;
|
--bs-btn-border-color: #adb5bd;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #b9c0c7;
|
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9);
|
||||||
--bs-btn-hover-border-color: #b5bcc4;
|
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6);
|
||||||
--bs-btn-focus-shadow-rgb: 147, 154, 161;
|
--bs-btn-focus-shadow-rgb: 147, 154, 161;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #bdc4ca;
|
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2);
|
||||||
--bs-btn-active-border-color: #b5bcc4;
|
--bs-btn-active-border-color: rgb(181.2, 188.4, 195.6);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #adb5bd;
|
--bs-btn-disabled-bg: #adb5bd;
|
||||||
|
@ -3006,12 +3009,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00bc8c;
|
--bs-btn-bg: #00bc8c;
|
||||||
--bs-btn-border-color: #00bc8c;
|
--bs-btn-border-color: #00bc8c;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #26c69d;
|
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
|
||||||
--bs-btn-hover-border-color: #1ac398;
|
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #33c9a3;
|
--bs-btn-active-bg: rgb(51, 201.4, 163);
|
||||||
--bs-btn-active-border-color: #1ac398;
|
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #00bc8c;
|
--bs-btn-disabled-bg: #00bc8c;
|
||||||
|
@ -3023,12 +3026,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #3498db;
|
--bs-btn-bg: #3498db;
|
||||||
--bs-btn-border-color: #3498db;
|
--bs-btn-border-color: #3498db;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #2c81ba;
|
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15);
|
||||||
--bs-btn-hover-border-color: #2a7aaf;
|
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2);
|
||||||
--bs-btn-focus-shadow-rgb: 82, 167, 224;
|
--bs-btn-focus-shadow-rgb: 82, 167, 224;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #2a7aaf;
|
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2);
|
||||||
--bs-btn-active-border-color: #2772a4;
|
--bs-btn-active-border-color: rgb(39, 114, 164.25);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #3498db;
|
--bs-btn-disabled-bg: #3498db;
|
||||||
|
@ -3040,12 +3043,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f39c12;
|
--bs-btn-bg: #f39c12;
|
||||||
--bs-btn-border-color: #f39c12;
|
--bs-btn-border-color: #f39c12;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #f5ab36;
|
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
|
||||||
--bs-btn-hover-border-color: #f4a62a;
|
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #f5b041;
|
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
|
||||||
--bs-btn-active-border-color: #f4a62a;
|
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #f39c12;
|
--bs-btn-disabled-bg: #f39c12;
|
||||||
|
@ -3057,12 +3060,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #e74c3c;
|
--bs-btn-bg: #e74c3c;
|
||||||
--bs-btn-border-color: #e74c3c;
|
--bs-btn-border-color: #e74c3c;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #c44133;
|
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
|
||||||
--bs-btn-hover-border-color: #b93d30;
|
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-focus-shadow-rgb: 235, 103, 89;
|
--bs-btn-focus-shadow-rgb: 235, 103, 89;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #b93d30;
|
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-active-border-color: #ad392d;
|
--bs-btn-active-border-color: rgb(173.25, 57, 45);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #e74c3c;
|
--bs-btn-disabled-bg: #e74c3c;
|
||||||
|
@ -3074,11 +3077,11 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #303030;
|
--bs-btn-bg: #303030;
|
||||||
--bs-btn-border-color: #303030;
|
--bs-btn-border-color: #303030;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #292929;
|
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8);
|
||||||
--bs-btn-hover-border-color: #262626;
|
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4);
|
||||||
--bs-btn-focus-shadow-rgb: 79, 79, 79;
|
--bs-btn-focus-shadow-rgb: 79, 79, 79;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #262626;
|
--bs-btn-active-bg: rgb(38.4, 38.4, 38.4);
|
||||||
--bs-btn-active-border-color: #242424;
|
--bs-btn-active-border-color: #242424;
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
|
@ -3091,12 +3094,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #dee2e6;
|
--bs-btn-bg: #dee2e6;
|
||||||
--bs-btn-border-color: #dee2e6;
|
--bs-btn-border-color: #dee2e6;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #e3e6ea;
|
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
|
||||||
--bs-btn-hover-border-color: #e1e5e9;
|
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #e5e8eb;
|
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
|
||||||
--bs-btn-active-border-color: #e1e5e9;
|
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #dee2e6;
|
--bs-btn-disabled-bg: #dee2e6;
|
||||||
|
@ -4487,12 +4490,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23dee2e6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23162433'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2822, 36, 50.8%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #9badbf;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4550,7 +4552,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4568,7 +4569,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4579,11 +4580,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4592,27 +4593,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23879cb2'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28135, 156, 178.2%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23879cb2'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28135, 156, 178.2%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -4657,16 +4658,16 @@ textarea.form-control-lg {
|
||||||
--bs-pagination-border-color: transparent;
|
--bs-pagination-border-color: transparent;
|
||||||
--bs-pagination-border-radius: var(--bs-border-radius);
|
--bs-pagination-border-radius: var(--bs-border-radius);
|
||||||
--bs-pagination-hover-color: #fff;
|
--bs-pagination-hover-color: #fff;
|
||||||
--bs-pagination-hover-bg: #00efb2;
|
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-hover-border-color: transparent;
|
--bs-pagination-hover-border-color: transparent;
|
||||||
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
||||||
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
||||||
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
|
||||||
--bs-pagination-active-color: #fff;
|
--bs-pagination-active-color: #fff;
|
||||||
--bs-pagination-active-bg: #00efb2;
|
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-active-border-color: transparent;
|
--bs-pagination-active-border-color: transparent;
|
||||||
--bs-pagination-disabled-color: #fff;
|
--bs-pagination-disabled-color: #fff;
|
||||||
--bs-pagination-disabled-bg: #007053;
|
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
|
||||||
--bs-pagination-disabled-border-color: transparent;
|
--bs-pagination-disabled-border-color: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
@ -5486,7 +5487,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6051,20 +6051,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6684,14 +6676,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -45,28 +45,28 @@
|
||||||
--bs-danger-rgb: 231, 76, 60;
|
--bs-danger-rgb: 231, 76, 60;
|
||||||
--bs-light-rgb: 48, 48, 48;
|
--bs-light-rgb: 48, 48, 48;
|
||||||
--bs-dark-rgb: 222, 226, 230;
|
--bs-dark-rgb: 222, 226, 230;
|
||||||
--bs-primary-text-emphasis: #004b38;
|
--bs-primary-text-emphasis: rgb(0, 75.2, 56);
|
||||||
--bs-secondary-text-emphasis: #45484c;
|
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6);
|
||||||
--bs-success-text-emphasis: #004b38;
|
--bs-success-text-emphasis: rgb(0, 75.2, 56);
|
||||||
--bs-info-text-emphasis: #153d58;
|
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
|
||||||
--bs-warning-text-emphasis: #613e07;
|
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
|
||||||
--bs-danger-text-emphasis: #5c1e18;
|
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
|
||||||
--bs-light-text-emphasis: #444;
|
--bs-light-text-emphasis: #444;
|
||||||
--bs-dark-text-emphasis: #444;
|
--bs-dark-text-emphasis: #444;
|
||||||
--bs-primary-bg-subtle: #ccf2e8;
|
--bs-primary-bg-subtle: rgb(204, 241.6, 232);
|
||||||
--bs-secondary-bg-subtle: #eff0f2;
|
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8);
|
||||||
--bs-success-bg-subtle: #ccf2e8;
|
--bs-success-bg-subtle: rgb(204, 241.6, 232);
|
||||||
--bs-info-bg-subtle: #d6eaf8;
|
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-warning-bg-subtle: #fdebd0;
|
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-danger-bg-subtle: #fadbd8;
|
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #99e4d1;
|
--bs-primary-border-subtle: rgb(153, 228.2, 209);
|
||||||
--bs-secondary-border-subtle: #dee1e5;
|
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6);
|
||||||
--bs-success-border-subtle: #99e4d1;
|
--bs-success-border-subtle: rgb(153, 228.2, 209);
|
||||||
--bs-info-border-subtle: #aed6f1;
|
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
|
||||||
--bs-warning-border-subtle: #fad7a0;
|
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
|
||||||
--bs-danger-border-subtle: #f5b7b1;
|
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
|
||||||
--bs-light-border-subtle: #ebebeb;
|
--bs-light-border-subtle: #ebebeb;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
--bs-white-rgb: 255, 255, 255;
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
--bs-link-color: #00bc8c;
|
--bs-link-color: #00bc8c;
|
||||||
--bs-link-color-rgb: 0, 188, 140;
|
--bs-link-color-rgb: 0, 188, 140;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #009670;
|
--bs-link-hover-color: rgb(0, 150.4, 112);
|
||||||
--bs-link-hover-color-rgb: 0, 150, 112;
|
--bs-link-hover-color-rgb: 0, 150, 112;
|
||||||
--bs-code-color: #d63384;
|
--bs-code-color: #d63384;
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
|
@ -142,44 +142,44 @@
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #292929;
|
--bs-tertiary-bg: #292929;
|
||||||
--bs-tertiary-bg-rgb: 41, 41, 41;
|
--bs-tertiary-bg-rgb: 41, 41, 41;
|
||||||
--bs-primary-text-emphasis: #66d7ba;
|
--bs-primary-text-emphasis: rgb(102, 214.8, 186);
|
||||||
--bs-secondary-text-emphasis: #ced3d7;
|
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4);
|
||||||
--bs-success-text-emphasis: #66d7ba;
|
--bs-success-text-emphasis: rgb(102, 214.8, 186);
|
||||||
--bs-info-text-emphasis: #85c1e9;
|
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
|
||||||
--bs-warning-text-emphasis: #f8c471;
|
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
|
||||||
--bs-danger-text-emphasis: #f1948a;
|
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #00261c;
|
--bs-primary-bg-subtle: rgb(0, 37.6, 28);
|
||||||
--bs-secondary-bg-subtle: #232426;
|
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8);
|
||||||
--bs-success-bg-subtle: #00261c;
|
--bs-success-bg-subtle: rgb(0, 37.6, 28);
|
||||||
--bs-info-bg-subtle: #0a1e2c;
|
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
|
||||||
--bs-warning-bg-subtle: #311f04;
|
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
|
||||||
--bs-danger-bg-subtle: #2e0f0c;
|
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
|
||||||
--bs-light-bg-subtle: #303030;
|
--bs-light-bg-subtle: #303030;
|
||||||
--bs-dark-bg-subtle: #181818;
|
--bs-dark-bg-subtle: #181818;
|
||||||
--bs-primary-border-subtle: #007154;
|
--bs-primary-border-subtle: rgb(0, 112.8, 84);
|
||||||
--bs-secondary-border-subtle: #686d71;
|
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4);
|
||||||
--bs-success-border-subtle: #007154;
|
--bs-success-border-subtle: rgb(0, 112.8, 84);
|
||||||
--bs-info-border-subtle: #1f5b83;
|
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
|
||||||
--bs-warning-border-subtle: #925e0b;
|
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
|
||||||
--bs-danger-border-subtle: #8b2e24;
|
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
|
||||||
--bs-light-border-subtle: #444;
|
--bs-light-border-subtle: #444;
|
||||||
--bs-dark-border-subtle: #303030;
|
--bs-dark-border-subtle: #303030;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #66d7ba;
|
--bs-link-color: rgb(102, 214.8, 186);
|
||||||
--bs-link-hover-color: #85dfc8;
|
--bs-link-hover-color: rgb(132.6, 222.84, 199.8);
|
||||||
--bs-link-color-rgb: 102, 215, 186;
|
--bs-link-color-rgb: 102, 215, 186;
|
||||||
--bs-link-hover-color-rgb: 133, 223, 200;
|
--bs-link-hover-color-rgb: 133, 223, 200;
|
||||||
--bs-code-color: #e685b5;
|
--bs-code-color: rgb(230.4, 132.6, 181.2);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #333;
|
--bs-highlight-bg: #333;
|
||||||
--bs-border-color: #444;
|
--bs-border-color: #444;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #66d7ba;
|
--bs-form-valid-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-valid-border-color: #66d7ba;
|
--bs-form-valid-border-color: rgb(102, 214.8, 186);
|
||||||
--bs-form-invalid-color: #f1948a;
|
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
|
||||||
--bs-form-invalid-border-color: #f1948a;
|
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -1935,13 +1935,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf2e8;
|
--bs-table-bg: rgb(204, 241.6, 232);
|
||||||
--bs-table-border-color: #a3c2ba;
|
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
|
||||||
--bs-table-striped-bg: #c2e6dc;
|
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dad1;
|
--bs-table-active-bg: rgb(183.6, 217.44, 208.8);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde0d7;
|
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1949,13 +1949,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #eff0f2;
|
--bs-table-bg: rgb(238.6, 240.2, 241.8);
|
||||||
--bs-table-border-color: #bfc0c2;
|
--bs-table-border-color: rgb(190.88, 192.16, 193.44);
|
||||||
--bs-table-striped-bg: #e3e4e6;
|
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #d7d8da;
|
--bs-table-active-bg: rgb(214.74, 216.18, 217.62);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #dddee0;
|
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1963,13 +1963,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf2e8;
|
--bs-table-bg: rgb(204, 241.6, 232);
|
||||||
--bs-table-border-color: #a3c2ba;
|
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
|
||||||
--bs-table-striped-bg: #c2e6dc;
|
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dad1;
|
--bs-table-active-bg: rgb(183.6, 217.44, 208.8);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde0d7;
|
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1977,13 +1977,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #d6eaf8;
|
--bs-table-bg: rgb(214.4, 234.4, 247.8);
|
||||||
--bs-table-border-color: #abbbc6;
|
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
|
||||||
--bs-table-striped-bg: #cbdeec;
|
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c1d3df;
|
--bs-table-active-bg: rgb(192.96, 210.96, 223.02);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #c6d8e5;
|
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1991,13 +1991,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fdebd0;
|
--bs-table-bg: rgb(252.6, 235.2, 207.6);
|
||||||
--bs-table-border-color: #cabca6;
|
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
|
||||||
--bs-table-striped-bg: #f0dfc6;
|
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e4d4bb;
|
--bs-table-active-bg: rgb(227.34, 211.68, 186.84);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ead9c0;
|
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2005,13 +2005,13 @@ progress {
|
||||||
|
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fadbd8;
|
--bs-table-bg: rgb(250.2, 219.2, 216);
|
||||||
--bs-table-border-color: #c8afad;
|
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
|
||||||
--bs-table-striped-bg: #eed0cd;
|
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e1c5c2;
|
--bs-table-active-bg: rgb(225.18, 197.28, 194.4);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #e7cbc8;
|
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2020,12 +2020,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #303030;
|
--bs-table-bg: #303030;
|
||||||
--bs-table-border-color: #595959;
|
--bs-table-border-color: rgb(89.4, 89.4, 89.4);
|
||||||
--bs-table-striped-bg: #3a3a3a;
|
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #454545;
|
--bs-table-active-bg: rgb(68.7, 68.7, 68.7);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #404040;
|
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2034,12 +2034,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #dee2e6;
|
--bs-table-bg: #dee2e6;
|
||||||
--bs-table-border-color: #b2b5b8;
|
--bs-table-border-color: rgb(177.6, 180.8, 184);
|
||||||
--bs-table-striped-bg: #d3d7db;
|
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c8cbcf;
|
--bs-table-active-bg: rgb(199.8, 203.4, 207);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #cdd1d5;
|
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2139,7 +2139,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2157,7 +2157,7 @@ progress {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.form-control:disabled {
|
.form-control:disabled {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.form-control::file-selector-button {
|
.form-control::file-selector-button {
|
||||||
|
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2293,7 +2293,7 @@ textarea.form-control-lg {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
.form-select:disabled {
|
.form-select:disabled {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
}
|
}
|
||||||
.form-select:-moz-focusring {
|
.form-select:-moz-focusring {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #80dec6;
|
border-color: rgb(127.5, 221.5, 197.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2415,7 +2415,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2380dec6'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 221.5, 197.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #b3ebdd;
|
background-color: rgb(178.5, 234.9, 220.5);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #b3ebdd;
|
background-color: rgb(178.5, 234.9, 220.5);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2618,7 +2618,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.form-floating > :disabled ~ label::after,
|
.form-floating > :disabled ~ label::after,
|
||||||
.form-floating > .form-control:disabled ~ label::after {
|
.form-floating > .form-control:disabled ~ label::after {
|
||||||
background-color: #2b2b2b;
|
background-color: rgb(42.5, 42.5, 42.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group {
|
.input-group {
|
||||||
|
@ -2959,6 +2959,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2972,12 +2975,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00bc8c;
|
--bs-btn-bg: #00bc8c;
|
||||||
--bs-btn-border-color: #00bc8c;
|
--bs-btn-border-color: #00bc8c;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #26c69d;
|
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
|
||||||
--bs-btn-hover-border-color: #1ac398;
|
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #33c9a3;
|
--bs-btn-active-bg: rgb(51, 201.4, 163);
|
||||||
--bs-btn-active-border-color: #1ac398;
|
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #00bc8c;
|
--bs-btn-disabled-bg: #00bc8c;
|
||||||
|
@ -2989,12 +2992,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #adb5bd;
|
--bs-btn-bg: #adb5bd;
|
||||||
--bs-btn-border-color: #adb5bd;
|
--bs-btn-border-color: #adb5bd;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #b9c0c7;
|
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9);
|
||||||
--bs-btn-hover-border-color: #b5bcc4;
|
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6);
|
||||||
--bs-btn-focus-shadow-rgb: 147, 154, 161;
|
--bs-btn-focus-shadow-rgb: 147, 154, 161;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #bdc4ca;
|
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2);
|
||||||
--bs-btn-active-border-color: #b5bcc4;
|
--bs-btn-active-border-color: rgb(181.2, 188.4, 195.6);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #adb5bd;
|
--bs-btn-disabled-bg: #adb5bd;
|
||||||
|
@ -3006,12 +3009,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00bc8c;
|
--bs-btn-bg: #00bc8c;
|
||||||
--bs-btn-border-color: #00bc8c;
|
--bs-btn-border-color: #00bc8c;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #26c69d;
|
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
|
||||||
--bs-btn-hover-border-color: #1ac398;
|
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
--bs-btn-focus-shadow-rgb: 0, 160, 119;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #33c9a3;
|
--bs-btn-active-bg: rgb(51, 201.4, 163);
|
||||||
--bs-btn-active-border-color: #1ac398;
|
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #00bc8c;
|
--bs-btn-disabled-bg: #00bc8c;
|
||||||
|
@ -3023,12 +3026,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #3498db;
|
--bs-btn-bg: #3498db;
|
||||||
--bs-btn-border-color: #3498db;
|
--bs-btn-border-color: #3498db;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #2c81ba;
|
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15);
|
||||||
--bs-btn-hover-border-color: #2a7aaf;
|
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2);
|
||||||
--bs-btn-focus-shadow-rgb: 82, 167, 224;
|
--bs-btn-focus-shadow-rgb: 82, 167, 224;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #2a7aaf;
|
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2);
|
||||||
--bs-btn-active-border-color: #2772a4;
|
--bs-btn-active-border-color: rgb(39, 114, 164.25);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #3498db;
|
--bs-btn-disabled-bg: #3498db;
|
||||||
|
@ -3040,12 +3043,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f39c12;
|
--bs-btn-bg: #f39c12;
|
||||||
--bs-btn-border-color: #f39c12;
|
--bs-btn-border-color: #f39c12;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #f5ab36;
|
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
|
||||||
--bs-btn-hover-border-color: #f4a62a;
|
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
--bs-btn-focus-shadow-rgb: 207, 133, 15;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #f5b041;
|
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
|
||||||
--bs-btn-active-border-color: #f4a62a;
|
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #f39c12;
|
--bs-btn-disabled-bg: #f39c12;
|
||||||
|
@ -3057,12 +3060,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #e74c3c;
|
--bs-btn-bg: #e74c3c;
|
||||||
--bs-btn-border-color: #e74c3c;
|
--bs-btn-border-color: #e74c3c;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #c44133;
|
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
|
||||||
--bs-btn-hover-border-color: #b93d30;
|
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-focus-shadow-rgb: 235, 103, 89;
|
--bs-btn-focus-shadow-rgb: 235, 103, 89;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #b93d30;
|
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
|
||||||
--bs-btn-active-border-color: #ad392d;
|
--bs-btn-active-border-color: rgb(173.25, 57, 45);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #e74c3c;
|
--bs-btn-disabled-bg: #e74c3c;
|
||||||
|
@ -3074,11 +3077,11 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #303030;
|
--bs-btn-bg: #303030;
|
||||||
--bs-btn-border-color: #303030;
|
--bs-btn-border-color: #303030;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #292929;
|
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8);
|
||||||
--bs-btn-hover-border-color: #262626;
|
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4);
|
||||||
--bs-btn-focus-shadow-rgb: 79, 79, 79;
|
--bs-btn-focus-shadow-rgb: 79, 79, 79;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #262626;
|
--bs-btn-active-bg: rgb(38.4, 38.4, 38.4);
|
||||||
--bs-btn-active-border-color: #242424;
|
--bs-btn-active-border-color: #242424;
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
|
@ -3091,12 +3094,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #dee2e6;
|
--bs-btn-bg: #dee2e6;
|
||||||
--bs-btn-border-color: #dee2e6;
|
--bs-btn-border-color: #dee2e6;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #e3e6ea;
|
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
|
||||||
--bs-btn-hover-border-color: #e1e5e9;
|
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
--bs-btn-focus-shadow-rgb: 189, 192, 196;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #e5e8eb;
|
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
|
||||||
--bs-btn-active-border-color: #e1e5e9;
|
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #dee2e6;
|
--bs-btn-disabled-bg: #dee2e6;
|
||||||
|
@ -4487,12 +4490,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23dee2e6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23004b38'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%280, 75.2, 56%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #80dec6;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4550,7 +4552,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4568,7 +4569,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4579,11 +4580,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4592,27 +4593,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -4657,16 +4658,16 @@ textarea.form-control-lg {
|
||||||
--bs-pagination-border-color: transparent;
|
--bs-pagination-border-color: transparent;
|
||||||
--bs-pagination-border-radius: var(--bs-border-radius);
|
--bs-pagination-border-radius: var(--bs-border-radius);
|
||||||
--bs-pagination-hover-color: #fff;
|
--bs-pagination-hover-color: #fff;
|
||||||
--bs-pagination-hover-bg: #00efb2;
|
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-hover-border-color: transparent;
|
--bs-pagination-hover-border-color: transparent;
|
||||||
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
--bs-pagination-focus-color: var(--bs-link-hover-color);
|
||||||
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
--bs-pagination-focus-bg: var(--bs-secondary-bg);
|
||||||
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
|
||||||
--bs-pagination-active-color: #fff;
|
--bs-pagination-active-color: #fff;
|
||||||
--bs-pagination-active-bg: #00efb2;
|
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043);
|
||||||
--bs-pagination-active-border-color: transparent;
|
--bs-pagination-active-border-color: transparent;
|
||||||
--bs-pagination-disabled-color: #fff;
|
--bs-pagination-disabled-color: #fff;
|
||||||
--bs-pagination-disabled-bg: #007053;
|
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
|
||||||
--bs-pagination-disabled-border-color: transparent;
|
--bs-pagination-disabled-border-color: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
@ -5486,7 +5487,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6051,20 +6051,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6684,14 +6676,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
|
11582
src/assets/css/themes/i386-dark.css
Normal file
11582
src/assets/css/themes/i386-dark.css
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
@import "variables.i386";
|
@import "variables.i386-dark";
|
||||||
@import "../../../../node_modules/bootstrap/scss/bootstrap";
|
@import "../../../../node_modules/bootstrap/scss/bootstrap";
|
||||||
|
|
||||||
.btn-outline-secondary {
|
.btn-outline-secondary {
|
File diff suppressed because it is too large
Load diff
|
@ -40,8 +40,8 @@ hr.my-3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -74,7 +74,7 @@ hr.my-3 {
|
||||||
--bs-success: #6610f2;
|
--bs-success: #6610f2;
|
||||||
--bs-info: #007bff;
|
--bs-info: #007bff;
|
||||||
--bs-warning: #ffc107;
|
--bs-warning: #ffc107;
|
||||||
--bs-danger: #873208;
|
--bs-danger: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-light: #f8f9fa;
|
--bs-light: #f8f9fa;
|
||||||
--bs-dark: #212529;
|
--bs-dark: #212529;
|
||||||
--bs-primary-rgb: 241, 100, 30;
|
--bs-primary-rgb: 241, 100, 30;
|
||||||
|
@ -85,28 +85,28 @@ hr.my-3 {
|
||||||
--bs-danger-rgb: 135, 50, 8;
|
--bs-danger-rgb: 135, 50, 8;
|
||||||
--bs-light-rgb: 248, 249, 250;
|
--bs-light-rgb: 248, 249, 250;
|
||||||
--bs-dark-rgb: 33, 37, 41;
|
--bs-dark-rgb: 33, 37, 41;
|
||||||
--bs-primary-text-emphasis: #60280c;
|
--bs-primary-text-emphasis: rgb(96.4, 40, 12);
|
||||||
--bs-secondary-text-emphasis: #00431c;
|
--bs-secondary-text-emphasis: rgb(0, 67.2, 28);
|
||||||
--bs-success-text-emphasis: #290661;
|
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8);
|
||||||
--bs-info-text-emphasis: #003166;
|
--bs-info-text-emphasis: rgb(0, 49.2, 102);
|
||||||
--bs-warning-text-emphasis: #664d03;
|
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8);
|
||||||
--bs-danger-text-emphasis: #361403;
|
--bs-danger-text-emphasis: rgb(54.0376569038, 20.1740585774, 3.3623430962);
|
||||||
--bs-light-text-emphasis: #495057;
|
--bs-light-text-emphasis: #495057;
|
||||||
--bs-dark-text-emphasis: #495057;
|
--bs-dark-text-emphasis: #495057;
|
||||||
--bs-primary-bg-subtle: #fce0d2;
|
--bs-primary-bg-subtle: rgb(252.2, 224, 210);
|
||||||
--bs-secondary-bg-subtle: #cceeda;
|
--bs-secondary-bg-subtle: rgb(204, 237.6, 218);
|
||||||
--bs-success-bg-subtle: #e0cffc;
|
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4);
|
||||||
--bs-info-bg-subtle: #cce5ff;
|
--bs-info-bg-subtle: rgb(204, 228.6, 255);
|
||||||
--bs-warning-bg-subtle: #fff3cd;
|
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4);
|
||||||
--bs-danger-bg-subtle: #e7d6ce;
|
--bs-danger-bg-subtle: rgb(231.0188284519, 214.0870292887, 205.6811715481);
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #f9c1a5;
|
--bs-primary-border-subtle: rgb(249.4, 193, 165);
|
||||||
--bs-secondary-border-subtle: #99dcb5;
|
--bs-secondary-border-subtle: rgb(153, 220.2, 181);
|
||||||
--bs-success-border-subtle: #c29ffa;
|
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8);
|
||||||
--bs-info-border-subtle: #99caff;
|
--bs-info-border-subtle: rgb(153, 202.2, 255);
|
||||||
--bs-warning-border-subtle: #ffe69c;
|
--bs-warning-border-subtle: rgb(255, 230.2, 155.8);
|
||||||
--bs-danger-border-subtle: #cfad9c;
|
--bs-danger-border-subtle: rgb(207.0376569038, 173.1740585774, 156.3623430962);
|
||||||
--bs-light-border-subtle: #e9ecef;
|
--bs-light-border-subtle: #e9ecef;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
--bs-white-rgb: 255, 255, 255;
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
@ -137,7 +137,7 @@ hr.my-3 {
|
||||||
--bs-link-color: #f1641e;
|
--bs-link-color: #f1641e;
|
||||||
--bs-link-color-rgb: 241, 100, 30;
|
--bs-link-color-rgb: 241, 100, 30;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #c15018;
|
--bs-link-hover-color: rgb(192.8, 80, 24);
|
||||||
--bs-link-hover-color-rgb: 193, 80, 24;
|
--bs-link-hover-color-rgb: 193, 80, 24;
|
||||||
--bs-code-color: #d63384;
|
--bs-code-color: #d63384;
|
||||||
--bs-highlight-color: #495057;
|
--bs-highlight-color: #495057;
|
||||||
|
@ -162,8 +162,8 @@ hr.my-3 {
|
||||||
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
|
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
|
||||||
--bs-form-valid-color: #007bff;
|
--bs-form-valid-color: #007bff;
|
||||||
--bs-form-valid-border-color: #007bff;
|
--bs-form-valid-border-color: #007bff;
|
||||||
--bs-form-invalid-color: #873208;
|
--bs-form-invalid-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-form-invalid-border-color: #873208;
|
--bs-form-invalid-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] {
|
[data-bs-theme=dark] {
|
||||||
|
@ -180,46 +180,46 @@ hr.my-3 {
|
||||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #2b3035;
|
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5);
|
||||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||||
--bs-primary-text-emphasis: #f7a278;
|
--bs-primary-text-emphasis: rgb(246.6, 162, 120);
|
||||||
--bs-secondary-text-emphasis: #66cb90;
|
--bs-secondary-text-emphasis: rgb(102, 202.8, 144);
|
||||||
--bs-success-text-emphasis: #a370f7;
|
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2);
|
||||||
--bs-info-text-emphasis: #66b0ff;
|
--bs-info-text-emphasis: rgb(102, 175.8, 255);
|
||||||
--bs-warning-text-emphasis: #ffda6a;
|
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2);
|
||||||
--bs-danger-text-emphasis: #b7846b;
|
--bs-danger-text-emphasis: rgb(183.0564853556, 132.2610878661, 107.0435146444);
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #301406;
|
--bs-primary-bg-subtle: rgb(48.2, 20, 6);
|
||||||
--bs-secondary-bg-subtle: #00220e;
|
--bs-secondary-bg-subtle: rgb(0, 33.6, 14);
|
||||||
--bs-success-bg-subtle: #140330;
|
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4);
|
||||||
--bs-info-bg-subtle: #001933;
|
--bs-info-bg-subtle: rgb(0, 24.6, 51);
|
||||||
--bs-warning-bg-subtle: #332701;
|
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4);
|
||||||
--bs-danger-bg-subtle: #1b0a02;
|
--bs-danger-bg-subtle: rgb(27.0188284519, 10.0870292887, 1.6811715481);
|
||||||
--bs-light-bg-subtle: #343a40;
|
--bs-light-bg-subtle: #343a40;
|
||||||
--bs-dark-bg-subtle: #2b2e31;
|
--bs-dark-bg-subtle: #2b2e31;
|
||||||
--bs-primary-border-subtle: #913c12;
|
--bs-primary-border-subtle: rgb(144.6, 60, 18);
|
||||||
--bs-secondary-border-subtle: #00652a;
|
--bs-secondary-border-subtle: rgb(0, 100.8, 42);
|
||||||
--bs-success-border-subtle: #3d0a91;
|
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2);
|
||||||
--bs-info-border-subtle: #004a99;
|
--bs-info-border-subtle: rgb(0, 73.8, 153);
|
||||||
--bs-warning-border-subtle: #997404;
|
--bs-warning-border-subtle: rgb(153, 115.8, 4.2);
|
||||||
--bs-danger-border-subtle: #511e05;
|
--bs-danger-border-subtle: rgb(81.0564853556, 30.2610878661, 5.0435146444);
|
||||||
--bs-light-border-subtle: #495057;
|
--bs-light-border-subtle: #495057;
|
||||||
--bs-dark-border-subtle: #343a40;
|
--bs-dark-border-subtle: #343a40;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #f7a278;
|
--bs-link-color: rgb(246.6, 162, 120);
|
||||||
--bs-link-hover-color: #f9b593;
|
--bs-link-hover-color: rgb(248.28, 180.6, 147);
|
||||||
--bs-link-color-rgb: 247, 162, 120;
|
--bs-link-color-rgb: 247, 162, 120;
|
||||||
--bs-link-hover-color-rgb: 249, 181, 147;
|
--bs-link-hover-color-rgb: 248, 181, 147;
|
||||||
--bs-code-color: #e685b5;
|
--bs-code-color: rgb(230.4, 132.6, 181.2);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #664d03;
|
--bs-highlight-bg: rgb(102, 77.2, 2.8);
|
||||||
--bs-border-color: #495057;
|
--bs-border-color: #495057;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #66cb90;
|
--bs-form-valid-color: rgb(102, 202.8, 144);
|
||||||
--bs-form-valid-border-color: #66cb90;
|
--bs-form-valid-border-color: rgb(102, 202.8, 144);
|
||||||
--bs-form-invalid-color: #e891a6;
|
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6);
|
||||||
--bs-form-invalid-border-color: #e891a6;
|
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -1950,13 +1950,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #fce0d2;
|
--bs-table-bg: rgb(252.2, 224, 210);
|
||||||
--bs-table-border-color: #d0baaf;
|
--bs-table-border-color: rgb(208.56, 186, 174.8);
|
||||||
--bs-table-striped-bg: #f1d7c9;
|
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e6cdc0;
|
--bs-table-active-bg: rgb(230.38, 205, 192.4);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #ecd2c5;
|
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1964,13 +1964,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #cceeda;
|
--bs-table-bg: rgb(204, 237.6, 218);
|
||||||
--bs-table-border-color: #aac5b5;
|
--bs-table-border-color: rgb(170, 196.88, 181.2);
|
||||||
--bs-table-striped-bg: #c4e4d1;
|
--bs-table-striped-bg: rgb(195.5, 227.42, 208.8);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #bbdac8;
|
--bs-table-active-bg: rgb(187, 217.24, 199.6);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #bfdfcc;
|
--bs-table-hover-bg: rgb(191.25, 222.33, 204.2);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1978,13 +1978,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #e0cffc;
|
--bs-table-bg: rgb(224.4, 207.2, 252.4);
|
||||||
--bs-table-border-color: #baacd0;
|
--bs-table-border-color: rgb(186.32, 172.56, 208.72);
|
||||||
--bs-table-striped-bg: #d7c6f1;
|
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #cdbee6;
|
--bs-table-active-bg: rgb(205.36, 189.88, 230.56);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #d2c2ec;
|
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1992,13 +1992,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #cce5ff;
|
--bs-table-bg: rgb(204, 228.6, 255);
|
||||||
--bs-table-border-color: #aabed3;
|
--bs-table-border-color: rgb(170, 189.68, 210.8);
|
||||||
--bs-table-striped-bg: #c4dbf4;
|
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #bbd2e9;
|
--bs-table-active-bg: rgb(187, 209.14, 232.9);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #bfd6ee;
|
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2006,13 +2006,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #fff3cd;
|
--bs-table-bg: rgb(255, 242.6, 205.4);
|
||||||
--bs-table-border-color: #d3c9ab;
|
--bs-table-border-color: rgb(210.8, 200.88, 171.12);
|
||||||
--bs-table-striped-bg: #f4e9c4;
|
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e9debc;
|
--bs-table-active-bg: rgb(232.9, 221.74, 188.26);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #eee3c0;
|
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2020,13 +2020,13 @@ progress {
|
||||||
|
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #e7d6ce;
|
--bs-table-bg: rgb(231.0188284519, 214.0870292887, 205.6811715481);
|
||||||
--bs-table-border-color: #c0b2ac;
|
--bs-table-border-color: rgb(191.6150627615, 178.069623431, 171.3449372385);
|
||||||
--bs-table-striped-bg: #ddcdc5;
|
--bs-table-striped-bg: rgb(221.1678870293, 205.0826778243, 197.0971129707);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #d3c4bd;
|
--bs-table-active-bg: rgb(211.3169456067, 196.0783263598, 188.5130543933);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #d8c9c1;
|
--bs-table-hover-bg: rgb(216.242416318, 200.5805020921, 192.805083682);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2035,12 +2035,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #f8f9fa;
|
--bs-table-bg: #f8f9fa;
|
||||||
--bs-table-border-color: #cdcecf;
|
--bs-table-border-color: rgb(205.2, 206, 206.8);
|
||||||
--bs-table-striped-bg: #edeeef;
|
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e3e4e4;
|
--bs-table-active-bg: rgb(226.6, 227.5, 228.4);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #e8e9ea;
|
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2049,12 +2049,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #212529;
|
--bs-table-bg: #212529;
|
||||||
--bs-table-border-color: #4d5154;
|
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-table-striped-bg: #2c3034;
|
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #373b3e;
|
--bs-table-active-bg: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #323539;
|
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2154,7 +2154,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: var(--bs-body-color);
|
color: var(--bs-body-color);
|
||||||
background-color: var(--bs-body-bg);
|
background-color: var(--bs-body-bg);
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2299,7 +2299,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
|
||||||
}
|
}
|
||||||
|
@ -2383,7 +2383,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2430,7 +2430,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f8b28f'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28248, 177.5, 142.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2500,7 +2500,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #fbd1bc;
|
background-color: rgb(250.8, 208.5, 187.5);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2526,7 +2526,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #fbd1bc;
|
background-color: rgb(250.8, 208.5, 187.5);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2849,7 +2849,7 @@ textarea.form-control-lg {
|
||||||
.was-validated .form-control:invalid, .form-control.is-invalid {
|
.was-validated .form-control:invalid, .form-control.is-invalid {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
padding-right: calc(1.5em + 0.75rem);
|
padding-right: calc(1.5em + 0.75rem);
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: right calc(0.375em + 0.1875rem) center;
|
background-position: right calc(0.375em + 0.1875rem) center;
|
||||||
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||||
|
@ -2868,7 +2868,7 @@ textarea.form-control-lg {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
}
|
}
|
||||||
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
|
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
|
||||||
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
|
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e");
|
||||||
padding-right: 4.125rem;
|
padding-right: 4.125rem;
|
||||||
background-position: right 0.75rem center, center right 2.25rem;
|
background-position: right 0.75rem center, center right 2.25rem;
|
||||||
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||||
|
@ -2974,6 +2974,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2987,12 +2990,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f1641e;
|
--bs-btn-bg: #f1641e;
|
||||||
--bs-btn-border-color: #f1641e;
|
--bs-btn-border-color: #f1641e;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #cd551a;
|
--bs-btn-hover-bg: rgb(204.85, 85, 25.5);
|
||||||
--bs-btn-hover-border-color: #c15018;
|
--bs-btn-hover-border-color: rgb(192.8, 80, 24);
|
||||||
--bs-btn-focus-shadow-rgb: 243, 123, 64;
|
--bs-btn-focus-shadow-rgb: 243, 123, 64;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #c15018;
|
--bs-btn-active-bg: rgb(192.8, 80, 24);
|
||||||
--bs-btn-active-border-color: #b54b17;
|
--bs-btn-active-border-color: rgb(180.75, 75, 22.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #f1641e;
|
--bs-btn-disabled-bg: #f1641e;
|
||||||
|
@ -3004,12 +3007,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00a846;
|
--bs-btn-bg: #00a846;
|
||||||
--bs-btn-border-color: #00a846;
|
--bs-btn-border-color: #00a846;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #008f3c;
|
--bs-btn-hover-bg: rgb(0, 142.8, 59.5);
|
||||||
--bs-btn-hover-border-color: #008638;
|
--bs-btn-hover-border-color: rgb(0, 134.4, 56);
|
||||||
--bs-btn-focus-shadow-rgb: 38, 181, 98;
|
--bs-btn-focus-shadow-rgb: 38, 181, 98;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #008638;
|
--bs-btn-active-bg: rgb(0, 134.4, 56);
|
||||||
--bs-btn-active-border-color: #007e35;
|
--bs-btn-active-border-color: rgb(0, 126, 52.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #00a846;
|
--bs-btn-disabled-bg: #00a846;
|
||||||
|
@ -3021,12 +3024,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #6610f2;
|
--bs-btn-bg: #6610f2;
|
||||||
--bs-btn-border-color: #6610f2;
|
--bs-btn-border-color: #6610f2;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #570ece;
|
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7);
|
||||||
--bs-btn-hover-border-color: #520dc2;
|
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6);
|
||||||
--bs-btn-focus-shadow-rgb: 125, 52, 244;
|
--bs-btn-focus-shadow-rgb: 125, 52, 244;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #520dc2;
|
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6);
|
||||||
--bs-btn-active-border-color: #4d0cb6;
|
--bs-btn-active-border-color: rgb(76.5, 12, 181.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #6610f2;
|
--bs-btn-disabled-bg: #6610f2;
|
||||||
|
@ -3038,12 +3041,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #007bff;
|
--bs-btn-bg: #007bff;
|
||||||
--bs-btn-border-color: #007bff;
|
--bs-btn-border-color: #007bff;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #0069d9;
|
--bs-btn-hover-bg: rgb(0, 104.55, 216.75);
|
||||||
--bs-btn-hover-border-color: #0062cc;
|
--bs-btn-hover-border-color: rgb(0, 98.4, 204);
|
||||||
--bs-btn-focus-shadow-rgb: 38, 143, 255;
|
--bs-btn-focus-shadow-rgb: 38, 143, 255;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #0062cc;
|
--bs-btn-active-bg: rgb(0, 98.4, 204);
|
||||||
--bs-btn-active-border-color: #005cbf;
|
--bs-btn-active-border-color: rgb(0, 92.25, 191.25);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #007bff;
|
--bs-btn-disabled-bg: #007bff;
|
||||||
|
@ -3055,12 +3058,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #ffc107;
|
--bs-btn-bg: #ffc107;
|
||||||
--bs-btn-border-color: #ffc107;
|
--bs-btn-border-color: #ffc107;
|
||||||
--bs-btn-hover-color: #222;
|
--bs-btn-hover-color: #222;
|
||||||
--bs-btn-hover-bg: #ffca2c;
|
--bs-btn-hover-bg: rgb(255, 202.3, 44.2);
|
||||||
--bs-btn-hover-border-color: #ffc720;
|
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8);
|
||||||
--bs-btn-focus-shadow-rgb: 222, 169, 11;
|
--bs-btn-focus-shadow-rgb: 222, 169, 11;
|
||||||
--bs-btn-active-color: #222;
|
--bs-btn-active-color: #222;
|
||||||
--bs-btn-active-bg: #ffcd39;
|
--bs-btn-active-bg: rgb(255, 205.4, 56.6);
|
||||||
--bs-btn-active-border-color: #ffc720;
|
--bs-btn-active-border-color: rgb(255, 199.2, 31.8);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #222;
|
--bs-btn-disabled-color: #222;
|
||||||
--bs-btn-disabled-bg: #ffc107;
|
--bs-btn-disabled-bg: #ffc107;
|
||||||
|
@ -3069,19 +3072,19 @@ textarea.form-control-lg {
|
||||||
|
|
||||||
.btn-danger {
|
.btn-danger {
|
||||||
--bs-btn-color: #fff;
|
--bs-btn-color: #fff;
|
||||||
--bs-btn-bg: #873208;
|
--bs-btn-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-border-color: #873208;
|
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #732b07;
|
--bs-btn-hover-bg: rgb(114.8300209205, 42.869874477, 7.1449790795);
|
||||||
--bs-btn-hover-border-color: #6c2806;
|
--bs-btn-hover-border-color: rgb(108.0753138075, 40.3481171548, 6.7246861925);
|
||||||
--bs-btn-focus-shadow-rgb: 153, 81, 45;
|
--bs-btn-focus-shadow-rgb: 153, 81, 45;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #6c2806;
|
--bs-btn-active-bg: rgb(108.0753138075, 40.3481171548, 6.7246861925);
|
||||||
--bs-btn-active-border-color: #652606;
|
--bs-btn-active-border-color: rgb(101.3206066946, 37.8263598326, 6.3043933054);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #873208;
|
--bs-btn-disabled-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-disabled-border-color: #873208;
|
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-light {
|
.btn-light {
|
||||||
|
@ -3089,12 +3092,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f8f9fa;
|
--bs-btn-bg: #f8f9fa;
|
||||||
--bs-btn-border-color: #f8f9fa;
|
--bs-btn-border-color: #f8f9fa;
|
||||||
--bs-btn-hover-color: #222;
|
--bs-btn-hover-color: #222;
|
||||||
--bs-btn-hover-bg: #d3d4d5;
|
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5);
|
||||||
--bs-btn-hover-border-color: #c6c7c8;
|
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200);
|
||||||
--bs-btn-focus-shadow-rgb: 216, 217, 218;
|
--bs-btn-focus-shadow-rgb: 216, 217, 218;
|
||||||
--bs-btn-active-color: #222;
|
--bs-btn-active-color: #222;
|
||||||
--bs-btn-active-bg: #c6c7c8;
|
--bs-btn-active-bg: rgb(198.4, 199.2, 200);
|
||||||
--bs-btn-active-border-color: #babbbc;
|
--bs-btn-active-border-color: rgb(186, 186.75, 187.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #222;
|
--bs-btn-disabled-color: #222;
|
||||||
--bs-btn-disabled-bg: #f8f9fa;
|
--bs-btn-disabled-bg: #f8f9fa;
|
||||||
|
@ -3106,12 +3109,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #212529;
|
--bs-btn-bg: #212529;
|
||||||
--bs-btn-border-color: #212529;
|
--bs-btn-border-color: #212529;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #424649;
|
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
|
||||||
--bs-btn-hover-border-color: #373b3e;
|
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #4d5154;
|
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-btn-active-border-color: #373b3e;
|
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #212529;
|
--bs-btn-disabled-bg: #212529;
|
||||||
|
@ -3204,19 +3207,19 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-outline-danger {
|
.btn-outline-danger {
|
||||||
--bs-btn-color: #873208;
|
--bs-btn-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-border-color: #873208;
|
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #873208;
|
--bs-btn-hover-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-hover-border-color: #873208;
|
--bs-btn-hover-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-focus-shadow-rgb: 135, 50, 8;
|
--bs-btn-focus-shadow-rgb: 135, 50, 8;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #873208;
|
--bs-btn-active-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-active-border-color: #873208;
|
--bs-btn-active-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #873208;
|
--bs-btn-disabled-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-disabled-bg: transparent;
|
--bs-btn-disabled-bg: transparent;
|
||||||
--bs-btn-disabled-border-color: #873208;
|
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-gradient: none;
|
--bs-gradient: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4498,12 +4501,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2360280c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2896.4, 40, 12%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #f8b28f;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4561,7 +4563,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4579,7 +4580,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4590,11 +4591,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4603,27 +4604,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -5497,7 +5498,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6062,20 +6062,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6695,14 +6687,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
@ -6857,8 +6846,8 @@ textarea.form-control-lg {
|
||||||
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
|
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
|
||||||
}
|
}
|
||||||
.link-danger:hover, .link-danger:focus {
|
.link-danger:hover, .link-danger:focus {
|
||||||
color: RGBA(108, 40, 6, var(--bs-link-opacity, 1)) !important;
|
color: RGBA(108, 40, 7, var(--bs-link-opacity, 1)) !important;
|
||||||
text-decoration-color: RGBA(108, 40, 6, var(--bs-link-underline-opacity, 1)) !important;
|
text-decoration-color: RGBA(108, 40, 7, var(--bs-link-underline-opacity, 1)) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-light {
|
.link-light {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
--bs-success: #6610f2;
|
--bs-success: #6610f2;
|
||||||
--bs-info: #007bff;
|
--bs-info: #007bff;
|
||||||
--bs-warning: #ffc107;
|
--bs-warning: #ffc107;
|
||||||
--bs-danger: #8c3409;
|
--bs-danger: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-light: #f8f9fa;
|
--bs-light: #f8f9fa;
|
||||||
--bs-dark: #212529;
|
--bs-dark: #212529;
|
||||||
--bs-primary-rgb: 241, 100, 30;
|
--bs-primary-rgb: 241, 100, 30;
|
||||||
|
@ -45,28 +45,28 @@
|
||||||
--bs-danger-rgb: 140, 52, 9;
|
--bs-danger-rgb: 140, 52, 9;
|
||||||
--bs-light-rgb: 248, 249, 250;
|
--bs-light-rgb: 248, 249, 250;
|
||||||
--bs-dark-rgb: 33, 37, 41;
|
--bs-dark-rgb: 33, 37, 41;
|
||||||
--bs-primary-text-emphasis: #60280c;
|
--bs-primary-text-emphasis: rgb(96.4, 40, 12);
|
||||||
--bs-secondary-text-emphasis: #500000;
|
--bs-secondary-text-emphasis: #500000;
|
||||||
--bs-success-text-emphasis: #290661;
|
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8);
|
||||||
--bs-info-text-emphasis: #003166;
|
--bs-info-text-emphasis: rgb(0, 49.2, 102);
|
||||||
--bs-warning-text-emphasis: #664d03;
|
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8);
|
||||||
--bs-danger-text-emphasis: #381504;
|
--bs-danger-text-emphasis: rgb(55.9581589958, 20.8910460251, 3.4818410042);
|
||||||
--bs-light-text-emphasis: #495057;
|
--bs-light-text-emphasis: #495057;
|
||||||
--bs-dark-text-emphasis: #495057;
|
--bs-dark-text-emphasis: #495057;
|
||||||
--bs-primary-bg-subtle: #fce0d2;
|
--bs-primary-bg-subtle: rgb(252.2, 224, 210);
|
||||||
--bs-secondary-bg-subtle: #f4cccc;
|
--bs-secondary-bg-subtle: #f4cccc;
|
||||||
--bs-success-bg-subtle: #e0cffc;
|
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4);
|
||||||
--bs-info-bg-subtle: #cce5ff;
|
--bs-info-bg-subtle: rgb(204, 228.6, 255);
|
||||||
--bs-warning-bg-subtle: #fff3cd;
|
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4);
|
||||||
--bs-danger-bg-subtle: #e8d6ce;
|
--bs-danger-bg-subtle: rgb(231.9790794979, 214.4455230126, 205.7409205021);
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #f9c1a5;
|
--bs-primary-border-subtle: rgb(249.4, 193, 165);
|
||||||
--bs-secondary-border-subtle: #e99999;
|
--bs-secondary-border-subtle: #e99999;
|
||||||
--bs-success-border-subtle: #c29ffa;
|
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8);
|
||||||
--bs-info-border-subtle: #99caff;
|
--bs-info-border-subtle: rgb(153, 202.2, 255);
|
||||||
--bs-warning-border-subtle: #ffe69c;
|
--bs-warning-border-subtle: rgb(255, 230.2, 155.8);
|
||||||
--bs-danger-border-subtle: #d1ae9d;
|
--bs-danger-border-subtle: rgb(208.9581589958, 173.8910460251, 156.4818410042);
|
||||||
--bs-light-border-subtle: #e9ecef;
|
--bs-light-border-subtle: #e9ecef;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
--bs-white-rgb: 255, 255, 255;
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
--bs-link-color: #f1641e;
|
--bs-link-color: #f1641e;
|
||||||
--bs-link-color-rgb: 241, 100, 30;
|
--bs-link-color-rgb: 241, 100, 30;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #c15018;
|
--bs-link-hover-color: rgb(192.8, 80, 24);
|
||||||
--bs-link-hover-color-rgb: 193, 80, 24;
|
--bs-link-hover-color-rgb: 193, 80, 24;
|
||||||
--bs-code-color: #d63384;
|
--bs-code-color: #d63384;
|
||||||
--bs-highlight-color: #495057;
|
--bs-highlight-color: #495057;
|
||||||
|
@ -122,8 +122,8 @@
|
||||||
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
|
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
|
||||||
--bs-form-valid-color: #007bff;
|
--bs-form-valid-color: #007bff;
|
||||||
--bs-form-valid-border-color: #007bff;
|
--bs-form-valid-border-color: #007bff;
|
||||||
--bs-form-invalid-color: #8c3409;
|
--bs-form-invalid-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-form-invalid-border-color: #8c3409;
|
--bs-form-invalid-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] {
|
[data-bs-theme=dark] {
|
||||||
|
@ -140,46 +140,46 @@
|
||||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #2b3035;
|
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5);
|
||||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||||
--bs-primary-text-emphasis: #f7a278;
|
--bs-primary-text-emphasis: rgb(246.6, 162, 120);
|
||||||
--bs-secondary-text-emphasis: #de6666;
|
--bs-secondary-text-emphasis: #de6666;
|
||||||
--bs-success-text-emphasis: #a370f7;
|
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2);
|
||||||
--bs-info-text-emphasis: #66b0ff;
|
--bs-info-text-emphasis: rgb(102, 175.8, 255);
|
||||||
--bs-warning-text-emphasis: #ffda6a;
|
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2);
|
||||||
--bs-danger-text-emphasis: #ba856b;
|
--bs-danger-text-emphasis: rgb(185.9372384937, 133.3365690377, 107.2227615063);
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #301406;
|
--bs-primary-bg-subtle: rgb(48.2, 20, 6);
|
||||||
--bs-secondary-bg-subtle: #280000;
|
--bs-secondary-bg-subtle: #280000;
|
||||||
--bs-success-bg-subtle: #140330;
|
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4);
|
||||||
--bs-info-bg-subtle: #001933;
|
--bs-info-bg-subtle: rgb(0, 24.6, 51);
|
||||||
--bs-warning-bg-subtle: #332701;
|
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4);
|
||||||
--bs-danger-bg-subtle: #1c0a02;
|
--bs-danger-bg-subtle: rgb(27.9790794979, 10.4455230126, 1.7409205021);
|
||||||
--bs-light-bg-subtle: #343a40;
|
--bs-light-bg-subtle: #343a40;
|
||||||
--bs-dark-bg-subtle: #2b2e31;
|
--bs-dark-bg-subtle: #2b2e31;
|
||||||
--bs-primary-border-subtle: #913c12;
|
--bs-primary-border-subtle: rgb(144.6, 60, 18);
|
||||||
--bs-secondary-border-subtle: #780000;
|
--bs-secondary-border-subtle: #780000;
|
||||||
--bs-success-border-subtle: #3d0a91;
|
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2);
|
||||||
--bs-info-border-subtle: #004a99;
|
--bs-info-border-subtle: rgb(0, 73.8, 153);
|
||||||
--bs-warning-border-subtle: #997404;
|
--bs-warning-border-subtle: rgb(153, 115.8, 4.2);
|
||||||
--bs-danger-border-subtle: #541f05;
|
--bs-danger-border-subtle: rgb(83.9372384937, 31.3365690377, 5.2227615063);
|
||||||
--bs-light-border-subtle: #495057;
|
--bs-light-border-subtle: #495057;
|
||||||
--bs-dark-border-subtle: #343a40;
|
--bs-dark-border-subtle: #343a40;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #f7a278;
|
--bs-link-color: rgb(246.6, 162, 120);
|
||||||
--bs-link-hover-color: #f9b593;
|
--bs-link-hover-color: rgb(248.28, 180.6, 147);
|
||||||
--bs-link-color-rgb: 247, 162, 120;
|
--bs-link-color-rgb: 247, 162, 120;
|
||||||
--bs-link-hover-color-rgb: 249, 181, 147;
|
--bs-link-hover-color-rgb: 248, 181, 147;
|
||||||
--bs-code-color: #e685b5;
|
--bs-code-color: rgb(230.4, 132.6, 181.2);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #664d03;
|
--bs-highlight-bg: rgb(102, 77.2, 2.8);
|
||||||
--bs-border-color: #495057;
|
--bs-border-color: #495057;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #66cb90;
|
--bs-form-valid-color: rgb(102, 202.8, 144);
|
||||||
--bs-form-valid-border-color: #66cb90;
|
--bs-form-valid-border-color: rgb(102, 202.8, 144);
|
||||||
--bs-form-invalid-color: #e891a6;
|
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6);
|
||||||
--bs-form-invalid-border-color: #e891a6;
|
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -1934,13 +1934,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #fce0d2;
|
--bs-table-bg: rgb(252.2, 224, 210);
|
||||||
--bs-table-border-color: #d0baaf;
|
--bs-table-border-color: rgb(208.56, 186, 174.8);
|
||||||
--bs-table-striped-bg: #f1d7c9;
|
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e6cdc0;
|
--bs-table-active-bg: rgb(230.38, 205, 192.4);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #ecd2c5;
|
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1950,11 +1950,11 @@ progress {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #f4cccc;
|
--bs-table-bg: #f4cccc;
|
||||||
--bs-table-border-color: #caaaaa;
|
--bs-table-border-color: #caaaaa;
|
||||||
--bs-table-striped-bg: #eac4c4;
|
--bs-table-striped-bg: rgb(233.5, 195.5, 195.5);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #dfbbbb;
|
--bs-table-active-bg: #dfbbbb;
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #e4bfbf;
|
--bs-table-hover-bg: rgb(228.25, 191.25, 191.25);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1962,13 +1962,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #e0cffc;
|
--bs-table-bg: rgb(224.4, 207.2, 252.4);
|
||||||
--bs-table-border-color: #baacd0;
|
--bs-table-border-color: rgb(186.32, 172.56, 208.72);
|
||||||
--bs-table-striped-bg: #d7c6f1;
|
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #cdbee6;
|
--bs-table-active-bg: rgb(205.36, 189.88, 230.56);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #d2c2ec;
|
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1976,13 +1976,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #cce5ff;
|
--bs-table-bg: rgb(204, 228.6, 255);
|
||||||
--bs-table-border-color: #aabed3;
|
--bs-table-border-color: rgb(170, 189.68, 210.8);
|
||||||
--bs-table-striped-bg: #c4dbf4;
|
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #bbd2e9;
|
--bs-table-active-bg: rgb(187, 209.14, 232.9);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #bfd6ee;
|
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1990,13 +1990,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #fff3cd;
|
--bs-table-bg: rgb(255, 242.6, 205.4);
|
||||||
--bs-table-border-color: #d3c9ab;
|
--bs-table-border-color: rgb(210.8, 200.88, 171.12);
|
||||||
--bs-table-striped-bg: #f4e9c4;
|
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e9debc;
|
--bs-table-active-bg: rgb(232.9, 221.74, 188.26);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #eee3c0;
|
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2004,13 +2004,13 @@ progress {
|
||||||
|
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #e8d6ce;
|
--bs-table-bg: rgb(231.9790794979, 214.4455230126, 205.7409205021);
|
||||||
--bs-table-border-color: #c0b2ac;
|
--bs-table-border-color: rgb(192.3832635983, 178.35641841, 171.3927364017);
|
||||||
--bs-table-striped-bg: #decdc5;
|
--bs-table-striped-bg: rgb(222.080125523, 205.4232468619, 197.153874477);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #d4c4bd;
|
--bs-table-active-bg: rgb(212.1811715481, 196.4009707113, 188.5668284519);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #d9c9c1;
|
--bs-table-hover-bg: rgb(217.1306485356, 200.9121087866, 192.8603514644);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2019,12 +2019,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #f8f9fa;
|
--bs-table-bg: #f8f9fa;
|
||||||
--bs-table-border-color: #cdcecf;
|
--bs-table-border-color: rgb(205.2, 206, 206.8);
|
||||||
--bs-table-striped-bg: #edeeef;
|
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e3e4e4;
|
--bs-table-active-bg: rgb(226.6, 227.5, 228.4);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #e8e9ea;
|
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2033,12 +2033,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #212529;
|
--bs-table-bg: #212529;
|
||||||
--bs-table-border-color: #4d5154;
|
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-table-striped-bg: #2c3034;
|
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #373b3e;
|
--bs-table-active-bg: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #323539;
|
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2138,7 +2138,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: var(--bs-body-color);
|
color: var(--bs-body-color);
|
||||||
background-color: var(--bs-body-bg);
|
background-color: var(--bs-body-bg);
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2283,7 +2283,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
|
||||||
}
|
}
|
||||||
|
@ -2367,7 +2367,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2414,7 +2414,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f8b28f'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28248, 177.5, 142.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2484,7 +2484,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #fbd1bc;
|
background-color: rgb(250.8, 208.5, 187.5);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2510,7 +2510,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #fbd1bc;
|
background-color: rgb(250.8, 208.5, 187.5);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2833,7 +2833,7 @@ textarea.form-control-lg {
|
||||||
.was-validated .form-control:invalid, .form-control.is-invalid {
|
.was-validated .form-control:invalid, .form-control.is-invalid {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
padding-right: calc(1.5em + 0.75rem);
|
padding-right: calc(1.5em + 0.75rem);
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%238c3409'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%238c3409' stroke='none'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29' stroke='none'/%3e%3c/svg%3e");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: right calc(0.375em + 0.1875rem) center;
|
background-position: right calc(0.375em + 0.1875rem) center;
|
||||||
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||||
|
@ -2852,7 +2852,7 @@ textarea.form-control-lg {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
}
|
}
|
||||||
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
|
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
|
||||||
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%238c3409'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%238c3409' stroke='none'/%3e%3c/svg%3e");
|
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29' stroke='none'/%3e%3c/svg%3e");
|
||||||
padding-right: 4.125rem;
|
padding-right: 4.125rem;
|
||||||
background-position: right 0.75rem center, center right 2.25rem;
|
background-position: right 0.75rem center, center right 2.25rem;
|
||||||
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||||
|
@ -2958,6 +2958,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2971,12 +2974,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f1641e;
|
--bs-btn-bg: #f1641e;
|
||||||
--bs-btn-border-color: #f1641e;
|
--bs-btn-border-color: #f1641e;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #cd551a;
|
--bs-btn-hover-bg: rgb(204.85, 85, 25.5);
|
||||||
--bs-btn-hover-border-color: #c15018;
|
--bs-btn-hover-border-color: rgb(192.8, 80, 24);
|
||||||
--bs-btn-focus-shadow-rgb: 243, 123, 64;
|
--bs-btn-focus-shadow-rgb: 243, 123, 64;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #c15018;
|
--bs-btn-active-bg: rgb(192.8, 80, 24);
|
||||||
--bs-btn-active-border-color: #b54b17;
|
--bs-btn-active-border-color: rgb(180.75, 75, 22.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #f1641e;
|
--bs-btn-disabled-bg: #f1641e;
|
||||||
|
@ -3005,12 +3008,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #6610f2;
|
--bs-btn-bg: #6610f2;
|
||||||
--bs-btn-border-color: #6610f2;
|
--bs-btn-border-color: #6610f2;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #570ece;
|
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7);
|
||||||
--bs-btn-hover-border-color: #520dc2;
|
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6);
|
||||||
--bs-btn-focus-shadow-rgb: 125, 52, 244;
|
--bs-btn-focus-shadow-rgb: 125, 52, 244;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #520dc2;
|
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6);
|
||||||
--bs-btn-active-border-color: #4d0cb6;
|
--bs-btn-active-border-color: rgb(76.5, 12, 181.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #6610f2;
|
--bs-btn-disabled-bg: #6610f2;
|
||||||
|
@ -3022,12 +3025,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #007bff;
|
--bs-btn-bg: #007bff;
|
||||||
--bs-btn-border-color: #007bff;
|
--bs-btn-border-color: #007bff;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #0069d9;
|
--bs-btn-hover-bg: rgb(0, 104.55, 216.75);
|
||||||
--bs-btn-hover-border-color: #0062cc;
|
--bs-btn-hover-border-color: rgb(0, 98.4, 204);
|
||||||
--bs-btn-focus-shadow-rgb: 38, 143, 255;
|
--bs-btn-focus-shadow-rgb: 38, 143, 255;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #0062cc;
|
--bs-btn-active-bg: rgb(0, 98.4, 204);
|
||||||
--bs-btn-active-border-color: #005cbf;
|
--bs-btn-active-border-color: rgb(0, 92.25, 191.25);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #007bff;
|
--bs-btn-disabled-bg: #007bff;
|
||||||
|
@ -3039,12 +3042,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #ffc107;
|
--bs-btn-bg: #ffc107;
|
||||||
--bs-btn-border-color: #ffc107;
|
--bs-btn-border-color: #ffc107;
|
||||||
--bs-btn-hover-color: #222;
|
--bs-btn-hover-color: #222;
|
||||||
--bs-btn-hover-bg: #ffca2c;
|
--bs-btn-hover-bg: rgb(255, 202.3, 44.2);
|
||||||
--bs-btn-hover-border-color: #ffc720;
|
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8);
|
||||||
--bs-btn-focus-shadow-rgb: 222, 169, 11;
|
--bs-btn-focus-shadow-rgb: 222, 169, 11;
|
||||||
--bs-btn-active-color: #222;
|
--bs-btn-active-color: #222;
|
||||||
--bs-btn-active-bg: #ffcd39;
|
--bs-btn-active-bg: rgb(255, 205.4, 56.6);
|
||||||
--bs-btn-active-border-color: #ffc720;
|
--bs-btn-active-border-color: rgb(255, 199.2, 31.8);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #222;
|
--bs-btn-disabled-color: #222;
|
||||||
--bs-btn-disabled-bg: #ffc107;
|
--bs-btn-disabled-bg: #ffc107;
|
||||||
|
@ -3053,19 +3056,19 @@ textarea.form-control-lg {
|
||||||
|
|
||||||
.btn-danger {
|
.btn-danger {
|
||||||
--bs-btn-color: #fff;
|
--bs-btn-color: #fff;
|
||||||
--bs-btn-bg: #8c3409;
|
--bs-btn-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-border-color: #8c3409;
|
--bs-btn-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #772c08;
|
--bs-btn-hover-bg: rgb(118.9110878661, 44.3934728033, 7.3989121339);
|
||||||
--bs-btn-hover-border-color: #702a07;
|
--bs-btn-hover-border-color: rgb(111.9163179916, 41.7820920502, 6.9636820084);
|
||||||
--bs-btn-focus-shadow-rgb: 157, 82, 46;
|
--bs-btn-focus-shadow-rgb: 157, 83, 46;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #702a07;
|
--bs-btn-active-bg: rgb(111.9163179916, 41.7820920502, 6.9636820084);
|
||||||
--bs-btn-active-border-color: #692707;
|
--bs-btn-active-border-color: rgb(104.9215481172, 39.1707112971, 6.5284518828);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #8c3409;
|
--bs-btn-disabled-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-disabled-border-color: #8c3409;
|
--bs-btn-disabled-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-light {
|
.btn-light {
|
||||||
|
@ -3073,12 +3076,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f8f9fa;
|
--bs-btn-bg: #f8f9fa;
|
||||||
--bs-btn-border-color: #f8f9fa;
|
--bs-btn-border-color: #f8f9fa;
|
||||||
--bs-btn-hover-color: #222;
|
--bs-btn-hover-color: #222;
|
||||||
--bs-btn-hover-bg: #d3d4d5;
|
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5);
|
||||||
--bs-btn-hover-border-color: #c6c7c8;
|
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200);
|
||||||
--bs-btn-focus-shadow-rgb: 216, 217, 218;
|
--bs-btn-focus-shadow-rgb: 216, 217, 218;
|
||||||
--bs-btn-active-color: #222;
|
--bs-btn-active-color: #222;
|
||||||
--bs-btn-active-bg: #c6c7c8;
|
--bs-btn-active-bg: rgb(198.4, 199.2, 200);
|
||||||
--bs-btn-active-border-color: #babbbc;
|
--bs-btn-active-border-color: rgb(186, 186.75, 187.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #222;
|
--bs-btn-disabled-color: #222;
|
||||||
--bs-btn-disabled-bg: #f8f9fa;
|
--bs-btn-disabled-bg: #f8f9fa;
|
||||||
|
@ -3090,12 +3093,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #212529;
|
--bs-btn-bg: #212529;
|
||||||
--bs-btn-border-color: #212529;
|
--bs-btn-border-color: #212529;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #424649;
|
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
|
||||||
--bs-btn-hover-border-color: #373b3e;
|
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #4d5154;
|
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-btn-active-border-color: #373b3e;
|
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #212529;
|
--bs-btn-disabled-bg: #212529;
|
||||||
|
@ -3188,19 +3191,19 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-outline-danger {
|
.btn-outline-danger {
|
||||||
--bs-btn-color: #8c3409;
|
--bs-btn-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-border-color: #8c3409;
|
--bs-btn-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #8c3409;
|
--bs-btn-hover-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-hover-border-color: #8c3409;
|
--bs-btn-hover-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-focus-shadow-rgb: 140, 52, 9;
|
--bs-btn-focus-shadow-rgb: 140, 52, 9;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #8c3409;
|
--bs-btn-active-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-active-border-color: #8c3409;
|
--bs-btn-active-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #8c3409;
|
--bs-btn-disabled-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-btn-disabled-bg: transparent;
|
--bs-btn-disabled-bg: transparent;
|
||||||
--bs-btn-disabled-border-color: #8c3409;
|
--bs-btn-disabled-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
|
||||||
--bs-gradient: none;
|
--bs-gradient: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4486,12 +4489,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2360280c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2896.4, 40, 12%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #f8b28f;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4549,7 +4551,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4567,7 +4568,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4578,11 +4579,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4591,27 +4592,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -5485,7 +5486,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6050,20 +6050,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6683,14 +6675,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
--bs-success: #6610f2;
|
--bs-success: #6610f2;
|
||||||
--bs-info: #007bff;
|
--bs-info: #007bff;
|
||||||
--bs-warning: #ffc107;
|
--bs-warning: #ffc107;
|
||||||
--bs-danger: #873208;
|
--bs-danger: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-light: #f8f9fa;
|
--bs-light: #f8f9fa;
|
||||||
--bs-dark: #212529;
|
--bs-dark: #212529;
|
||||||
--bs-primary-rgb: 241, 100, 30;
|
--bs-primary-rgb: 241, 100, 30;
|
||||||
|
@ -45,28 +45,28 @@
|
||||||
--bs-danger-rgb: 135, 50, 8;
|
--bs-danger-rgb: 135, 50, 8;
|
||||||
--bs-light-rgb: 248, 249, 250;
|
--bs-light-rgb: 248, 249, 250;
|
||||||
--bs-dark-rgb: 33, 37, 41;
|
--bs-dark-rgb: 33, 37, 41;
|
||||||
--bs-primary-text-emphasis: #60280c;
|
--bs-primary-text-emphasis: rgb(96.4, 40, 12);
|
||||||
--bs-secondary-text-emphasis: #00431c;
|
--bs-secondary-text-emphasis: rgb(0, 67.2, 28);
|
||||||
--bs-success-text-emphasis: #290661;
|
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8);
|
||||||
--bs-info-text-emphasis: #003166;
|
--bs-info-text-emphasis: rgb(0, 49.2, 102);
|
||||||
--bs-warning-text-emphasis: #664d03;
|
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8);
|
||||||
--bs-danger-text-emphasis: #361403;
|
--bs-danger-text-emphasis: rgb(54.0376569038, 20.1740585774, 3.3623430962);
|
||||||
--bs-light-text-emphasis: #495057;
|
--bs-light-text-emphasis: #495057;
|
||||||
--bs-dark-text-emphasis: #495057;
|
--bs-dark-text-emphasis: #495057;
|
||||||
--bs-primary-bg-subtle: #fce0d2;
|
--bs-primary-bg-subtle: rgb(252.2, 224, 210);
|
||||||
--bs-secondary-bg-subtle: #cceeda;
|
--bs-secondary-bg-subtle: rgb(204, 237.6, 218);
|
||||||
--bs-success-bg-subtle: #e0cffc;
|
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4);
|
||||||
--bs-info-bg-subtle: #cce5ff;
|
--bs-info-bg-subtle: rgb(204, 228.6, 255);
|
||||||
--bs-warning-bg-subtle: #fff3cd;
|
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4);
|
||||||
--bs-danger-bg-subtle: #e7d6ce;
|
--bs-danger-bg-subtle: rgb(231.0188284519, 214.0870292887, 205.6811715481);
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #f9c1a5;
|
--bs-primary-border-subtle: rgb(249.4, 193, 165);
|
||||||
--bs-secondary-border-subtle: #99dcb5;
|
--bs-secondary-border-subtle: rgb(153, 220.2, 181);
|
||||||
--bs-success-border-subtle: #c29ffa;
|
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8);
|
||||||
--bs-info-border-subtle: #99caff;
|
--bs-info-border-subtle: rgb(153, 202.2, 255);
|
||||||
--bs-warning-border-subtle: #ffe69c;
|
--bs-warning-border-subtle: rgb(255, 230.2, 155.8);
|
||||||
--bs-danger-border-subtle: #cfad9c;
|
--bs-danger-border-subtle: rgb(207.0376569038, 173.1740585774, 156.3623430962);
|
||||||
--bs-light-border-subtle: #e9ecef;
|
--bs-light-border-subtle: #e9ecef;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
--bs-white-rgb: 255, 255, 255;
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
--bs-link-color: #f1641e;
|
--bs-link-color: #f1641e;
|
||||||
--bs-link-color-rgb: 241, 100, 30;
|
--bs-link-color-rgb: 241, 100, 30;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #c15018;
|
--bs-link-hover-color: rgb(192.8, 80, 24);
|
||||||
--bs-link-hover-color-rgb: 193, 80, 24;
|
--bs-link-hover-color-rgb: 193, 80, 24;
|
||||||
--bs-code-color: #d63384;
|
--bs-code-color: #d63384;
|
||||||
--bs-highlight-color: #495057;
|
--bs-highlight-color: #495057;
|
||||||
|
@ -122,8 +122,8 @@
|
||||||
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
|
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
|
||||||
--bs-form-valid-color: #007bff;
|
--bs-form-valid-color: #007bff;
|
||||||
--bs-form-valid-border-color: #007bff;
|
--bs-form-valid-border-color: #007bff;
|
||||||
--bs-form-invalid-color: #873208;
|
--bs-form-invalid-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-form-invalid-border-color: #873208;
|
--bs-form-invalid-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] {
|
[data-bs-theme=dark] {
|
||||||
|
@ -140,46 +140,46 @@
|
||||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #2b3035;
|
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5);
|
||||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||||
--bs-primary-text-emphasis: #f7a278;
|
--bs-primary-text-emphasis: rgb(246.6, 162, 120);
|
||||||
--bs-secondary-text-emphasis: #66cb90;
|
--bs-secondary-text-emphasis: rgb(102, 202.8, 144);
|
||||||
--bs-success-text-emphasis: #a370f7;
|
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2);
|
||||||
--bs-info-text-emphasis: #66b0ff;
|
--bs-info-text-emphasis: rgb(102, 175.8, 255);
|
||||||
--bs-warning-text-emphasis: #ffda6a;
|
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2);
|
||||||
--bs-danger-text-emphasis: #b7846b;
|
--bs-danger-text-emphasis: rgb(183.0564853556, 132.2610878661, 107.0435146444);
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #301406;
|
--bs-primary-bg-subtle: rgb(48.2, 20, 6);
|
||||||
--bs-secondary-bg-subtle: #00220e;
|
--bs-secondary-bg-subtle: rgb(0, 33.6, 14);
|
||||||
--bs-success-bg-subtle: #140330;
|
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4);
|
||||||
--bs-info-bg-subtle: #001933;
|
--bs-info-bg-subtle: rgb(0, 24.6, 51);
|
||||||
--bs-warning-bg-subtle: #332701;
|
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4);
|
||||||
--bs-danger-bg-subtle: #1b0a02;
|
--bs-danger-bg-subtle: rgb(27.0188284519, 10.0870292887, 1.6811715481);
|
||||||
--bs-light-bg-subtle: #343a40;
|
--bs-light-bg-subtle: #343a40;
|
||||||
--bs-dark-bg-subtle: #2b2e31;
|
--bs-dark-bg-subtle: #2b2e31;
|
||||||
--bs-primary-border-subtle: #913c12;
|
--bs-primary-border-subtle: rgb(144.6, 60, 18);
|
||||||
--bs-secondary-border-subtle: #00652a;
|
--bs-secondary-border-subtle: rgb(0, 100.8, 42);
|
||||||
--bs-success-border-subtle: #3d0a91;
|
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2);
|
||||||
--bs-info-border-subtle: #004a99;
|
--bs-info-border-subtle: rgb(0, 73.8, 153);
|
||||||
--bs-warning-border-subtle: #997404;
|
--bs-warning-border-subtle: rgb(153, 115.8, 4.2);
|
||||||
--bs-danger-border-subtle: #511e05;
|
--bs-danger-border-subtle: rgb(81.0564853556, 30.2610878661, 5.0435146444);
|
||||||
--bs-light-border-subtle: #495057;
|
--bs-light-border-subtle: #495057;
|
||||||
--bs-dark-border-subtle: #343a40;
|
--bs-dark-border-subtle: #343a40;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #f7a278;
|
--bs-link-color: rgb(246.6, 162, 120);
|
||||||
--bs-link-hover-color: #f9b593;
|
--bs-link-hover-color: rgb(248.28, 180.6, 147);
|
||||||
--bs-link-color-rgb: 247, 162, 120;
|
--bs-link-color-rgb: 247, 162, 120;
|
||||||
--bs-link-hover-color-rgb: 249, 181, 147;
|
--bs-link-hover-color-rgb: 248, 181, 147;
|
||||||
--bs-code-color: #e685b5;
|
--bs-code-color: rgb(230.4, 132.6, 181.2);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #664d03;
|
--bs-highlight-bg: rgb(102, 77.2, 2.8);
|
||||||
--bs-border-color: #495057;
|
--bs-border-color: #495057;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #66cb90;
|
--bs-form-valid-color: rgb(102, 202.8, 144);
|
||||||
--bs-form-valid-border-color: #66cb90;
|
--bs-form-valid-border-color: rgb(102, 202.8, 144);
|
||||||
--bs-form-invalid-color: #e891a6;
|
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6);
|
||||||
--bs-form-invalid-border-color: #e891a6;
|
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -1934,13 +1934,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #fce0d2;
|
--bs-table-bg: rgb(252.2, 224, 210);
|
||||||
--bs-table-border-color: #d0baaf;
|
--bs-table-border-color: rgb(208.56, 186, 174.8);
|
||||||
--bs-table-striped-bg: #f1d7c9;
|
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e6cdc0;
|
--bs-table-active-bg: rgb(230.38, 205, 192.4);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #ecd2c5;
|
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1948,13 +1948,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #cceeda;
|
--bs-table-bg: rgb(204, 237.6, 218);
|
||||||
--bs-table-border-color: #aac5b5;
|
--bs-table-border-color: rgb(170, 196.88, 181.2);
|
||||||
--bs-table-striped-bg: #c4e4d1;
|
--bs-table-striped-bg: rgb(195.5, 227.42, 208.8);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #bbdac8;
|
--bs-table-active-bg: rgb(187, 217.24, 199.6);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #bfdfcc;
|
--bs-table-hover-bg: rgb(191.25, 222.33, 204.2);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1962,13 +1962,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #e0cffc;
|
--bs-table-bg: rgb(224.4, 207.2, 252.4);
|
||||||
--bs-table-border-color: #baacd0;
|
--bs-table-border-color: rgb(186.32, 172.56, 208.72);
|
||||||
--bs-table-striped-bg: #d7c6f1;
|
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #cdbee6;
|
--bs-table-active-bg: rgb(205.36, 189.88, 230.56);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #d2c2ec;
|
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1976,13 +1976,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #cce5ff;
|
--bs-table-bg: rgb(204, 228.6, 255);
|
||||||
--bs-table-border-color: #aabed3;
|
--bs-table-border-color: rgb(170, 189.68, 210.8);
|
||||||
--bs-table-striped-bg: #c4dbf4;
|
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #bbd2e9;
|
--bs-table-active-bg: rgb(187, 209.14, 232.9);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #bfd6ee;
|
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1990,13 +1990,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #fff3cd;
|
--bs-table-bg: rgb(255, 242.6, 205.4);
|
||||||
--bs-table-border-color: #d3c9ab;
|
--bs-table-border-color: rgb(210.8, 200.88, 171.12);
|
||||||
--bs-table-striped-bg: #f4e9c4;
|
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e9debc;
|
--bs-table-active-bg: rgb(232.9, 221.74, 188.26);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #eee3c0;
|
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2004,13 +2004,13 @@ progress {
|
||||||
|
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #e7d6ce;
|
--bs-table-bg: rgb(231.0188284519, 214.0870292887, 205.6811715481);
|
||||||
--bs-table-border-color: #c0b2ac;
|
--bs-table-border-color: rgb(191.6150627615, 178.069623431, 171.3449372385);
|
||||||
--bs-table-striped-bg: #ddcdc5;
|
--bs-table-striped-bg: rgb(221.1678870293, 205.0826778243, 197.0971129707);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #d3c4bd;
|
--bs-table-active-bg: rgb(211.3169456067, 196.0783263598, 188.5130543933);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #d8c9c1;
|
--bs-table-hover-bg: rgb(216.242416318, 200.5805020921, 192.805083682);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2019,12 +2019,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #222;
|
--bs-table-color: #222;
|
||||||
--bs-table-bg: #f8f9fa;
|
--bs-table-bg: #f8f9fa;
|
||||||
--bs-table-border-color: #cdcecf;
|
--bs-table-border-color: rgb(205.2, 206, 206.8);
|
||||||
--bs-table-striped-bg: #edeeef;
|
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2);
|
||||||
--bs-table-striped-color: #222;
|
--bs-table-striped-color: #222;
|
||||||
--bs-table-active-bg: #e3e4e4;
|
--bs-table-active-bg: rgb(226.6, 227.5, 228.4);
|
||||||
--bs-table-active-color: #222;
|
--bs-table-active-color: #222;
|
||||||
--bs-table-hover-bg: #e8e9ea;
|
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8);
|
||||||
--bs-table-hover-color: #222;
|
--bs-table-hover-color: #222;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2033,12 +2033,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #212529;
|
--bs-table-bg: #212529;
|
||||||
--bs-table-border-color: #4d5154;
|
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-table-striped-bg: #2c3034;
|
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #373b3e;
|
--bs-table-active-bg: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #323539;
|
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2138,7 +2138,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: var(--bs-body-color);
|
color: var(--bs-body-color);
|
||||||
background-color: var(--bs-body-bg);
|
background-color: var(--bs-body-bg);
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2283,7 +2283,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
|
||||||
}
|
}
|
||||||
|
@ -2367,7 +2367,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #f8b28f;
|
border-color: rgb(248, 177.5, 142.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2414,7 +2414,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f8b28f'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28248, 177.5, 142.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2484,7 +2484,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #fbd1bc;
|
background-color: rgb(250.8, 208.5, 187.5);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2510,7 +2510,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #fbd1bc;
|
background-color: rgb(250.8, 208.5, 187.5);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -2833,7 +2833,7 @@ textarea.form-control-lg {
|
||||||
.was-validated .form-control:invalid, .form-control.is-invalid {
|
.was-validated .form-control:invalid, .form-control.is-invalid {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
padding-right: calc(1.5em + 0.75rem);
|
padding-right: calc(1.5em + 0.75rem);
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: right calc(0.375em + 0.1875rem) center;
|
background-position: right calc(0.375em + 0.1875rem) center;
|
||||||
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||||
|
@ -2852,7 +2852,7 @@ textarea.form-control-lg {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
}
|
}
|
||||||
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
|
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
|
||||||
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
|
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e");
|
||||||
padding-right: 4.125rem;
|
padding-right: 4.125rem;
|
||||||
background-position: right 0.75rem center, center right 2.25rem;
|
background-position: right 0.75rem center, center right 2.25rem;
|
||||||
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||||
|
@ -2958,6 +2958,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2971,12 +2974,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f1641e;
|
--bs-btn-bg: #f1641e;
|
||||||
--bs-btn-border-color: #f1641e;
|
--bs-btn-border-color: #f1641e;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #cd551a;
|
--bs-btn-hover-bg: rgb(204.85, 85, 25.5);
|
||||||
--bs-btn-hover-border-color: #c15018;
|
--bs-btn-hover-border-color: rgb(192.8, 80, 24);
|
||||||
--bs-btn-focus-shadow-rgb: 243, 123, 64;
|
--bs-btn-focus-shadow-rgb: 243, 123, 64;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #c15018;
|
--bs-btn-active-bg: rgb(192.8, 80, 24);
|
||||||
--bs-btn-active-border-color: #b54b17;
|
--bs-btn-active-border-color: rgb(180.75, 75, 22.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #f1641e;
|
--bs-btn-disabled-bg: #f1641e;
|
||||||
|
@ -2988,12 +2991,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #00a846;
|
--bs-btn-bg: #00a846;
|
||||||
--bs-btn-border-color: #00a846;
|
--bs-btn-border-color: #00a846;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #008f3c;
|
--bs-btn-hover-bg: rgb(0, 142.8, 59.5);
|
||||||
--bs-btn-hover-border-color: #008638;
|
--bs-btn-hover-border-color: rgb(0, 134.4, 56);
|
||||||
--bs-btn-focus-shadow-rgb: 38, 181, 98;
|
--bs-btn-focus-shadow-rgb: 38, 181, 98;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #008638;
|
--bs-btn-active-bg: rgb(0, 134.4, 56);
|
||||||
--bs-btn-active-border-color: #007e35;
|
--bs-btn-active-border-color: rgb(0, 126, 52.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #00a846;
|
--bs-btn-disabled-bg: #00a846;
|
||||||
|
@ -3005,12 +3008,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #6610f2;
|
--bs-btn-bg: #6610f2;
|
||||||
--bs-btn-border-color: #6610f2;
|
--bs-btn-border-color: #6610f2;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #570ece;
|
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7);
|
||||||
--bs-btn-hover-border-color: #520dc2;
|
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6);
|
||||||
--bs-btn-focus-shadow-rgb: 125, 52, 244;
|
--bs-btn-focus-shadow-rgb: 125, 52, 244;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #520dc2;
|
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6);
|
||||||
--bs-btn-active-border-color: #4d0cb6;
|
--bs-btn-active-border-color: rgb(76.5, 12, 181.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #6610f2;
|
--bs-btn-disabled-bg: #6610f2;
|
||||||
|
@ -3022,12 +3025,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #007bff;
|
--bs-btn-bg: #007bff;
|
||||||
--bs-btn-border-color: #007bff;
|
--bs-btn-border-color: #007bff;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #0069d9;
|
--bs-btn-hover-bg: rgb(0, 104.55, 216.75);
|
||||||
--bs-btn-hover-border-color: #0062cc;
|
--bs-btn-hover-border-color: rgb(0, 98.4, 204);
|
||||||
--bs-btn-focus-shadow-rgb: 38, 143, 255;
|
--bs-btn-focus-shadow-rgb: 38, 143, 255;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #0062cc;
|
--bs-btn-active-bg: rgb(0, 98.4, 204);
|
||||||
--bs-btn-active-border-color: #005cbf;
|
--bs-btn-active-border-color: rgb(0, 92.25, 191.25);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #007bff;
|
--bs-btn-disabled-bg: #007bff;
|
||||||
|
@ -3039,12 +3042,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #ffc107;
|
--bs-btn-bg: #ffc107;
|
||||||
--bs-btn-border-color: #ffc107;
|
--bs-btn-border-color: #ffc107;
|
||||||
--bs-btn-hover-color: #222;
|
--bs-btn-hover-color: #222;
|
||||||
--bs-btn-hover-bg: #ffca2c;
|
--bs-btn-hover-bg: rgb(255, 202.3, 44.2);
|
||||||
--bs-btn-hover-border-color: #ffc720;
|
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8);
|
||||||
--bs-btn-focus-shadow-rgb: 222, 169, 11;
|
--bs-btn-focus-shadow-rgb: 222, 169, 11;
|
||||||
--bs-btn-active-color: #222;
|
--bs-btn-active-color: #222;
|
||||||
--bs-btn-active-bg: #ffcd39;
|
--bs-btn-active-bg: rgb(255, 205.4, 56.6);
|
||||||
--bs-btn-active-border-color: #ffc720;
|
--bs-btn-active-border-color: rgb(255, 199.2, 31.8);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #222;
|
--bs-btn-disabled-color: #222;
|
||||||
--bs-btn-disabled-bg: #ffc107;
|
--bs-btn-disabled-bg: #ffc107;
|
||||||
|
@ -3053,19 +3056,19 @@ textarea.form-control-lg {
|
||||||
|
|
||||||
.btn-danger {
|
.btn-danger {
|
||||||
--bs-btn-color: #fff;
|
--bs-btn-color: #fff;
|
||||||
--bs-btn-bg: #873208;
|
--bs-btn-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-border-color: #873208;
|
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #732b07;
|
--bs-btn-hover-bg: rgb(114.8300209205, 42.869874477, 7.1449790795);
|
||||||
--bs-btn-hover-border-color: #6c2806;
|
--bs-btn-hover-border-color: rgb(108.0753138075, 40.3481171548, 6.7246861925);
|
||||||
--bs-btn-focus-shadow-rgb: 153, 81, 45;
|
--bs-btn-focus-shadow-rgb: 153, 81, 45;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #6c2806;
|
--bs-btn-active-bg: rgb(108.0753138075, 40.3481171548, 6.7246861925);
|
||||||
--bs-btn-active-border-color: #652606;
|
--bs-btn-active-border-color: rgb(101.3206066946, 37.8263598326, 6.3043933054);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #873208;
|
--bs-btn-disabled-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-disabled-border-color: #873208;
|
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-light {
|
.btn-light {
|
||||||
|
@ -3073,12 +3076,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #f8f9fa;
|
--bs-btn-bg: #f8f9fa;
|
||||||
--bs-btn-border-color: #f8f9fa;
|
--bs-btn-border-color: #f8f9fa;
|
||||||
--bs-btn-hover-color: #222;
|
--bs-btn-hover-color: #222;
|
||||||
--bs-btn-hover-bg: #d3d4d5;
|
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5);
|
||||||
--bs-btn-hover-border-color: #c6c7c8;
|
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200);
|
||||||
--bs-btn-focus-shadow-rgb: 216, 217, 218;
|
--bs-btn-focus-shadow-rgb: 216, 217, 218;
|
||||||
--bs-btn-active-color: #222;
|
--bs-btn-active-color: #222;
|
||||||
--bs-btn-active-bg: #c6c7c8;
|
--bs-btn-active-bg: rgb(198.4, 199.2, 200);
|
||||||
--bs-btn-active-border-color: #babbbc;
|
--bs-btn-active-border-color: rgb(186, 186.75, 187.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #222;
|
--bs-btn-disabled-color: #222;
|
||||||
--bs-btn-disabled-bg: #f8f9fa;
|
--bs-btn-disabled-bg: #f8f9fa;
|
||||||
|
@ -3090,12 +3093,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #212529;
|
--bs-btn-bg: #212529;
|
||||||
--bs-btn-border-color: #212529;
|
--bs-btn-border-color: #212529;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #424649;
|
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
|
||||||
--bs-btn-hover-border-color: #373b3e;
|
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #4d5154;
|
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-btn-active-border-color: #373b3e;
|
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #212529;
|
--bs-btn-disabled-bg: #212529;
|
||||||
|
@ -3188,19 +3191,19 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-outline-danger {
|
.btn-outline-danger {
|
||||||
--bs-btn-color: #873208;
|
--bs-btn-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-border-color: #873208;
|
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #873208;
|
--bs-btn-hover-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-hover-border-color: #873208;
|
--bs-btn-hover-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-focus-shadow-rgb: 135, 50, 8;
|
--bs-btn-focus-shadow-rgb: 135, 50, 8;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #873208;
|
--bs-btn-active-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-active-border-color: #873208;
|
--bs-btn-active-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
|
||||||
--bs-btn-disabled-color: #873208;
|
--bs-btn-disabled-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-btn-disabled-bg: transparent;
|
--bs-btn-disabled-bg: transparent;
|
||||||
--bs-btn-disabled-border-color: #873208;
|
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
|
||||||
--bs-gradient: none;
|
--bs-gradient: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4486,12 +4489,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2360280c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2896.4, 40, 12%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #f8b28f;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4549,7 +4551,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4567,7 +4568,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4578,11 +4579,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4591,27 +4592,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -5485,7 +5486,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6050,20 +6050,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6683,14 +6675,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
@ -6845,8 +6834,8 @@ textarea.form-control-lg {
|
||||||
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
|
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
|
||||||
}
|
}
|
||||||
.link-danger:hover, .link-danger:focus {
|
.link-danger:hover, .link-danger:focus {
|
||||||
color: RGBA(108, 40, 6, var(--bs-link-opacity, 1)) !important;
|
color: RGBA(108, 40, 7, var(--bs-link-opacity, 1)) !important;
|
||||||
text-decoration-color: RGBA(108, 40, 6, var(--bs-link-underline-opacity, 1)) !important;
|
text-decoration-color: RGBA(108, 40, 7, var(--bs-link-underline-opacity, 1)) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-light {
|
.link-light {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -45,27 +45,27 @@
|
||||||
--bs-danger-rgb: 255, 95, 110;
|
--bs-danger-rgb: 255, 95, 110;
|
||||||
--bs-light-rgb: 68, 68, 68;
|
--bs-light-rgb: 68, 68, 68;
|
||||||
--bs-dark-rgb: 235, 235, 235;
|
--bs-dark-rgb: 235, 235, 235;
|
||||||
--bs-primary-text-emphasis: #661a4a;
|
--bs-primary-text-emphasis: rgb(102, 25.6, 74.4);
|
||||||
--bs-secondary-text-emphasis: #005266;
|
--bs-secondary-text-emphasis: rgb(0.4, 82, 101.6);
|
||||||
--bs-success-text-emphasis: #026640;
|
--bs-success-text-emphasis: rgb(2, 102, 64.4);
|
||||||
--bs-info-text-emphasis: #005266;
|
--bs-info-text-emphasis: rgb(0.4, 82, 101.6);
|
||||||
--bs-warning-text-emphasis: #66643c;
|
--bs-warning-text-emphasis: rgb(102, 100.4, 60);
|
||||||
--bs-danger-text-emphasis: #66262c;
|
--bs-danger-text-emphasis: #66262c;
|
||||||
--bs-light-text-emphasis: #444;
|
--bs-light-text-emphasis: #444;
|
||||||
--bs-dark-text-emphasis: #444;
|
--bs-dark-text-emphasis: #444;
|
||||||
--bs-primary-bg-subtle: #ffd9f1;
|
--bs-primary-bg-subtle: rgb(255, 216.8, 241.2);
|
||||||
--bs-secondary-bg-subtle: #ccf5ff;
|
--bs-secondary-bg-subtle: rgb(204.2, 245, 254.8);
|
||||||
--bs-success-bg-subtle: #cdffec;
|
--bs-success-bg-subtle: rgb(205, 255, 236.2);
|
||||||
--bs-info-bg-subtle: #ccf5ff;
|
--bs-info-bg-subtle: rgb(204.2, 245, 254.8);
|
||||||
--bs-warning-bg-subtle: #fffeea;
|
--bs-warning-bg-subtle: rgb(255, 254.2, 234);
|
||||||
--bs-danger-bg-subtle: #ffdfe2;
|
--bs-danger-bg-subtle: #ffdfe2;
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #ffb3e3;
|
--bs-primary-border-subtle: rgb(255, 178.6, 227.4);
|
||||||
--bs-secondary-border-subtle: #99ebff;
|
--bs-secondary-border-subtle: rgb(153.4, 235, 254.6);
|
||||||
--bs-success-border-subtle: #9bffd9;
|
--bs-success-border-subtle: rgb(155, 255, 217.4);
|
||||||
--bs-info-border-subtle: #99ebff;
|
--bs-info-border-subtle: rgb(153.4, 235, 254.6);
|
||||||
--bs-warning-border-subtle: #fffdd5;
|
--bs-warning-border-subtle: rgb(255, 253.4, 213);
|
||||||
--bs-danger-border-subtle: #ffbfc5;
|
--bs-danger-border-subtle: #ffbfc5;
|
||||||
--bs-light-border-subtle: #ebebeb;
|
--bs-light-border-subtle: #ebebeb;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
--bs-link-color: rgb(255, 64, 186);
|
--bs-link-color: rgb(255, 64, 186);
|
||||||
--bs-link-color-rgb: 255, 64, 186;
|
--bs-link-color-rgb: 255, 64, 186;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #cc3395;
|
--bs-link-hover-color: rgb(204, 51.2, 148.8);
|
||||||
--bs-link-hover-color-rgb: 204, 51, 149;
|
--bs-link-hover-color-rgb: 204, 51, 149;
|
||||||
--bs-code-color: rgb(255, 64, 186);
|
--bs-code-color: rgb(255, 64, 186);
|
||||||
--bs-highlight-color: #ebebeb;
|
--bs-highlight-color: #ebebeb;
|
||||||
|
@ -142,42 +142,42 @@
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #292929;
|
--bs-tertiary-bg: #292929;
|
||||||
--bs-tertiary-bg-rgb: 41, 41, 41;
|
--bs-tertiary-bg-rgb: 41, 41, 41;
|
||||||
--bs-primary-text-emphasis: #ff8cd6;
|
--bs-primary-text-emphasis: rgb(255, 140.4, 213.6);
|
||||||
--bs-secondary-text-emphasis: #67e1fe;
|
--bs-secondary-text-emphasis: rgb(102.6, 225, 254.4);
|
||||||
--bs-success-text-emphasis: #69ffc7;
|
--bs-success-text-emphasis: rgb(105, 255, 198.6);
|
||||||
--bs-info-text-emphasis: #67e1fe;
|
--bs-info-text-emphasis: rgb(102.6, 225, 254.4);
|
||||||
--bs-warning-text-emphasis: #fffdc0;
|
--bs-warning-text-emphasis: rgb(255, 252.6, 192);
|
||||||
--bs-danger-text-emphasis: #ff9fa8;
|
--bs-danger-text-emphasis: #ff9fa8;
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #330d25;
|
--bs-primary-bg-subtle: rgb(51, 12.8, 37.2);
|
||||||
--bs-secondary-bg-subtle: #002933;
|
--bs-secondary-bg-subtle: rgb(0.2, 41, 50.8);
|
||||||
--bs-success-bg-subtle: #013320;
|
--bs-success-bg-subtle: rgb(1, 51, 32.2);
|
||||||
--bs-info-bg-subtle: #002933;
|
--bs-info-bg-subtle: rgb(0.2, 41, 50.8);
|
||||||
--bs-warning-bg-subtle: #33321e;
|
--bs-warning-bg-subtle: rgb(51, 50.2, 30);
|
||||||
--bs-danger-bg-subtle: #331316;
|
--bs-danger-bg-subtle: #331316;
|
||||||
--bs-light-bg-subtle: #303030;
|
--bs-light-bg-subtle: #303030;
|
||||||
--bs-dark-bg-subtle: #181818;
|
--bs-dark-bg-subtle: #181818;
|
||||||
--bs-primary-border-subtle: #992670;
|
--bs-primary-border-subtle: rgb(153, 38.4, 111.6);
|
||||||
--bs-secondary-border-subtle: #017b98;
|
--bs-secondary-border-subtle: rgb(0.6, 123, 152.4);
|
||||||
--bs-success-border-subtle: #039961;
|
--bs-success-border-subtle: rgb(3, 153, 96.6);
|
||||||
--bs-info-border-subtle: #017b98;
|
--bs-info-border-subtle: rgb(0.6, 123, 152.4);
|
||||||
--bs-warning-border-subtle: #99975a;
|
--bs-warning-border-subtle: rgb(153, 150.6, 90);
|
||||||
--bs-danger-border-subtle: #993942;
|
--bs-danger-border-subtle: #993942;
|
||||||
--bs-light-border-subtle: #444;
|
--bs-light-border-subtle: #444;
|
||||||
--bs-dark-border-subtle: #303030;
|
--bs-dark-border-subtle: #303030;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #ff8cd6;
|
--bs-link-color: rgb(255, 140.4, 213.6);
|
||||||
--bs-link-hover-color: #ffa3de;
|
--bs-link-hover-color: rgb(255, 163.32, 221.88);
|
||||||
--bs-link-color-rgb: 255, 140, 214;
|
--bs-link-color-rgb: 255, 140, 214;
|
||||||
--bs-link-hover-color-rgb: 255, 163, 222;
|
--bs-link-hover-color-rgb: 255, 163, 222;
|
||||||
--bs-code-color: #ff8cd6;
|
--bs-code-color: rgb(255, 140.4, 213.6);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #888;
|
--bs-highlight-bg: #888;
|
||||||
--bs-border-color: #444;
|
--bs-border-color: #444;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #69ffc7;
|
--bs-form-valid-color: rgb(105, 255, 198.6);
|
||||||
--bs-form-valid-border-color: #69ffc7;
|
--bs-form-valid-border-color: rgb(105, 255, 198.6);
|
||||||
--bs-form-invalid-color: #ff9fa8;
|
--bs-form-invalid-color: #ff9fa8;
|
||||||
--bs-form-invalid-border-color: #ff9fa8;
|
--bs-form-invalid-border-color: #ff9fa8;
|
||||||
}
|
}
|
||||||
|
@ -1936,13 +1936,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ffd9f1;
|
--bs-table-bg: rgb(255, 216.8, 241.2);
|
||||||
--bs-table-border-color: #ccaec1;
|
--bs-table-border-color: rgb(204, 173.44, 192.96);
|
||||||
--bs-table-striped-bg: #f2cee5;
|
--bs-table-striped-bg: rgb(242.25, 205.96, 229.14);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e6c3d9;
|
--bs-table-active-bg: rgb(229.5, 195.12, 217.08);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ecc9df;
|
--bs-table-hover-bg: rgb(235.875, 200.54, 223.11);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1950,13 +1950,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf5ff;
|
--bs-table-bg: rgb(204.2, 245, 254.8);
|
||||||
--bs-table-border-color: #a3c4cc;
|
--bs-table-border-color: rgb(163.36, 196, 203.84);
|
||||||
--bs-table-striped-bg: #c2e9f2;
|
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dde6;
|
--bs-table-active-bg: rgb(183.78, 220.5, 229.32);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde3ec;
|
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1964,13 +1964,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #cdffec;
|
--bs-table-bg: rgb(205, 255, 236.2);
|
||||||
--bs-table-border-color: #a4ccbd;
|
--bs-table-border-color: rgb(164, 204, 188.96);
|
||||||
--bs-table-striped-bg: #c3f2e0;
|
--bs-table-striped-bg: rgb(194.75, 242.25, 224.39);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b9e6d4;
|
--bs-table-active-bg: rgb(184.5, 229.5, 212.58);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #beecda;
|
--bs-table-hover-bg: rgb(189.625, 235.875, 218.485);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1978,13 +1978,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf5ff;
|
--bs-table-bg: rgb(204.2, 245, 254.8);
|
||||||
--bs-table-border-color: #a3c4cc;
|
--bs-table-border-color: rgb(163.36, 196, 203.84);
|
||||||
--bs-table-striped-bg: #c2e9f2;
|
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dde6;
|
--bs-table-active-bg: rgb(183.78, 220.5, 229.32);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde3ec;
|
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1992,13 +1992,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fffeea;
|
--bs-table-bg: rgb(255, 254.2, 234);
|
||||||
--bs-table-border-color: #cccbbb;
|
--bs-table-border-color: rgb(204, 203.36, 187.2);
|
||||||
--bs-table-striped-bg: #f2f1de;
|
--bs-table-striped-bg: rgb(242.25, 241.49, 222.3);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e6e5d3;
|
--bs-table-active-bg: rgb(229.5, 228.78, 210.6);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ecebd8;
|
--bs-table-hover-bg: rgb(235.875, 235.135, 216.45);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2007,12 +2007,12 @@ progress {
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ffdfe2;
|
--bs-table-bg: #ffdfe2;
|
||||||
--bs-table-border-color: #ccb2b5;
|
--bs-table-border-color: rgb(204, 178.4, 180.8);
|
||||||
--bs-table-striped-bg: #f2d4d7;
|
--bs-table-striped-bg: rgb(242.25, 211.85, 214.7);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e6c9cb;
|
--bs-table-active-bg: rgb(229.5, 200.7, 203.4);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ecced1;
|
--bs-table-hover-bg: rgb(235.875, 206.275, 209.05);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2021,12 +2021,12 @@ progress {
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #444;
|
--bs-table-bg: #444;
|
||||||
--bs-table-border-color: dimgray;
|
--bs-table-border-color: rgb(105.4, 105.4, 105.4);
|
||||||
--bs-table-striped-bg: #4d4d4d;
|
--bs-table-striped-bg: rgb(77.35, 77.35, 77.35);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #575757;
|
--bs-table-active-bg: rgb(86.7, 86.7, 86.7);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #525252;
|
--bs-table-hover-bg: rgb(82.025, 82.025, 82.025);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2036,11 +2036,11 @@ progress {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ebebeb;
|
--bs-table-bg: #ebebeb;
|
||||||
--bs-table-border-color: #bcbcbc;
|
--bs-table-border-color: #bcbcbc;
|
||||||
--bs-table-striped-bg: #dfdfdf;
|
--bs-table-striped-bg: rgb(223.25, 223.25, 223.25);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #d4d4d4;
|
--bs-table-active-bg: rgb(211.5, 211.5, 211.5);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #d9d9d9;
|
--bs-table-hover-bg: rgb(217.375, 217.375, 217.375);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2141,7 +2141,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #888;
|
background-color: #888;
|
||||||
border-color: #ffa0dd;
|
border-color: rgb(255, 159.5, 220.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2288,7 +2288,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #ffa0dd;
|
border-color: rgb(255, 159.5, 220.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2372,7 +2372,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #ffa0dd;
|
border-color: rgb(255, 159.5, 220.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2419,7 +2419,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffa0dd'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28255, 159.5, 220.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2491,7 +2491,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #ffc6ea;
|
background-color: rgb(255, 197.7, 234.3);
|
||||||
background-image: var(--bs-gradient);
|
background-image: var(--bs-gradient);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
|
@ -2521,7 +2521,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #ffc6ea;
|
background-color: rgb(255, 197.7, 234.3);
|
||||||
background-image: var(--bs-gradient);
|
background-image: var(--bs-gradient);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
|
@ -2763,7 +2763,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-control:valid:focus, .form-control.is-valid:focus {
|
.was-validated .form-control:valid:focus, .form-control.is-valid:focus {
|
||||||
border-color: var(--bs-form-valid-border-color);
|
border-color: var(--bs-form-valid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated textarea.form-control:valid, textarea.form-control.is-valid {
|
.was-validated textarea.form-control:valid, textarea.form-control.is-valid {
|
||||||
|
@ -2782,7 +2782,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-select:valid:focus, .form-select.is-valid:focus {
|
.was-validated .form-select:valid:focus, .form-select.is-valid:focus {
|
||||||
border-color: var(--bs-form-valid-border-color);
|
border-color: var(--bs-form-valid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated .form-control-color:valid, .form-control-color.is-valid {
|
.was-validated .form-control-color:valid, .form-control-color.is-valid {
|
||||||
|
@ -2853,7 +2853,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {
|
.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
|
.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
|
||||||
|
@ -2872,7 +2872,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus {
|
.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated .form-control-color:invalid, .form-control-color.is-invalid {
|
.was-validated .form-control-color:invalid, .form-control-color.is-invalid {
|
||||||
|
@ -2976,6 +2976,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2991,12 +2994,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: rgb(255, 64, 186);
|
--bs-btn-bg: rgb(255, 64, 186);
|
||||||
--bs-btn-border-color: rgb(255, 64, 186);
|
--bs-btn-border-color: rgb(255, 64, 186);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #d9369e;
|
--bs-btn-hover-bg: rgb(216.75, 54.4, 158.1);
|
||||||
--bs-btn-hover-border-color: #cc3395;
|
--bs-btn-hover-border-color: rgb(204, 51.2, 148.8);
|
||||||
--bs-btn-focus-shadow-rgb: 255, 93, 196;
|
--bs-btn-focus-shadow-rgb: 255, 93, 196;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #cc3395;
|
--bs-btn-active-bg: rgb(204, 51.2, 148.8);
|
||||||
--bs-btn-active-border-color: #bf308c;
|
--bs-btn-active-border-color: rgb(191.25, 48, 139.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: rgb(255, 64, 186);
|
--bs-btn-disabled-bg: rgb(255, 64, 186);
|
||||||
|
@ -3008,12 +3011,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #01cdfe;
|
--bs-btn-bg: #01cdfe;
|
||||||
--bs-btn-border-color: #01cdfe;
|
--bs-btn-border-color: #01cdfe;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #27d5fe;
|
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
|
||||||
--bs-btn-hover-border-color: #1ad2fe;
|
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #34d7fe;
|
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
|
||||||
--bs-btn-active-border-color: #1ad2fe;
|
--bs-btn-active-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #01cdfe;
|
--bs-btn-disabled-bg: #01cdfe;
|
||||||
|
@ -3025,12 +3028,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #05ffa1;
|
--bs-btn-bg: #05ffa1;
|
||||||
--bs-btn-border-color: #05ffa1;
|
--bs-btn-border-color: #05ffa1;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #2bffaf;
|
--bs-btn-hover-bg: rgb(42.5, 255, 175.1);
|
||||||
--bs-btn-hover-border-color: #1effaa;
|
--bs-btn-hover-border-color: rgb(30, 255, 170.4);
|
||||||
--bs-btn-focus-shadow-rgb: 4, 217, 137;
|
--bs-btn-focus-shadow-rgb: 4, 217, 137;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #37ffb4;
|
--bs-btn-active-bg: rgb(55, 255, 179.8);
|
||||||
--bs-btn-active-border-color: #1effaa;
|
--bs-btn-active-border-color: rgb(30, 255, 170.4);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #05ffa1;
|
--bs-btn-disabled-bg: #05ffa1;
|
||||||
|
@ -3042,12 +3045,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #01cdfe;
|
--bs-btn-bg: #01cdfe;
|
||||||
--bs-btn-border-color: #01cdfe;
|
--bs-btn-border-color: #01cdfe;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #27d5fe;
|
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
|
||||||
--bs-btn-hover-border-color: #1ad2fe;
|
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #34d7fe;
|
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
|
||||||
--bs-btn-active-border-color: #1ad2fe;
|
--bs-btn-active-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #01cdfe;
|
--bs-btn-disabled-bg: #01cdfe;
|
||||||
|
@ -3059,12 +3062,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #fffb96;
|
--bs-btn-bg: #fffb96;
|
||||||
--bs-btn-border-color: #fffb96;
|
--bs-btn-border-color: #fffb96;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #fffca6;
|
--bs-btn-hover-bg: rgb(255, 251.6, 165.75);
|
||||||
--bs-btn-hover-border-color: #fffba1;
|
--bs-btn-hover-border-color: rgb(255, 251.4, 160.5);
|
||||||
--bs-btn-focus-shadow-rgb: 217, 213, 128;
|
--bs-btn-focus-shadow-rgb: 217, 213, 128;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #fffcab;
|
--bs-btn-active-bg: rgb(255, 251.8, 171);
|
||||||
--bs-btn-active-border-color: #fffba1;
|
--bs-btn-active-border-color: rgb(255, 251.4, 160.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #fffb96;
|
--bs-btn-disabled-bg: #fffb96;
|
||||||
|
@ -3076,12 +3079,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: rgb(255, 95, 110);
|
--bs-btn-bg: rgb(255, 95, 110);
|
||||||
--bs-btn-border-color: rgb(255, 95, 110);
|
--bs-btn-border-color: rgb(255, 95, 110);
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #ff7784;
|
--bs-btn-hover-bg: rgb(255, 119, 131.75);
|
||||||
--bs-btn-hover-border-color: #ff6f7d;
|
--bs-btn-hover-border-color: rgb(255, 111, 124.5);
|
||||||
--bs-btn-focus-shadow-rgb: 217, 81, 94;
|
--bs-btn-focus-shadow-rgb: 217, 81, 94;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #ff7f8b;
|
--bs-btn-active-bg: #ff7f8b;
|
||||||
--bs-btn-active-border-color: #ff6f7d;
|
--bs-btn-active-border-color: rgb(255, 111, 124.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: rgb(255, 95, 110);
|
--bs-btn-disabled-bg: rgb(255, 95, 110);
|
||||||
|
@ -3093,11 +3096,11 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #444;
|
--bs-btn-bg: #444;
|
||||||
--bs-btn-border-color: #444;
|
--bs-btn-border-color: #444;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #3a3a3a;
|
--bs-btn-hover-bg: rgb(57.8, 57.8, 57.8);
|
||||||
--bs-btn-hover-border-color: #363636;
|
--bs-btn-hover-border-color: rgb(54.4, 54.4, 54.4);
|
||||||
--bs-btn-focus-shadow-rgb: 96, 96, 96;
|
--bs-btn-focus-shadow-rgb: 96, 96, 96;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #363636;
|
--bs-btn-active-bg: rgb(54.4, 54.4, 54.4);
|
||||||
--bs-btn-active-border-color: #333333;
|
--bs-btn-active-border-color: #333333;
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
|
@ -4527,12 +4530,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ebebeb'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ebebeb' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23661a4a'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%28102, 25.6, 74.4%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #ffa0dd;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4590,7 +4592,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4608,7 +4609,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4619,11 +4620,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4632,27 +4633,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -5530,7 +5531,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6098,20 +6098,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6737,14 +6729,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/*!
|
/*!
|
||||||
* Bootstrap v5.3.2 (https://getbootstrap.com/)
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||||
* Copyright 2011-2023 The Bootstrap Authors
|
* Copyright 2011-2024 The Bootstrap Authors
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
*/
|
*/
|
||||||
:root,
|
:root,
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
--bs-info: #01cdfe;
|
--bs-info: #01cdfe;
|
||||||
--bs-warning: #fffb96;
|
--bs-warning: #fffb96;
|
||||||
--bs-danger: rgb(255, 95, 110);
|
--bs-danger: rgb(255, 95, 110);
|
||||||
--bs-light: #dadee3;
|
--bs-light: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-dark: #212529;
|
--bs-dark: #212529;
|
||||||
--bs-primary-rgb: 255, 64, 186;
|
--bs-primary-rgb: 255, 64, 186;
|
||||||
--bs-secondary-rgb: 1, 205, 254;
|
--bs-secondary-rgb: 1, 205, 254;
|
||||||
|
@ -45,27 +45,27 @@
|
||||||
--bs-danger-rgb: 255, 95, 110;
|
--bs-danger-rgb: 255, 95, 110;
|
||||||
--bs-light-rgb: 218, 222, 227;
|
--bs-light-rgb: 218, 222, 227;
|
||||||
--bs-dark-rgb: 33, 37, 41;
|
--bs-dark-rgb: 33, 37, 41;
|
||||||
--bs-primary-text-emphasis: #661a4a;
|
--bs-primary-text-emphasis: rgb(102, 25.6, 74.4);
|
||||||
--bs-secondary-text-emphasis: #005266;
|
--bs-secondary-text-emphasis: rgb(0.4, 82, 101.6);
|
||||||
--bs-success-text-emphasis: #026640;
|
--bs-success-text-emphasis: rgb(2, 102, 64.4);
|
||||||
--bs-info-text-emphasis: #005266;
|
--bs-info-text-emphasis: rgb(0.4, 82, 101.6);
|
||||||
--bs-warning-text-emphasis: #66643c;
|
--bs-warning-text-emphasis: rgb(102, 100.4, 60);
|
||||||
--bs-danger-text-emphasis: #66262c;
|
--bs-danger-text-emphasis: #66262c;
|
||||||
--bs-light-text-emphasis: #495057;
|
--bs-light-text-emphasis: #495057;
|
||||||
--bs-dark-text-emphasis: #495057;
|
--bs-dark-text-emphasis: #495057;
|
||||||
--bs-primary-bg-subtle: #ffd9f1;
|
--bs-primary-bg-subtle: rgb(255, 216.8, 241.2);
|
||||||
--bs-secondary-bg-subtle: #ccf5ff;
|
--bs-secondary-bg-subtle: rgb(204.2, 245, 254.8);
|
||||||
--bs-success-bg-subtle: #cdffec;
|
--bs-success-bg-subtle: rgb(205, 255, 236.2);
|
||||||
--bs-info-bg-subtle: #ccf5ff;
|
--bs-info-bg-subtle: rgb(204.2, 245, 254.8);
|
||||||
--bs-warning-bg-subtle: #fffeea;
|
--bs-warning-bg-subtle: rgb(255, 254.2, 234);
|
||||||
--bs-danger-bg-subtle: #ffdfe2;
|
--bs-danger-bg-subtle: #ffdfe2;
|
||||||
--bs-light-bg-subtle: #fcfcfd;
|
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
|
||||||
--bs-dark-bg-subtle: #ced4da;
|
--bs-dark-bg-subtle: #ced4da;
|
||||||
--bs-primary-border-subtle: #ffb3e3;
|
--bs-primary-border-subtle: rgb(255, 178.6, 227.4);
|
||||||
--bs-secondary-border-subtle: #99ebff;
|
--bs-secondary-border-subtle: rgb(153.4, 235, 254.6);
|
||||||
--bs-success-border-subtle: #9bffd9;
|
--bs-success-border-subtle: rgb(155, 255, 217.4);
|
||||||
--bs-info-border-subtle: #99ebff;
|
--bs-info-border-subtle: rgb(153.4, 235, 254.6);
|
||||||
--bs-warning-border-subtle: #fffdd5;
|
--bs-warning-border-subtle: rgb(255, 253.4, 213);
|
||||||
--bs-danger-border-subtle: #ffbfc5;
|
--bs-danger-border-subtle: #ffbfc5;
|
||||||
--bs-light-border-subtle: #e9ecef;
|
--bs-light-border-subtle: #e9ecef;
|
||||||
--bs-dark-border-subtle: #adb5bd;
|
--bs-dark-border-subtle: #adb5bd;
|
||||||
|
@ -97,11 +97,11 @@
|
||||||
--bs-link-color: rgb(255, 64, 186);
|
--bs-link-color: rgb(255, 64, 186);
|
||||||
--bs-link-color-rgb: 255, 64, 186;
|
--bs-link-color-rgb: 255, 64, 186;
|
||||||
--bs-link-decoration: none;
|
--bs-link-decoration: none;
|
||||||
--bs-link-hover-color: #cc3395;
|
--bs-link-hover-color: rgb(204, 51.2, 148.8);
|
||||||
--bs-link-hover-color-rgb: 204, 51, 149;
|
--bs-link-hover-color-rgb: 204, 51, 149;
|
||||||
--bs-code-color: rgb(255, 64, 186);
|
--bs-code-color: rgb(255, 64, 186);
|
||||||
--bs-highlight-color: #495057;
|
--bs-highlight-color: #495057;
|
||||||
--bs-highlight-bg: #fffeea;
|
--bs-highlight-bg: rgb(255, 254.2, 234);
|
||||||
--bs-border-width: 1px;
|
--bs-border-width: 1px;
|
||||||
--bs-border-style: solid;
|
--bs-border-style: solid;
|
||||||
--bs-border-color: #dee2e6;
|
--bs-border-color: #dee2e6;
|
||||||
|
@ -140,44 +140,44 @@
|
||||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||||
--bs-tertiary-bg: #2b3035;
|
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5);
|
||||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||||
--bs-primary-text-emphasis: #ff8cd6;
|
--bs-primary-text-emphasis: rgb(255, 140.4, 213.6);
|
||||||
--bs-secondary-text-emphasis: #67e1fe;
|
--bs-secondary-text-emphasis: rgb(102.6, 225, 254.4);
|
||||||
--bs-success-text-emphasis: #69ffc7;
|
--bs-success-text-emphasis: rgb(105, 255, 198.6);
|
||||||
--bs-info-text-emphasis: #67e1fe;
|
--bs-info-text-emphasis: rgb(102.6, 225, 254.4);
|
||||||
--bs-warning-text-emphasis: #fffdc0;
|
--bs-warning-text-emphasis: rgb(255, 252.6, 192);
|
||||||
--bs-danger-text-emphasis: #ff9fa8;
|
--bs-danger-text-emphasis: #ff9fa8;
|
||||||
--bs-light-text-emphasis: #f8f9fa;
|
--bs-light-text-emphasis: #f8f9fa;
|
||||||
--bs-dark-text-emphasis: #dee2e6;
|
--bs-dark-text-emphasis: #dee2e6;
|
||||||
--bs-primary-bg-subtle: #330d25;
|
--bs-primary-bg-subtle: rgb(51, 12.8, 37.2);
|
||||||
--bs-secondary-bg-subtle: #002933;
|
--bs-secondary-bg-subtle: rgb(0.2, 41, 50.8);
|
||||||
--bs-success-bg-subtle: #013320;
|
--bs-success-bg-subtle: rgb(1, 51, 32.2);
|
||||||
--bs-info-bg-subtle: #002933;
|
--bs-info-bg-subtle: rgb(0.2, 41, 50.8);
|
||||||
--bs-warning-bg-subtle: #33321e;
|
--bs-warning-bg-subtle: rgb(51, 50.2, 30);
|
||||||
--bs-danger-bg-subtle: #331316;
|
--bs-danger-bg-subtle: #331316;
|
||||||
--bs-light-bg-subtle: #343a40;
|
--bs-light-bg-subtle: #343a40;
|
||||||
--bs-dark-bg-subtle: #1a1d20;
|
--bs-dark-bg-subtle: #1a1d20;
|
||||||
--bs-primary-border-subtle: #992670;
|
--bs-primary-border-subtle: rgb(153, 38.4, 111.6);
|
||||||
--bs-secondary-border-subtle: #017b98;
|
--bs-secondary-border-subtle: rgb(0.6, 123, 152.4);
|
||||||
--bs-success-border-subtle: #039961;
|
--bs-success-border-subtle: rgb(3, 153, 96.6);
|
||||||
--bs-info-border-subtle: #017b98;
|
--bs-info-border-subtle: rgb(0.6, 123, 152.4);
|
||||||
--bs-warning-border-subtle: #99975a;
|
--bs-warning-border-subtle: rgb(153, 150.6, 90);
|
||||||
--bs-danger-border-subtle: #993942;
|
--bs-danger-border-subtle: #993942;
|
||||||
--bs-light-border-subtle: #495057;
|
--bs-light-border-subtle: #495057;
|
||||||
--bs-dark-border-subtle: #343a40;
|
--bs-dark-border-subtle: #343a40;
|
||||||
--bs-heading-color: inherit;
|
--bs-heading-color: inherit;
|
||||||
--bs-link-color: #ff8cd6;
|
--bs-link-color: rgb(255, 140.4, 213.6);
|
||||||
--bs-link-hover-color: #ffa3de;
|
--bs-link-hover-color: rgb(255, 163.32, 221.88);
|
||||||
--bs-link-color-rgb: 255, 140, 214;
|
--bs-link-color-rgb: 255, 140, 214;
|
||||||
--bs-link-hover-color-rgb: 255, 163, 222;
|
--bs-link-hover-color-rgb: 255, 163, 222;
|
||||||
--bs-code-color: #ff8cd6;
|
--bs-code-color: rgb(255, 140.4, 213.6);
|
||||||
--bs-highlight-color: #dee2e6;
|
--bs-highlight-color: #dee2e6;
|
||||||
--bs-highlight-bg: #66643c;
|
--bs-highlight-bg: rgb(102, 100.4, 60);
|
||||||
--bs-border-color: #495057;
|
--bs-border-color: #495057;
|
||||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||||
--bs-form-valid-color: #69ffc7;
|
--bs-form-valid-color: rgb(105, 255, 198.6);
|
||||||
--bs-form-valid-border-color: #69ffc7;
|
--bs-form-valid-border-color: rgb(105, 255, 198.6);
|
||||||
--bs-form-invalid-color: #ff9fa8;
|
--bs-form-invalid-color: #ff9fa8;
|
||||||
--bs-form-invalid-border-color: #ff9fa8;
|
--bs-form-invalid-border-color: #ff9fa8;
|
||||||
}
|
}
|
||||||
|
@ -1935,13 +1935,13 @@ progress {
|
||||||
|
|
||||||
.table-primary {
|
.table-primary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ffd9f1;
|
--bs-table-bg: rgb(255, 216.8, 241.2);
|
||||||
--bs-table-border-color: #ccaec1;
|
--bs-table-border-color: rgb(204, 173.44, 192.96);
|
||||||
--bs-table-striped-bg: #f2cee5;
|
--bs-table-striped-bg: rgb(242.25, 205.96, 229.14);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e6c3d9;
|
--bs-table-active-bg: rgb(229.5, 195.12, 217.08);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ecc9df;
|
--bs-table-hover-bg: rgb(235.875, 200.54, 223.11);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1949,13 +1949,13 @@ progress {
|
||||||
|
|
||||||
.table-secondary {
|
.table-secondary {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf5ff;
|
--bs-table-bg: rgb(204.2, 245, 254.8);
|
||||||
--bs-table-border-color: #a3c4cc;
|
--bs-table-border-color: rgb(163.36, 196, 203.84);
|
||||||
--bs-table-striped-bg: #c2e9f2;
|
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dde6;
|
--bs-table-active-bg: rgb(183.78, 220.5, 229.32);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde3ec;
|
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1963,13 +1963,13 @@ progress {
|
||||||
|
|
||||||
.table-success {
|
.table-success {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #cdffec;
|
--bs-table-bg: rgb(205, 255, 236.2);
|
||||||
--bs-table-border-color: #a4ccbd;
|
--bs-table-border-color: rgb(164, 204, 188.96);
|
||||||
--bs-table-striped-bg: #c3f2e0;
|
--bs-table-striped-bg: rgb(194.75, 242.25, 224.39);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b9e6d4;
|
--bs-table-active-bg: rgb(184.5, 229.5, 212.58);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #beecda;
|
--bs-table-hover-bg: rgb(189.625, 235.875, 218.485);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1977,13 +1977,13 @@ progress {
|
||||||
|
|
||||||
.table-info {
|
.table-info {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ccf5ff;
|
--bs-table-bg: rgb(204.2, 245, 254.8);
|
||||||
--bs-table-border-color: #a3c4cc;
|
--bs-table-border-color: rgb(163.36, 196, 203.84);
|
||||||
--bs-table-striped-bg: #c2e9f2;
|
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #b8dde6;
|
--bs-table-active-bg: rgb(183.78, 220.5, 229.32);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #bde3ec;
|
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -1991,13 +1991,13 @@ progress {
|
||||||
|
|
||||||
.table-warning {
|
.table-warning {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #fffeea;
|
--bs-table-bg: rgb(255, 254.2, 234);
|
||||||
--bs-table-border-color: #cccbbb;
|
--bs-table-border-color: rgb(204, 203.36, 187.2);
|
||||||
--bs-table-striped-bg: #f2f1de;
|
--bs-table-striped-bg: rgb(242.25, 241.49, 222.3);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e6e5d3;
|
--bs-table-active-bg: rgb(229.5, 228.78, 210.6);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ecebd8;
|
--bs-table-hover-bg: rgb(235.875, 235.135, 216.45);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2006,12 +2006,12 @@ progress {
|
||||||
.table-danger {
|
.table-danger {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #ffdfe2;
|
--bs-table-bg: #ffdfe2;
|
||||||
--bs-table-border-color: #ccb2b5;
|
--bs-table-border-color: rgb(204, 178.4, 180.8);
|
||||||
--bs-table-striped-bg: #f2d4d7;
|
--bs-table-striped-bg: rgb(242.25, 211.85, 214.7);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #e6c9cb;
|
--bs-table-active-bg: rgb(229.5, 200.7, 203.4);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #ecced1;
|
--bs-table-hover-bg: rgb(235.875, 206.275, 209.05);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2019,13 +2019,13 @@ progress {
|
||||||
|
|
||||||
.table-light {
|
.table-light {
|
||||||
--bs-table-color: #000;
|
--bs-table-color: #000;
|
||||||
--bs-table-bg: #dadee3;
|
--bs-table-bg: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-table-border-color: #aeb2b6;
|
--bs-table-border-color: rgb(174.1179310345, 177.74, 181.3620689655);
|
||||||
--bs-table-striped-bg: #cfd3d8;
|
--bs-table-striped-bg: rgb(206.7650431034, 211.06625, 215.3674568966);
|
||||||
--bs-table-striped-color: #000;
|
--bs-table-striped-color: #000;
|
||||||
--bs-table-active-bg: #c4c8cc;
|
--bs-table-active-bg: rgb(195.8826724138, 199.9575, 204.0323275862);
|
||||||
--bs-table-active-color: #000;
|
--bs-table-active-color: #000;
|
||||||
--bs-table-hover-bg: #cacdd2;
|
--bs-table-hover-bg: rgb(201.3238577586, 205.511875, 209.6998922414);
|
||||||
--bs-table-hover-color: #000;
|
--bs-table-hover-color: #000;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2034,12 +2034,12 @@ progress {
|
||||||
.table-dark {
|
.table-dark {
|
||||||
--bs-table-color: #fff;
|
--bs-table-color: #fff;
|
||||||
--bs-table-bg: #212529;
|
--bs-table-bg: #212529;
|
||||||
--bs-table-border-color: #4d5154;
|
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-table-striped-bg: #2c3034;
|
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
|
||||||
--bs-table-striped-color: #fff;
|
--bs-table-striped-color: #fff;
|
||||||
--bs-table-active-bg: #373b3e;
|
--bs-table-active-bg: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-table-active-color: #fff;
|
--bs-table-active-color: #fff;
|
||||||
--bs-table-hover-bg: #323539;
|
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
|
||||||
--bs-table-hover-color: #fff;
|
--bs-table-hover-color: #fff;
|
||||||
color: var(--bs-table-color);
|
color: var(--bs-table-color);
|
||||||
border-color: var(--bs-table-border-color);
|
border-color: var(--bs-table-border-color);
|
||||||
|
@ -2140,7 +2140,7 @@ progress {
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
color: var(--bs-body-color);
|
color: var(--bs-body-color);
|
||||||
background-color: var(--bs-body-bg);
|
background-color: var(--bs-body-bg);
|
||||||
border-color: #ffa0dd;
|
border-color: rgb(255, 159.5, 220.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2287,7 +2287,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-select:focus {
|
.form-select:focus {
|
||||||
border-color: #ffa0dd;
|
border-color: rgb(255, 159.5, 220.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2371,7 +2371,7 @@ textarea.form-control-lg {
|
||||||
filter: brightness(90%);
|
filter: brightness(90%);
|
||||||
}
|
}
|
||||||
.form-check-input:focus {
|
.form-check-input:focus {
|
||||||
border-color: #ffa0dd;
|
border-color: rgb(255, 159.5, 220.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
}
|
}
|
||||||
|
@ -2418,7 +2418,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:focus {
|
.form-switch .form-check-input:focus {
|
||||||
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffa0dd'/%3e%3c/svg%3e");
|
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28255, 159.5, 220.5%29'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
.form-switch .form-check-input:checked {
|
.form-switch .form-check-input:checked {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
|
@ -2490,7 +2490,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-thumb:active {
|
.form-range::-webkit-slider-thumb:active {
|
||||||
background-color: #ffc6ea;
|
background-color: rgb(255, 197.7, 234.3);
|
||||||
background-image: var(--bs-gradient);
|
background-image: var(--bs-gradient);
|
||||||
}
|
}
|
||||||
.form-range::-webkit-slider-runnable-track {
|
.form-range::-webkit-slider-runnable-track {
|
||||||
|
@ -2520,7 +2520,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-thumb:active {
|
.form-range::-moz-range-thumb:active {
|
||||||
background-color: #ffc6ea;
|
background-color: rgb(255, 197.7, 234.3);
|
||||||
background-image: var(--bs-gradient);
|
background-image: var(--bs-gradient);
|
||||||
}
|
}
|
||||||
.form-range::-moz-range-track {
|
.form-range::-moz-range-track {
|
||||||
|
@ -2762,7 +2762,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-control:valid:focus, .form-control.is-valid:focus {
|
.was-validated .form-control:valid:focus, .form-control.is-valid:focus {
|
||||||
border-color: var(--bs-form-valid-border-color);
|
border-color: var(--bs-form-valid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated textarea.form-control:valid, textarea.form-control.is-valid {
|
.was-validated textarea.form-control:valid, textarea.form-control.is-valid {
|
||||||
|
@ -2781,7 +2781,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-select:valid:focus, .form-select.is-valid:focus {
|
.was-validated .form-select:valid:focus, .form-select.is-valid:focus {
|
||||||
border-color: var(--bs-form-valid-border-color);
|
border-color: var(--bs-form-valid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated .form-control-color:valid, .form-control-color.is-valid {
|
.was-validated .form-control-color:valid, .form-control-color.is-valid {
|
||||||
|
@ -2852,7 +2852,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {
|
.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
|
.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
|
||||||
|
@ -2871,7 +2871,7 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus {
|
.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus {
|
||||||
border-color: var(--bs-form-invalid-border-color);
|
border-color: var(--bs-form-invalid-border-color);
|
||||||
box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.was-validated .form-control-color:invalid, .form-control-color.is-invalid {
|
.was-validated .form-control-color:invalid, .form-control-color.is-invalid {
|
||||||
|
@ -2975,6 +2975,9 @@ textarea.form-control-lg {
|
||||||
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
|
||||||
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
|
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
.btn-check:checked:focus-visible + .btn {
|
||||||
|
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
|
||||||
|
}
|
||||||
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
|
||||||
color: var(--bs-btn-disabled-color);
|
color: var(--bs-btn-disabled-color);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -2990,12 +2993,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: rgb(255, 64, 186);
|
--bs-btn-bg: rgb(255, 64, 186);
|
||||||
--bs-btn-border-color: rgb(255, 64, 186);
|
--bs-btn-border-color: rgb(255, 64, 186);
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #d9369e;
|
--bs-btn-hover-bg: rgb(216.75, 54.4, 158.1);
|
||||||
--bs-btn-hover-border-color: #cc3395;
|
--bs-btn-hover-border-color: rgb(204, 51.2, 148.8);
|
||||||
--bs-btn-focus-shadow-rgb: 255, 93, 196;
|
--bs-btn-focus-shadow-rgb: 255, 93, 196;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #cc3395;
|
--bs-btn-active-bg: rgb(204, 51.2, 148.8);
|
||||||
--bs-btn-active-border-color: #bf308c;
|
--bs-btn-active-border-color: rgb(191.25, 48, 139.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: rgb(255, 64, 186);
|
--bs-btn-disabled-bg: rgb(255, 64, 186);
|
||||||
|
@ -3007,12 +3010,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #01cdfe;
|
--bs-btn-bg: #01cdfe;
|
||||||
--bs-btn-border-color: #01cdfe;
|
--bs-btn-border-color: #01cdfe;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #27d5fe;
|
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
|
||||||
--bs-btn-hover-border-color: #1ad2fe;
|
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #34d7fe;
|
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
|
||||||
--bs-btn-active-border-color: #1ad2fe;
|
--bs-btn-active-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #01cdfe;
|
--bs-btn-disabled-bg: #01cdfe;
|
||||||
|
@ -3024,12 +3027,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #05ffa1;
|
--bs-btn-bg: #05ffa1;
|
||||||
--bs-btn-border-color: #05ffa1;
|
--bs-btn-border-color: #05ffa1;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #2bffaf;
|
--bs-btn-hover-bg: rgb(42.5, 255, 175.1);
|
||||||
--bs-btn-hover-border-color: #1effaa;
|
--bs-btn-hover-border-color: rgb(30, 255, 170.4);
|
||||||
--bs-btn-focus-shadow-rgb: 4, 217, 137;
|
--bs-btn-focus-shadow-rgb: 4, 217, 137;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #37ffb4;
|
--bs-btn-active-bg: rgb(55, 255, 179.8);
|
||||||
--bs-btn-active-border-color: #1effaa;
|
--bs-btn-active-border-color: rgb(30, 255, 170.4);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #05ffa1;
|
--bs-btn-disabled-bg: #05ffa1;
|
||||||
|
@ -3041,12 +3044,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #01cdfe;
|
--bs-btn-bg: #01cdfe;
|
||||||
--bs-btn-border-color: #01cdfe;
|
--bs-btn-border-color: #01cdfe;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #27d5fe;
|
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
|
||||||
--bs-btn-hover-border-color: #1ad2fe;
|
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
--bs-btn-focus-shadow-rgb: 1, 174, 216;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #34d7fe;
|
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
|
||||||
--bs-btn-active-border-color: #1ad2fe;
|
--bs-btn-active-border-color: rgb(26.4, 210, 254.1);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #01cdfe;
|
--bs-btn-disabled-bg: #01cdfe;
|
||||||
|
@ -3058,12 +3061,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #fffb96;
|
--bs-btn-bg: #fffb96;
|
||||||
--bs-btn-border-color: #fffb96;
|
--bs-btn-border-color: #fffb96;
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #fffca6;
|
--bs-btn-hover-bg: rgb(255, 251.6, 165.75);
|
||||||
--bs-btn-hover-border-color: #fffba1;
|
--bs-btn-hover-border-color: rgb(255, 251.4, 160.5);
|
||||||
--bs-btn-focus-shadow-rgb: 217, 213, 128;
|
--bs-btn-focus-shadow-rgb: 217, 213, 128;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #fffcab;
|
--bs-btn-active-bg: rgb(255, 251.8, 171);
|
||||||
--bs-btn-active-border-color: #fffba1;
|
--bs-btn-active-border-color: rgb(255, 251.4, 160.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #fffb96;
|
--bs-btn-disabled-bg: #fffb96;
|
||||||
|
@ -3075,12 +3078,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: rgb(255, 95, 110);
|
--bs-btn-bg: rgb(255, 95, 110);
|
||||||
--bs-btn-border-color: rgb(255, 95, 110);
|
--bs-btn-border-color: rgb(255, 95, 110);
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #ff7784;
|
--bs-btn-hover-bg: rgb(255, 119, 131.75);
|
||||||
--bs-btn-hover-border-color: #ff6f7d;
|
--bs-btn-hover-border-color: rgb(255, 111, 124.5);
|
||||||
--bs-btn-focus-shadow-rgb: 217, 81, 94;
|
--bs-btn-focus-shadow-rgb: 217, 81, 94;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #ff7f8b;
|
--bs-btn-active-bg: #ff7f8b;
|
||||||
--bs-btn-active-border-color: #ff6f7d;
|
--bs-btn-active-border-color: rgb(255, 111, 124.5);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: rgb(255, 95, 110);
|
--bs-btn-disabled-bg: rgb(255, 95, 110);
|
||||||
|
@ -3089,19 +3092,19 @@ textarea.form-control-lg {
|
||||||
|
|
||||||
.btn-light {
|
.btn-light {
|
||||||
--bs-btn-color: #000;
|
--bs-btn-color: #000;
|
||||||
--bs-btn-bg: #dadee3;
|
--bs-btn-bg: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-border-color: #dadee3;
|
--bs-btn-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #b9bdc1;
|
--bs-btn-hover-bg: rgb(185.0003017241, 188.84875, 192.6971982759);
|
||||||
--bs-btn-hover-border-color: #aeb2b6;
|
--bs-btn-hover-border-color: rgb(174.1179310345, 177.74, 181.3620689655);
|
||||||
--bs-btn-focus-shadow-rgb: 185, 189, 193;
|
--bs-btn-focus-shadow-rgb: 185, 189, 193;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #aeb2b6;
|
--bs-btn-active-bg: rgb(174.1179310345, 177.74, 181.3620689655);
|
||||||
--bs-btn-active-border-color: #a4a7aa;
|
--bs-btn-active-border-color: rgb(163.2355603448, 166.63125, 170.0269396552);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #000;
|
--bs-btn-disabled-color: #000;
|
||||||
--bs-btn-disabled-bg: #dadee3;
|
--bs-btn-disabled-bg: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-disabled-border-color: #dadee3;
|
--bs-btn-disabled-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-dark {
|
.btn-dark {
|
||||||
|
@ -3109,12 +3112,12 @@ textarea.form-control-lg {
|
||||||
--bs-btn-bg: #212529;
|
--bs-btn-bg: #212529;
|
||||||
--bs-btn-border-color: #212529;
|
--bs-btn-border-color: #212529;
|
||||||
--bs-btn-hover-color: #fff;
|
--bs-btn-hover-color: #fff;
|
||||||
--bs-btn-hover-bg: #424649;
|
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
|
||||||
--bs-btn-hover-border-color: #373b3e;
|
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
||||||
--bs-btn-active-color: #fff;
|
--bs-btn-active-color: #fff;
|
||||||
--bs-btn-active-bg: #4d5154;
|
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
|
||||||
--bs-btn-active-border-color: #373b3e;
|
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #fff;
|
--bs-btn-disabled-color: #fff;
|
||||||
--bs-btn-disabled-bg: #212529;
|
--bs-btn-disabled-bg: #212529;
|
||||||
|
@ -3224,19 +3227,19 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-outline-light {
|
.btn-outline-light {
|
||||||
--bs-btn-color: #dadee3;
|
--bs-btn-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-border-color: #dadee3;
|
--bs-btn-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-hover-color: #000;
|
--bs-btn-hover-color: #000;
|
||||||
--bs-btn-hover-bg: #dadee3;
|
--bs-btn-hover-bg: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-hover-border-color: #dadee3;
|
--bs-btn-hover-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-focus-shadow-rgb: 218, 222, 227;
|
--bs-btn-focus-shadow-rgb: 218, 222, 227;
|
||||||
--bs-btn-active-color: #000;
|
--bs-btn-active-color: #000;
|
||||||
--bs-btn-active-bg: #dadee3;
|
--bs-btn-active-bg: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-active-border-color: #dadee3;
|
--bs-btn-active-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
--bs-btn-disabled-color: #dadee3;
|
--bs-btn-disabled-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-btn-disabled-bg: transparent;
|
--bs-btn-disabled-bg: transparent;
|
||||||
--bs-btn-disabled-border-color: #dadee3;
|
--bs-btn-disabled-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
|
||||||
--bs-gradient: none;
|
--bs-gradient: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4526,12 +4529,11 @@ textarea.form-control-lg {
|
||||||
--bs-accordion-btn-padding-y: 1rem;
|
--bs-accordion-btn-padding-y: 1rem;
|
||||||
--bs-accordion-btn-color: var(--bs-body-color);
|
--bs-accordion-btn-color: var(--bs-body-color);
|
||||||
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
--bs-accordion-btn-bg: var(--bs-accordion-bg);
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-icon-width: 1.25rem;
|
--bs-accordion-btn-icon-width: 1.25rem;
|
||||||
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
--bs-accordion-btn-icon-transform: rotate(-180deg);
|
||||||
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23661a4a'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%28102, 25.6, 74.4%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-focus-border-color: #ffa0dd;
|
|
||||||
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
|
||||||
--bs-accordion-body-padding-x: 1.25rem;
|
--bs-accordion-body-padding-x: 1.25rem;
|
||||||
--bs-accordion-body-padding-y: 1rem;
|
--bs-accordion-body-padding-y: 1rem;
|
||||||
|
@ -4589,7 +4591,6 @@ textarea.form-control-lg {
|
||||||
}
|
}
|
||||||
.accordion-button:focus {
|
.accordion-button:focus {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-color: var(--bs-accordion-btn-focus-border-color);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
box-shadow: var(--bs-accordion-btn-focus-box-shadow);
|
||||||
}
|
}
|
||||||
|
@ -4607,7 +4608,7 @@ textarea.form-control-lg {
|
||||||
border-top-left-radius: var(--bs-accordion-border-radius);
|
border-top-left-radius: var(--bs-accordion-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-border-radius);
|
border-top-right-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:first-of-type .accordion-button {
|
.accordion-item:first-of-type > .accordion-header .accordion-button {
|
||||||
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
border-top-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
border-top-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4618,11 +4619,11 @@ textarea.form-control-lg {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-button.collapsed {
|
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed {
|
||||||
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
|
||||||
}
|
}
|
||||||
.accordion-item:last-of-type .accordion-collapse {
|
.accordion-item:last-of-type > .accordion-collapse {
|
||||||
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
border-bottom-right-radius: var(--bs-accordion-border-radius);
|
||||||
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
border-bottom-left-radius: var(--bs-accordion-border-radius);
|
||||||
}
|
}
|
||||||
|
@ -4631,27 +4632,27 @@ textarea.form-control-lg {
|
||||||
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-flush .accordion-collapse {
|
.accordion-flush > .accordion-item {
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
.accordion-flush .accordion-item {
|
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:first-child {
|
.accordion-flush > .accordion-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item:last-child {
|
.accordion-flush > .accordion-item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
|
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.accordion-flush > .accordion-item > .accordion-collapse {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .accordion-button::after {
|
[data-bs-theme=dark] .accordion-button::after {
|
||||||
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
@ -5529,7 +5530,6 @@ textarea.form-control-lg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-modal-header-padding);
|
padding: var(--bs-modal-header-padding);
|
||||||
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
|
||||||
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
border-top-left-radius: var(--bs-modal-inner-border-radius);
|
||||||
|
@ -6097,20 +6097,12 @@ textarea.form-control-lg {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rtl:options: {
|
|
||||||
"autoRename": true,
|
|
||||||
"stringMap":[ {
|
|
||||||
"name" : "prev-next",
|
|
||||||
"search" : "prev",
|
|
||||||
"replace" : "next"
|
|
||||||
} ]
|
|
||||||
} */
|
|
||||||
.carousel-control-prev-icon {
|
.carousel-control-prev-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-control-next-icon {
|
.carousel-control-next-icon {
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-indicators {
|
.carousel-indicators {
|
||||||
|
@ -6736,14 +6728,11 @@ textarea.form-control-lg {
|
||||||
.offcanvas-header {
|
.offcanvas-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
|
||||||
}
|
}
|
||||||
.offcanvas-header .btn-close {
|
.offcanvas-header .btn-close {
|
||||||
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
|
||||||
margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto;
|
||||||
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
|
|
||||||
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.offcanvas-title {
|
.offcanvas-title {
|
||||||
|
@ -6907,8 +6896,8 @@ textarea.form-control-lg {
|
||||||
text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important;
|
text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important;
|
||||||
}
|
}
|
||||||
.link-light:hover, .link-light:focus {
|
.link-light:hover, .link-light:focus {
|
||||||
color: RGBA(225, 229, 233, var(--bs-link-opacity, 1)) !important;
|
color: RGBA(225, 229, 232, var(--bs-link-opacity, 1)) !important;
|
||||||
text-decoration-color: RGBA(225, 229, 233, var(--bs-link-underline-opacity, 1)) !important;
|
text-decoration-color: RGBA(225, 229, 232, var(--bs-link-underline-opacity, 1)) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-dark {
|
.link-dark {
|
||||||
|
|
|
@ -60,6 +60,10 @@
|
||||||
<symbol id="icon-add" viewBox="0 0 32 32" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
<symbol id="icon-add" viewBox="0 0 32 32" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
<path d="M14.5,14.501l-10.502,0c-0.828,0 -1.5,0.673 -1.5,1.5c0,0.828 0.672,1.5 1.5,1.5l10.502,0l-0.001,10.502c0,0.828 0.672,1.5 1.5,1.501c0.828,-0 1.5,-0.673 1.5,-1.5l0.001,-10.503l10.502,0c0.828,0 1.5,-0.672 1.5,-1.5c0,-0.827 -0.672,-1.5 -1.5,-1.5l-10.502,0l0.001,-10.501c-0,-0.828 -0.672,-1.501 -1.5,-1.501c-0.828,0 -1.5,0.672 -1.5,1.5l-0.001,10.502Z"/>
|
<path d="M14.5,14.501l-10.502,0c-0.828,0 -1.5,0.673 -1.5,1.5c0,0.828 0.672,1.5 1.5,1.5l10.502,0l-0.001,10.502c0,0.828 0.672,1.5 1.5,1.501c0.828,-0 1.5,-0.673 1.5,-1.5l0.001,-10.503l10.502,0c0.828,0 1.5,-0.672 1.5,-1.5c0,-0.827 -0.672,-1.5 -1.5,-1.5l-10.502,0l0.001,-10.501c-0,-0.828 -0.672,-1.501 -1.5,-1.501c-0.828,0 -1.5,0.672 -1.5,1.5l-0.001,10.502Z"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
<symbol id="icon-video" viewBox="0 0 256 256">
|
||||||
|
<rect width="256" height="256" fill="none"/>
|
||||||
|
<polygon points="160 112 112 80 112 144 160 112" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><rect x="32" y="48" width="192" height="128" rx="8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="32" y1="208" x2="224" y2="208" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
|
||||||
|
</symbol>
|
||||||
<symbol id="icon-play" viewBox="0 0 24 24">
|
<symbol id="icon-play" viewBox="0 0 24 24">
|
||||||
<path d="M5.541 2.159c-0.153-0.1-0.34-0.159-0.541-0.159-0.552 0-1 0.448-1 1v18c-0.001 0.182 0.050 0.372 0.159 0.541 0.299 0.465 0.917 0.599 1.382 0.3l14-9c0.114-0.072 0.219-0.174 0.3-0.3 0.299-0.465 0.164-1.083-0.3-1.382zM6 4.832l11.151 7.168-11.151 7.168z"/>
|
<path d="M5.541 2.159c-0.153-0.1-0.34-0.159-0.541-0.159-0.552 0-1 0.448-1 1v18c-0.001 0.182 0.050 0.372 0.159 0.541 0.299 0.465 0.917 0.599 1.382 0.3l14-9c0.114-0.072 0.219-0.174 0.3-0.3 0.299-0.465 0.164-1.083-0.3-1.382zM6 4.832l11.151 7.168-11.151 7.168z"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
@ -301,5 +305,8 @@
|
||||||
<symbol id="icon-history" viewBox="0 0 256 256">
|
<symbol id="icon-history" viewBox="0 0 256 256">
|
||||||
<path d="M136,80v43.47l36.12,21.67a8,8,0,0,1-8.24,13.72l-40-24A8,8,0,0,1,120,128V80a8,8,0,0,1,16,0Zm-8-48A95.44,95.44,0,0,0,60.08,60.15C52.81,67.51,46.35,74.59,40,82V64a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H72a8,8,0,0,0,0-16H49c7.15-8.42,14.27-16.35,22.39-24.57a80,80,0,1,1,1.66,114.75,8,8,0,1,0-11,11.64A96,96,0,1,0,128,32Z" />
|
<path d="M136,80v43.47l36.12,21.67a8,8,0,0,1-8.24,13.72l-40-24A8,8,0,0,1,120,128V80a8,8,0,0,1,16,0Zm-8-48A95.44,95.44,0,0,0,60.08,60.15C52.81,67.51,46.35,74.59,40,82V64a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H72a8,8,0,0,0,0-16H49c7.15-8.42,14.27-16.35,22.39-24.57a80,80,0,1,1,1.66,114.75,8,8,0,1,0-11,11.64A96,96,0,1,0,128,32Z" />
|
||||||
</symbol>
|
</symbol>
|
||||||
|
<symbol id="icon-caret-right" fill="currentColor" viewBox="0 0 256 256">
|
||||||
|
<path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z" />
|
||||||
|
</symbol>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 70 KiB |
|
@ -5,6 +5,7 @@ import App from "../shared/components/app/app";
|
||||||
import { lazyHighlightjs } from "../shared/lazy-highlightjs";
|
import { lazyHighlightjs } from "../shared/lazy-highlightjs";
|
||||||
import { loadUserLanguage } from "../shared/services/I18NextService";
|
import { loadUserLanguage } from "../shared/services/I18NextService";
|
||||||
import { verifyDynamicImports } from "../shared/dynamic-imports";
|
import { verifyDynamicImports } from "../shared/dynamic-imports";
|
||||||
|
import { setupEmojiDataModel } from "../shared/markdown";
|
||||||
|
|
||||||
import "bootstrap/js/dist/collapse";
|
import "bootstrap/js/dist/collapse";
|
||||||
import "bootstrap/js/dist/dropdown";
|
import "bootstrap/js/dist/dropdown";
|
||||||
|
@ -22,7 +23,7 @@ async function startClient() {
|
||||||
|
|
||||||
lazyHighlightjs.enableLazyLoading();
|
lazyHighlightjs.enableLazyLoading();
|
||||||
|
|
||||||
await loadUserLanguage();
|
await Promise.all([loadUserLanguage(), setupEmojiDataModel()]);
|
||||||
|
|
||||||
const wrapper = (
|
const wrapper = (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
|
|
|
@ -14,7 +14,7 @@ const themes: ReadonlyArray<string> = [
|
||||||
"litely-compact",
|
"litely-compact",
|
||||||
"vaporwave-dark",
|
"vaporwave-dark",
|
||||||
"vaporwave-light",
|
"vaporwave-light",
|
||||||
"i386",
|
"i386-dark",
|
||||||
];
|
];
|
||||||
|
|
||||||
export async function buildThemeList(): Promise<ReadonlyArray<string>> {
|
export async function buildThemeList(): Promise<ReadonlyArray<string>> {
|
||||||
|
|
|
@ -33,6 +33,7 @@ export async function createSsrHtml(
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!appleTouchIcon) {
|
if (!appleTouchIcon) {
|
||||||
|
try {
|
||||||
appleTouchIcon = site?.site_view.site.icon
|
appleTouchIcon = site?.site_view.site.icon
|
||||||
? `data:image/png;base64,${await sharp(
|
? `data:image/png;base64,${await sharp(
|
||||||
await fetchIconPng(site.site_view.site.icon),
|
await fetchIconPng(site.site_view.site.icon),
|
||||||
|
@ -49,6 +50,12 @@ export async function createSsrHtml(
|
||||||
.toBuffer()
|
.toBuffer()
|
||||||
.then(buf => buf.toString("base64"))}`
|
.then(buf => buf.toString("base64"))}`
|
||||||
: favIconPngUrl;
|
: favIconPngUrl;
|
||||||
|
} catch {
|
||||||
|
console.log(
|
||||||
|
"Could not fetch site logo for apple touch icon. Using default icon.",
|
||||||
|
);
|
||||||
|
appleTouchIcon = favIconPngUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const erudaStr =
|
const erudaStr =
|
||||||
|
|
|
@ -1,20 +1,55 @@
|
||||||
import { readFile } from "fs/promises";
|
|
||||||
import { Site } from "lemmy-js-client";
|
import { Site } from "lemmy-js-client";
|
||||||
import path from "path";
|
|
||||||
import { fetchIconPng } from "./fetch-icon-png";
|
import { fetchIconPng } from "./fetch-icon-png";
|
||||||
|
import { getStaticDir } from "@utils/env";
|
||||||
|
|
||||||
|
type Icon = { sizes: string; src: string; type: string; purpose: string };
|
||||||
const iconSizes = [72, 96, 128, 144, 152, 192, 384, 512];
|
const iconSizes = [72, 96, 128, 144, 152, 192, 384, 512];
|
||||||
|
let icons: Icon[] | null = null;
|
||||||
|
|
||||||
const defaultLogoPathDirectory = path.join(
|
function mapIcon(src: string, size: number): Icon {
|
||||||
process.cwd(),
|
return {
|
||||||
"dist",
|
sizes: `${size}x${size}`,
|
||||||
"assets",
|
type: "image/png",
|
||||||
"icons",
|
src,
|
||||||
);
|
purpose: "any maskable",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateDefaultIcons() {
|
||||||
|
return iconSizes.map(size =>
|
||||||
|
mapIcon(`${getStaticDir()}/assets/icons/icon-${size}x${size}.png`, size),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default async function (site: Site) {
|
export default async function (site: Site) {
|
||||||
|
if (!icons) {
|
||||||
|
try {
|
||||||
const icon = site.icon ? await fetchIconPng(site.icon) : null;
|
const icon = site.icon ? await fetchIconPng(site.icon) : null;
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
icons = await Promise.all(
|
||||||
|
iconSizes.map(async size => {
|
||||||
|
const sharp = (await import("sharp")).default;
|
||||||
|
const src = `data:image/png:base64,${await sharp(icon)
|
||||||
|
.resize(size, size)
|
||||||
|
.png()
|
||||||
|
.toBuffer()
|
||||||
|
.then(buf => buf.toString("base64"))}`;
|
||||||
|
|
||||||
|
return mapIcon(src, size);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
icons = generateDefaultIcons();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
console.log(
|
||||||
|
`Failed to fetch site logo for manifest icon. Using default icon`,
|
||||||
|
);
|
||||||
|
icons = generateDefaultIcons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: site.name,
|
name: site.name,
|
||||||
description: site.description ?? "A link aggregator for the fediverse",
|
description: site.description ?? "A link aggregator for the fediverse",
|
||||||
|
@ -24,29 +59,7 @@ export default async function (site: Site) {
|
||||||
id: "/",
|
id: "/",
|
||||||
background_color: "#222222",
|
background_color: "#222222",
|
||||||
theme_color: "#222222",
|
theme_color: "#222222",
|
||||||
icons: await Promise.all(
|
icons,
|
||||||
iconSizes.map(async size => {
|
|
||||||
let src = await readFile(
|
|
||||||
path.join(defaultLogoPathDirectory, `icon-${size}x${size}.png`),
|
|
||||||
).then(buf => buf.toString("base64"));
|
|
||||||
|
|
||||||
if (icon) {
|
|
||||||
const sharp = (await import("sharp")).default;
|
|
||||||
src = await sharp(icon)
|
|
||||||
.resize(size, size)
|
|
||||||
.png()
|
|
||||||
.toBuffer()
|
|
||||||
.then(buf => buf.toString("base64"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
sizes: `${size}x${size}`,
|
|
||||||
type: "image/png",
|
|
||||||
src: `data:image/png;base64,${src}`,
|
|
||||||
purpose: "any maskable",
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
shortcuts: [
|
shortcuts: [
|
||||||
{
|
{
|
||||||
name: "Search",
|
name: "Search",
|
||||||
|
|
|
@ -13,16 +13,18 @@ import { Navbar } from "./navbar";
|
||||||
import "./styles.scss";
|
import "./styles.scss";
|
||||||
import { Theme } from "./theme";
|
import { Theme } from "./theme";
|
||||||
import AnonymousGuard from "../common/anonymous-guard";
|
import AnonymousGuard from "../common/anonymous-guard";
|
||||||
import AdultConsentModal from "../common/adult-consent-modal";
|
import AdultConsentModal from "../common/modal/adult-consent-modal";
|
||||||
import { destroyTippy, setupTippy } from "../../tippy";
|
import { destroyTippy, setupTippy } from "../../tippy";
|
||||||
|
|
||||||
function handleJumpToContent(event) {
|
function handleJumpToContent(app: App, event: any) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
app.contentRef.current?.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class App extends Component<any, any> {
|
export default class App extends Component<any, any> {
|
||||||
private isoData: IsoDataOptionalSite = setIsoData(this.context);
|
private isoData: IsoDataOptionalSite = setIsoData(this.context);
|
||||||
private readonly rootRef = createRef<HTMLDivElement>();
|
private readonly rootRef = createRef<HTMLDivElement>();
|
||||||
|
readonly contentRef = createRef<HTMLDivElement>();
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
setupTippy(this.rootRef);
|
setupTippy(this.rootRef);
|
||||||
|
@ -32,6 +34,64 @@ export default class App extends Component<any, any> {
|
||||||
destroyTippy();
|
destroyTippy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
routes = routes.map(
|
||||||
|
({
|
||||||
|
path,
|
||||||
|
component: RouteComponent,
|
||||||
|
fetchInitialData,
|
||||||
|
getQueryParams,
|
||||||
|
mountedSameRouteNavKey,
|
||||||
|
}) => (
|
||||||
|
<Route
|
||||||
|
key={path}
|
||||||
|
path={path}
|
||||||
|
exact
|
||||||
|
component={routeProps => {
|
||||||
|
if (!fetchInitialData) {
|
||||||
|
FirstLoadService.falsify();
|
||||||
|
}
|
||||||
|
|
||||||
|
let queryProps = routeProps;
|
||||||
|
if (getQueryParams && this.isoData.site_res) {
|
||||||
|
// ErrorGuard will not render its children when
|
||||||
|
// site_res is missing, this guarantees that props
|
||||||
|
// will always contain the query params.
|
||||||
|
queryProps = {
|
||||||
|
...routeProps,
|
||||||
|
...getQueryParams(
|
||||||
|
routeProps.location.search,
|
||||||
|
this.isoData.site_res,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// When key is location.key the component will be recreated when
|
||||||
|
// navigating to itself. This is usesful to e.g. reset forms.
|
||||||
|
const key = mountedSameRouteNavKey ?? routeProps.location.key;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ErrorGuard>
|
||||||
|
<div tabIndex={-1} ref={this.contentRef}>
|
||||||
|
{RouteComponent &&
|
||||||
|
(isAuthPath(path ?? "") ? (
|
||||||
|
<AuthGuard {...routeProps}>
|
||||||
|
<RouteComponent key={key} {...queryProps} />
|
||||||
|
</AuthGuard>
|
||||||
|
) : isAnonymousPath(path ?? "") ? (
|
||||||
|
<AnonymousGuard>
|
||||||
|
<RouteComponent key={key} {...queryProps} />
|
||||||
|
</AnonymousGuard>
|
||||||
|
) : (
|
||||||
|
<RouteComponent key={key} {...queryProps} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ErrorGuard>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const siteRes = this.isoData.site_res;
|
const siteRes = this.isoData.site_res;
|
||||||
const siteView = siteRes?.site_view;
|
const siteView = siteRes?.site_view;
|
||||||
|
@ -64,58 +124,7 @@ export default class App extends Component<any, any> {
|
||||||
<Navbar siteRes={siteRes} />
|
<Navbar siteRes={siteRes} />
|
||||||
<div className="mt-4 p-0 fl-1">
|
<div className="mt-4 p-0 fl-1">
|
||||||
<Switch>
|
<Switch>
|
||||||
{routes.map(
|
{this.routes}
|
||||||
({
|
|
||||||
path,
|
|
||||||
component: RouteComponent,
|
|
||||||
fetchInitialData,
|
|
||||||
getQueryParams,
|
|
||||||
}) => (
|
|
||||||
<Route
|
|
||||||
key={path}
|
|
||||||
path={path}
|
|
||||||
exact
|
|
||||||
component={routeProps => {
|
|
||||||
if (!fetchInitialData) {
|
|
||||||
FirstLoadService.falsify();
|
|
||||||
}
|
|
||||||
|
|
||||||
let queryProps = routeProps;
|
|
||||||
if (getQueryParams && this.isoData.site_res) {
|
|
||||||
// ErrorGuard will not render its children when
|
|
||||||
// site_res is missing, this guarantees that props
|
|
||||||
// will always contain the query params.
|
|
||||||
queryProps = {
|
|
||||||
...routeProps,
|
|
||||||
...getQueryParams(
|
|
||||||
routeProps.location.search,
|
|
||||||
this.isoData.site_res,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ErrorGuard>
|
|
||||||
<div tabIndex={-1}>
|
|
||||||
{RouteComponent &&
|
|
||||||
(isAuthPath(path ?? "") ? (
|
|
||||||
<AuthGuard {...routeProps}>
|
|
||||||
<RouteComponent {...queryProps} />
|
|
||||||
</AuthGuard>
|
|
||||||
) : isAnonymousPath(path ?? "") ? (
|
|
||||||
<AnonymousGuard>
|
|
||||||
<RouteComponent {...queryProps} />
|
|
||||||
</AnonymousGuard>
|
|
||||||
) : (
|
|
||||||
<RouteComponent {...queryProps} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</ErrorGuard>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
<Route component={ErrorPage} />
|
<Route component={ErrorPage} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -63,7 +63,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
this.handleOutsideMenuClick = this.handleOutsideMenuClick.bind(this);
|
this.handleOutsideMenuClick = this.handleOutsideMenuClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
// Subscribe to jwt changes
|
// Subscribe to jwt changes
|
||||||
if (isBrowser()) {
|
if (isBrowser()) {
|
||||||
// On the first load, check the unreads
|
// On the first load, check the unreads
|
||||||
|
|
|
@ -2,18 +2,23 @@ import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
import { CreateComment, EditComment, Language } from "lemmy-js-client";
|
import {
|
||||||
|
CommentResponse,
|
||||||
|
CreateComment,
|
||||||
|
EditComment,
|
||||||
|
Language,
|
||||||
|
} from "lemmy-js-client";
|
||||||
import { CommentNodeI } from "../../interfaces";
|
import { CommentNodeI } from "../../interfaces";
|
||||||
import { I18NextService, UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { Icon } from "../common/icon";
|
import { Icon } from "../common/icon";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
|
import { RequestState } from "../../services/HttpService";
|
||||||
|
|
||||||
interface CommentFormProps {
|
interface CommentFormProps {
|
||||||
/**
|
/**
|
||||||
* Can either be the parent, or the editable comment. The right side is a postId.
|
* Can either be the parent, or the editable comment. The right side is a postId.
|
||||||
*/
|
*/
|
||||||
node: CommentNodeI | number;
|
node: CommentNodeI | number;
|
||||||
finished?: boolean;
|
|
||||||
edit?: boolean;
|
edit?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
focus?: boolean;
|
focus?: boolean;
|
||||||
|
@ -21,7 +26,9 @@ interface CommentFormProps {
|
||||||
allLanguages: Language[];
|
allLanguages: Language[];
|
||||||
siteLanguages: number[];
|
siteLanguages: number[];
|
||||||
containerClass?: string;
|
containerClass?: string;
|
||||||
onUpsertComment(form: EditComment | CreateComment): void;
|
onUpsertComment(
|
||||||
|
form: EditComment | CreateComment,
|
||||||
|
): Promise<RequestState<CommentResponse>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CommentForm extends Component<CommentFormProps, any> {
|
export class CommentForm extends Component<CommentFormProps, any> {
|
||||||
|
@ -50,7 +57,6 @@ export class CommentForm extends Component<CommentFormProps, any> {
|
||||||
initialContent={initialContent}
|
initialContent={initialContent}
|
||||||
showLanguage
|
showLanguage
|
||||||
buttonTitle={this.buttonTitle}
|
buttonTitle={this.buttonTitle}
|
||||||
finished={this.props.finished}
|
|
||||||
replyType={typeof this.props.node !== "number"}
|
replyType={typeof this.props.node !== "number"}
|
||||||
focus={this.props.focus}
|
focus={this.props.focus}
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
|
@ -68,6 +74,9 @@ export class CommentForm extends Component<CommentFormProps, any> {
|
||||||
<Link className="alert-link" to="/login">
|
<Link className="alert-link" to="/login">
|
||||||
#
|
#
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link className="alert-link" to="/signup">
|
||||||
|
#
|
||||||
|
</Link>
|
||||||
</T>
|
</T>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -83,19 +92,23 @@ export class CommentForm extends Component<CommentFormProps, any> {
|
||||||
: capitalizeFirstLetter(I18NextService.i18n.t("reply"));
|
: capitalizeFirstLetter(I18NextService.i18n.t("reply"));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommentSubmit(content: string, language_id?: number) {
|
async handleCommentSubmit(
|
||||||
|
content: string,
|
||||||
|
language_id?: number,
|
||||||
|
): Promise<boolean> {
|
||||||
const { node, onUpsertComment, edit } = this.props;
|
const { node, onUpsertComment, edit } = this.props;
|
||||||
|
let response: RequestState<CommentResponse>;
|
||||||
|
|
||||||
if (typeof node === "number") {
|
if (typeof node === "number") {
|
||||||
const post_id = node;
|
const post_id = node;
|
||||||
onUpsertComment({
|
response = await onUpsertComment({
|
||||||
content,
|
content,
|
||||||
post_id,
|
post_id,
|
||||||
language_id,
|
language_id,
|
||||||
});
|
});
|
||||||
} else {
|
} else if (edit) {
|
||||||
if (edit) {
|
|
||||||
const comment_id = node.comment_view.comment.id;
|
const comment_id = node.comment_view.comment.id;
|
||||||
onUpsertComment({
|
response = await onUpsertComment({
|
||||||
content,
|
content,
|
||||||
comment_id,
|
comment_id,
|
||||||
language_id,
|
language_id,
|
||||||
|
@ -103,13 +116,14 @@ export class CommentForm extends Component<CommentFormProps, any> {
|
||||||
} else {
|
} else {
|
||||||
const post_id = node.comment_view.post.id;
|
const post_id = node.comment_view.post.id;
|
||||||
const parent_id = node.comment_view.comment.id;
|
const parent_id = node.comment_view.comment.id;
|
||||||
this.props.onUpsertComment({
|
response = await onUpsertComment({
|
||||||
content,
|
content,
|
||||||
parent_id,
|
parent_id,
|
||||||
post_id,
|
post_id,
|
||||||
language_id,
|
language_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return response.state !== "failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { colorList, getCommentParentId } from "@utils/app";
|
||||||
import { futureDaysToUnixTime, numToSI } from "@utils/helpers";
|
import { futureDaysToUnixTime, numToSI } from "@utils/helpers";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { isBefore, parseISO, subMinutes } from "date-fns";
|
import { isBefore, parseISO, subMinutes } from "date-fns";
|
||||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
import {
|
import {
|
||||||
AddAdmin,
|
AddAdmin,
|
||||||
|
@ -33,7 +33,6 @@ import {
|
||||||
SaveComment,
|
SaveComment,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import deepEqual from "lodash.isequal";
|
|
||||||
import { commentTreeMaxDepth } from "../../config";
|
import { commentTreeMaxDepth } from "../../config";
|
||||||
import {
|
import {
|
||||||
CommentNodeI,
|
CommentNodeI,
|
||||||
|
@ -52,7 +51,7 @@ import { CommunityLink } from "../community/community-link";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
import { CommentForm } from "./comment-form";
|
import { CommentForm } from "./comment-form";
|
||||||
import { CommentNodes } from "./comment-nodes";
|
import { CommentNodes } from "./comment-nodes";
|
||||||
import { BanUpdateForm } from "../common/mod-action-form-modal";
|
import { BanUpdateForm } from "../common/modal/mod-action-form-modal";
|
||||||
import CommentActionDropdown from "../common/content-actions/comment-action-dropdown";
|
import CommentActionDropdown from "../common/content-actions/comment-action-dropdown";
|
||||||
import { RequestState } from "../../services/HttpService";
|
import { RequestState } from "../../services/HttpService";
|
||||||
import { VoteDisplay } from "../common/vote-display";
|
import { VoteDisplay } from "../common/vote-display";
|
||||||
|
@ -87,7 +86,6 @@ interface CommentNodeProps {
|
||||||
allLanguages: Language[];
|
allLanguages: Language[];
|
||||||
siteLanguages: number[];
|
siteLanguages: number[];
|
||||||
hideImages?: boolean;
|
hideImages?: boolean;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
onSaveComment(form: SaveComment): Promise<void>;
|
onSaveComment(form: SaveComment): Promise<void>;
|
||||||
onCommentReplyRead(form: MarkCommentReplyAsRead): void;
|
onCommentReplyRead(form: MarkCommentReplyAsRead): void;
|
||||||
onPersonMentionRead(form: MarkPersonMentionAsRead): void;
|
onPersonMentionRead(form: MarkPersonMentionAsRead): void;
|
||||||
|
@ -139,6 +137,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleReplyCancel = this.handleReplyCancel.bind(this);
|
this.handleReplyCancel = this.handleReplyCancel.bind(this);
|
||||||
|
this.handleCreateComment = this.handleCreateComment.bind(this);
|
||||||
|
this.handleEditComment = this.handleEditComment.bind(this);
|
||||||
this.handleReportComment = this.handleReportComment.bind(this);
|
this.handleReportComment = this.handleReportComment.bind(this);
|
||||||
this.handleRemoveComment = this.handleRemoveComment.bind(this);
|
this.handleRemoveComment = this.handleRemoveComment.bind(this);
|
||||||
this.handleReplyClick = this.handleReplyClick.bind(this);
|
this.handleReplyClick = this.handleReplyClick.bind(this);
|
||||||
|
@ -164,22 +164,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
return this.commentView.comment.id;
|
return this.commentView.comment.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(
|
|
||||||
nextProps: Readonly<{ children?: InfernoNode } & CommentNodeProps>,
|
|
||||||
): void {
|
|
||||||
if (!deepEqual(this.props, nextProps)) {
|
|
||||||
this.setState({
|
|
||||||
showEdit: false,
|
|
||||||
showAdvanced: false,
|
|
||||||
createOrEditCommentLoading: false,
|
|
||||||
upvoteLoading: false,
|
|
||||||
downvoteLoading: false,
|
|
||||||
readLoading: false,
|
|
||||||
fetchChildrenLoading: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const node = this.props.node;
|
const node = this.props.node;
|
||||||
const cv = this.commentView;
|
const cv = this.commentView;
|
||||||
|
@ -283,12 +267,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
edit
|
edit
|
||||||
onReplyCancel={this.handleReplyCancel}
|
onReplyCancel={this.handleReplyCancel}
|
||||||
disabled={this.props.locked}
|
disabled={this.props.locked}
|
||||||
finished={this.props.finished.get(id)}
|
|
||||||
focus
|
focus
|
||||||
allLanguages={this.props.allLanguages}
|
allLanguages={this.props.allLanguages}
|
||||||
siteLanguages={this.props.siteLanguages}
|
siteLanguages={this.props.siteLanguages}
|
||||||
containerClass="comment-comment-container"
|
containerClass="comment-comment-container"
|
||||||
onUpsertComment={this.props.onEditComment}
|
onUpsertComment={this.handleEditComment}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!this.state.showEdit && !this.state.collapsed && (
|
{!this.state.showEdit && !this.state.collapsed && (
|
||||||
|
@ -311,7 +294,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="comment-bottom-btns d-flex justify-content-between justify-content-lg-start flex-wrap text-muted fw-bold mt-1">
|
<div className="comment-bottom-btns d-flex justify-content-start column-gap-1.5 flex-wrap text-muted fw-bold mt-1 align-items-center">
|
||||||
{this.props.showContext && this.getLinkButton()}
|
{this.props.showContext && this.getLinkButton()}
|
||||||
{this.props.markable && (
|
{this.props.markable && (
|
||||||
<button
|
<button
|
||||||
|
@ -425,12 +408,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
node={node}
|
node={node}
|
||||||
onReplyCancel={this.handleReplyCancel}
|
onReplyCancel={this.handleReplyCancel}
|
||||||
disabled={this.props.locked}
|
disabled={this.props.locked}
|
||||||
finished={this.props.finished.get(id)}
|
|
||||||
focus
|
focus
|
||||||
allLanguages={this.props.allLanguages}
|
allLanguages={this.props.allLanguages}
|
||||||
siteLanguages={this.props.siteLanguages}
|
siteLanguages={this.props.siteLanguages}
|
||||||
containerClass="comment-comment-container"
|
containerClass="comment-comment-container"
|
||||||
onUpsertComment={this.props.onCreateComment}
|
onUpsertComment={this.handleCreateComment}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!this.state.collapsed && node.children.length > 0 && (
|
{!this.state.collapsed && node.children.length > 0 && (
|
||||||
|
@ -447,7 +429,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
hideImages={this.props.hideImages}
|
hideImages={this.props.hideImages}
|
||||||
isChild={!this.props.isTopLevel}
|
isChild={!this.props.isTopLevel}
|
||||||
depth={this.props.node.depth + 1}
|
depth={this.props.node.depth + 1}
|
||||||
finished={this.props.finished}
|
|
||||||
onCommentReplyRead={this.props.onCommentReplyRead}
|
onCommentReplyRead={this.props.onCommentReplyRead}
|
||||||
onPersonMentionRead={this.props.onPersonMentionRead}
|
onPersonMentionRead={this.props.onPersonMentionRead}
|
||||||
onCreateComment={this.props.onCreateComment}
|
onCreateComment={this.props.onCreateComment}
|
||||||
|
@ -502,7 +483,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<>
|
<>
|
||||||
<Link
|
<Link
|
||||||
className={classnames}
|
className={classnames}
|
||||||
to={`/comment/${
|
to={`/post/${cv.post.id}/${
|
||||||
(this.props.showContext && getCommentParentId(cv.comment)) ||
|
(this.props.showContext && getCommentParentId(cv.comment)) ||
|
||||||
cv.comment.id
|
cv.comment.id
|
||||||
}`}
|
}`}
|
||||||
|
@ -559,6 +540,26 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this.setState({ showReply: false, showEdit: false });
|
this.setState({ showReply: false, showEdit: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleCreateComment(
|
||||||
|
form: CreateComment,
|
||||||
|
): Promise<RequestState<CommentResponse>> {
|
||||||
|
const res = await this.props.onCreateComment(form);
|
||||||
|
if (res.state !== "failed") {
|
||||||
|
this.setState({ showReply: false, showEdit: false });
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleEditComment(
|
||||||
|
form: EditComment,
|
||||||
|
): Promise<RequestState<CommentResponse>> {
|
||||||
|
const res = await this.props.onEditComment(form);
|
||||||
|
if (res.state !== "failed") {
|
||||||
|
this.setState({ showReply: false, showEdit: false });
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
isPersonMentionType(item: CommentNodeView): item is PersonMentionView {
|
isPersonMentionType(item: CommentNodeView): item is PersonMentionView {
|
||||||
return item.person_mention?.id !== undefined;
|
return item.person_mention?.id !== undefined;
|
||||||
}
|
}
|
||||||
|
@ -636,7 +637,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
async handleBanFromCommunity({
|
async handleBanFromCommunity({
|
||||||
daysUntilExpires,
|
daysUntilExpires,
|
||||||
reason,
|
reason,
|
||||||
shouldRemove,
|
shouldRemoveOrRestoreData,
|
||||||
}: BanUpdateForm) {
|
}: BanUpdateForm) {
|
||||||
const {
|
const {
|
||||||
creator: { id: person_id },
|
creator: { id: person_id },
|
||||||
|
@ -645,10 +646,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
} = this.commentView;
|
} = this.commentView;
|
||||||
|
|
||||||
const ban = !creator_banned_from_community;
|
const ban = !creator_banned_from_community;
|
||||||
|
|
||||||
// If its an unban, restore all their data
|
// If its an unban, restore all their data
|
||||||
if (ban === false) {
|
if (ban === false) {
|
||||||
shouldRemove = false;
|
shouldRemoveOrRestoreData = true;
|
||||||
}
|
}
|
||||||
const expires = futureDaysToUnixTime(daysUntilExpires);
|
const expires = futureDaysToUnixTime(daysUntilExpires);
|
||||||
|
|
||||||
|
@ -656,7 +656,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
community_id,
|
community_id,
|
||||||
person_id,
|
person_id,
|
||||||
ban,
|
ban,
|
||||||
remove_data: shouldRemove,
|
remove_or_restore_data: shouldRemoveOrRestoreData,
|
||||||
reason,
|
reason,
|
||||||
expires,
|
expires,
|
||||||
});
|
});
|
||||||
|
@ -665,7 +665,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
async handleBanFromSite({
|
async handleBanFromSite({
|
||||||
daysUntilExpires,
|
daysUntilExpires,
|
||||||
reason,
|
reason,
|
||||||
shouldRemove,
|
shouldRemoveOrRestoreData,
|
||||||
}: BanUpdateForm) {
|
}: BanUpdateForm) {
|
||||||
const {
|
const {
|
||||||
creator: { id: person_id, banned },
|
creator: { id: person_id, banned },
|
||||||
|
@ -675,14 +675,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
|
|
||||||
// If its an unban, restore all their data
|
// If its an unban, restore all their data
|
||||||
if (ban === false) {
|
if (ban === false) {
|
||||||
shouldRemove = false;
|
shouldRemoveOrRestoreData = true;
|
||||||
}
|
}
|
||||||
const expires = futureDaysToUnixTime(daysUntilExpires);
|
const expires = futureDaysToUnixTime(daysUntilExpires);
|
||||||
|
|
||||||
this.props.onBanPerson({
|
this.props.onBanPerson({
|
||||||
person_id,
|
person_id,
|
||||||
ban,
|
ban,
|
||||||
remove_data: shouldRemove,
|
remove_or_restore_data: shouldRemoveOrRestoreData,
|
||||||
reason,
|
reason,
|
||||||
expires,
|
expires,
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
BanFromCommunity,
|
BanFromCommunity,
|
||||||
BanPerson,
|
BanPerson,
|
||||||
BlockPerson,
|
BlockPerson,
|
||||||
CommentId,
|
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
CommunityModeratorView,
|
CommunityModeratorView,
|
||||||
CreateComment,
|
CreateComment,
|
||||||
|
@ -52,7 +51,6 @@ interface CommentNodesProps {
|
||||||
hideImages?: boolean;
|
hideImages?: boolean;
|
||||||
isChild?: boolean;
|
isChild?: boolean;
|
||||||
depth?: number;
|
depth?: number;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
onSaveComment(form: SaveComment): Promise<void>;
|
onSaveComment(form: SaveComment): Promise<void>;
|
||||||
onCommentReplyRead(form: MarkCommentReplyAsRead): void;
|
onCommentReplyRead(form: MarkCommentReplyAsRead): void;
|
||||||
onPersonMentionRead(form: MarkPersonMentionAsRead): void;
|
onPersonMentionRead(form: MarkPersonMentionAsRead): void;
|
||||||
|
@ -124,7 +122,6 @@ export class CommentNodes extends Component<CommentNodesProps, any> {
|
||||||
hideImages={this.props.hideImages}
|
hideImages={this.props.hideImages}
|
||||||
onCommentReplyRead={this.props.onCommentReplyRead}
|
onCommentReplyRead={this.props.onCommentReplyRead}
|
||||||
onPersonMentionRead={this.props.onPersonMentionRead}
|
onPersonMentionRead={this.props.onPersonMentionRead}
|
||||||
finished={this.props.finished}
|
|
||||||
onCreateComment={this.props.onCreateComment}
|
onCreateComment={this.props.onCreateComment}
|
||||||
onEditComment={this.props.onEditComment}
|
onEditComment={this.props.onEditComment}
|
||||||
onCommentVote={this.props.onCommentVote}
|
onCommentVote={this.props.onCommentVote}
|
||||||
|
|
|
@ -90,7 +90,6 @@ export class CommentReport extends Component<
|
||||||
siteLanguages={[]}
|
siteLanguages={[]}
|
||||||
hideImages
|
hideImages
|
||||||
// All of these are unused, since its viewonly
|
// All of these are unused, since its viewonly
|
||||||
finished={new Map()}
|
|
||||||
onSaveComment={async () => {}}
|
onSaveComment={async () => {}}
|
||||||
onBlockPerson={async () => {}}
|
onBlockPerson={async () => {}}
|
||||||
onDeleteComment={async () => {}}
|
onDeleteComment={async () => {}}
|
||||||
|
|
|
@ -1,30 +1,25 @@
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { UserService } from "../../services";
|
import { UserService } from "../../services";
|
||||||
import { Spinner } from "./icon";
|
import { Spinner } from "./icon";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
interface AnonymousGuardState {
|
class AnonymousGuard extends Component<any, any> {
|
||||||
hasRedirected: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AnonymousGuard extends Component<any, AnonymousGuardState> {
|
|
||||||
state = {
|
|
||||||
hasRedirected: false,
|
|
||||||
} as AnonymousGuardState;
|
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
hasAuth() {
|
||||||
if (UserService.Instance.myUserInfo) {
|
return UserService.Instance.myUserInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
if (this.hasAuth() && isBrowser()) {
|
||||||
this.context.router.history.replace(`/`);
|
this.context.router.history.replace(`/`);
|
||||||
} else {
|
|
||||||
this.setState({ hasRedirected: true });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.state.hasRedirected ? this.props.children : <Spinner />;
|
return !this.hasAuth() ? this.props.children : <Spinner />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,12 @@ import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { UserService } from "../../services";
|
import { UserService } from "../../services";
|
||||||
import { Spinner } from "./icon";
|
import { Spinner } from "./icon";
|
||||||
import { getQueryString } from "@utils/helpers";
|
import { getQueryString } from "@utils/helpers";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
interface AuthGuardState {
|
|
||||||
hasRedirected: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AuthGuard extends Component<
|
class AuthGuard extends Component<
|
||||||
RouteComponentProps<Record<string, string>>,
|
RouteComponentProps<Record<string, string>>,
|
||||||
AuthGuardState
|
any
|
||||||
> {
|
> {
|
||||||
state = {
|
|
||||||
hasRedirected: false,
|
|
||||||
} as AuthGuardState;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
props: RouteComponentProps<Record<string, string>>,
|
props: RouteComponentProps<Record<string, string>>,
|
||||||
context: any,
|
context: any,
|
||||||
|
@ -23,19 +16,21 @@ class AuthGuard extends Component<
|
||||||
super(props, context);
|
super(props, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
hasAuth() {
|
||||||
if (!UserService.Instance.myUserInfo) {
|
return UserService.Instance.myUserInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
if (!this.hasAuth() && isBrowser()) {
|
||||||
const { pathname, search } = this.props.location;
|
const { pathname, search } = this.props.location;
|
||||||
this.context.router.history.replace(
|
this.context.router.history.replace(
|
||||||
`/login${getQueryString({ prev: pathname + search })}`,
|
`/login${getQueryString({ prev: pathname + search })}`,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
this.setState({ hasRedirected: true });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.state.hasRedirected ? this.props.children : <Spinner />;
|
return this.hasAuth() ? this.props.children : <Spinner />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,13 +47,13 @@ export class CommentSortSelect extends Component<
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
{I18NextService.i18n.t("sort_type")}
|
{I18NextService.i18n.t("sort_type")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"Hot"}>{I18NextService.i18n.t("hot")}</option>,
|
<option value="Hot">{I18NextService.i18n.t("hot")}</option>
|
||||||
<option value={"Controversial"}>
|
<option value="Controversial">
|
||||||
{I18NextService.i18n.t("controversial")}
|
{I18NextService.i18n.t("controversial")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"Top"}>{I18NextService.i18n.t("top")}</option>,
|
<option value="Top">{I18NextService.i18n.t("top")}</option>
|
||||||
<option value={"New"}>{I18NextService.i18n.t("new")}</option>
|
<option value="New">{I18NextService.i18n.t("new")}</option>
|
||||||
<option value={"Old"}>{I18NextService.i18n.t("old")}</option>
|
<option value="Old">{I18NextService.i18n.t("old")}</option>
|
||||||
</select>
|
</select>
|
||||||
<a
|
<a
|
||||||
className="sort-select-help text-muted"
|
className="sort-select-help text-muted"
|
||||||
|
|
|
@ -14,9 +14,11 @@ import {
|
||||||
import ActionButton from "./action-button";
|
import ActionButton from "./action-button";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
import ConfirmationModal from "../confirmation-modal";
|
import ConfirmationModal from "../modal/confirmation-modal";
|
||||||
import ViewVotesModal from "../view-votes-modal";
|
import ViewVotesModal from "../modal/view-votes-modal";
|
||||||
import ModActionFormModal, { BanUpdateForm } from "../mod-action-form-modal";
|
import ModActionFormModal, {
|
||||||
|
BanUpdateForm,
|
||||||
|
} from "../modal/mod-action-form-modal";
|
||||||
import { BanType, CommentNodeView, PurgeType } from "../../../interfaces";
|
import { BanType, CommentNodeView, PurgeType } from "../../../interfaces";
|
||||||
import { getApubName, hostname } from "@utils/helpers";
|
import { getApubName, hostname } from "@utils/helpers";
|
||||||
import { tippyMixin } from "../../mixins/tippy-mixin";
|
import { tippyMixin } from "../../mixins/tippy-mixin";
|
||||||
|
@ -159,6 +161,26 @@ export default class ContentActionDropdown extends Component<
|
||||||
(amMod(community.id) || (amAdmin() && community.local)) &&
|
(amMod(community.id) || (amAdmin() && community.local)) &&
|
||||||
!creator_banned_from_community;
|
!creator_banned_from_community;
|
||||||
|
|
||||||
|
const modHistoryUserTranslation = I18NextService.i18n.t(
|
||||||
|
"user_moderation_history",
|
||||||
|
{ user: creator.name },
|
||||||
|
);
|
||||||
|
|
||||||
|
// The link and translation string for the item
|
||||||
|
const { modHistoryItemLink, modHistoryItemTranslation } =
|
||||||
|
type === "post"
|
||||||
|
? {
|
||||||
|
modHistoryItemLink: `/modlog?postId=${id}`,
|
||||||
|
modHistoryItemTranslation: I18NextService.i18n.t(
|
||||||
|
"post_moderation_history",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
modHistoryItemLink: `/modlog?commentId=${id}`,
|
||||||
|
modHistoryItemTranslation: I18NextService.i18n.t(
|
||||||
|
"comment_moderation_history",
|
||||||
|
),
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{type === "comment" && (
|
{type === "comment" && (
|
||||||
|
@ -349,15 +371,23 @@ export default class ContentActionDropdown extends Component<
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<Link
|
||||||
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
||||||
to={`/modlog?${type === "post" ? "postId" : "commentId"}=${id}`}
|
to={`/modlog?userId=${creator.id}`}
|
||||||
title={I18NextService.i18n.t("moderation_history")}
|
title={modHistoryUserTranslation}
|
||||||
aria-label={I18NextService.i18n.t("moderation_history")}
|
aria-label={modHistoryUserTranslation}
|
||||||
data-tippy-content={I18NextService.i18n.t(
|
data-tippy-content={modHistoryUserTranslation}
|
||||||
"moderation_history",
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<Icon icon="history" inline classes="me-2" />
|
<Icon icon="history" inline classes="me-2" />
|
||||||
{I18NextService.i18n.t("moderation_history")}
|
{modHistoryUserTranslation}
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
||||||
|
to={modHistoryItemLink}
|
||||||
|
title={modHistoryItemTranslation}
|
||||||
|
aria-label={modHistoryItemTranslation}
|
||||||
|
data-tippy-content={modHistoryItemTranslation}
|
||||||
|
>
|
||||||
|
<Icon icon="history" inline classes="me-2" />
|
||||||
|
{modHistoryItemTranslation}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
{(this.canMod || this.canAdmin) && (
|
{(this.canMod || this.canAdmin) && (
|
||||||
|
@ -643,7 +673,6 @@ export default class ContentActionDropdown extends Component<
|
||||||
type,
|
type,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// Wait until componentDidMount runs (which only happens on the browser) to prevent sending over a gratuitous amount of markup
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{renderRemoveDialog && (
|
{renderRemoveDialog && (
|
||||||
|
|
|
@ -13,8 +13,10 @@ interface EmojiPickerState {
|
||||||
showPicker: boolean;
|
showPicker: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeEmojiMartOnEsc(i, event): void {
|
function closeEmojiMartOnEsc(i: EmojiPicker, event: KeyboardEvent): void {
|
||||||
event.key === "Escape" && i.setState({ showPicker: false });
|
if (event.key === "Escape") {
|
||||||
|
i.setState({ showPicker: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@tippyMixin
|
@tippyMixin
|
||||||
|
@ -72,9 +74,11 @@ export class EmojiPicker extends Component<EmojiPickerProps, EmojiPickerState> {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
i.setState({ showPicker: !i.state.showPicker });
|
i.setState({ showPicker: !i.state.showPicker });
|
||||||
|
|
||||||
i.state.showPicker
|
if (i.state.showPicker) {
|
||||||
? document.addEventListener("keyup", e => closeEmojiMartOnEsc(i, e))
|
document.addEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
|
||||||
: document.removeEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
|
} else {
|
||||||
|
document.removeEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEmojiClick(e: any) {
|
handleEmojiClick(e: any) {
|
||||||
|
|
|
@ -77,8 +77,6 @@ export class ImageUploadForm extends Component<
|
||||||
i.setState({ loading: true });
|
i.setState({ loading: true });
|
||||||
|
|
||||||
HttpService.client.uploadImage({ image }).then(res => {
|
HttpService.client.uploadImage({ image }).then(res => {
|
||||||
console.log("pictrs upload:");
|
|
||||||
console.log(res);
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
if (res.data.msg === "ok") {
|
if (res.data.msg === "ok") {
|
||||||
i.props.onUpload(res.data.url as string);
|
i.props.onUpload(res.data.url as string);
|
||||||
|
|
|
@ -58,40 +58,6 @@ class PostsLoadingSkeletonItem extends Component<any, any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TrendingCommunitiesLoadingSkeleton extends Component<
|
|
||||||
LoadingSkeletonProps,
|
|
||||||
any
|
|
||||||
> {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="mb-2">
|
|
||||||
{Array.from({ length: this.props.itemCount ?? 10 }, (_, index) => (
|
|
||||||
<TrendingCommunitiesLoadingSkeletonItem key={index} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TrendingCommunitiesLoadingSkeletonItem extends Component<any, any> {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="col flex-grow-1 mt-2 ps-2 pe-4">
|
|
||||||
<div className="row">
|
|
||||||
<div className="col flex-grow-0 pe-0">
|
|
||||||
<div className="d-flex placeholder-glow img-icon">
|
|
||||||
<span className="placeholder placeholder-lg w-100 h-100 rounded-circle" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col flex-grow-1 pe-0">
|
|
||||||
<LoadingSkeletonLine size={12} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CommentsLoadingSkeleton extends Component<any, any> {
|
export class CommentsLoadingSkeleton extends Component<any, any> {
|
||||||
render() {
|
render() {
|
||||||
return Array.from({ length: this.props.itemCount ?? 10 }, (_, index) => (
|
return Array.from({ length: this.props.itemCount ?? 10 }, (_, index) => (
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { numToSI, randomStr } from "@utils/helpers";
|
||||||
import autosize from "autosize";
|
import autosize from "autosize";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { NoOptionI18nKeys } from "i18next";
|
import { NoOptionI18nKeys } from "i18next";
|
||||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { Prompt } from "inferno-router";
|
import { Prompt } from "inferno-router";
|
||||||
import { Language } from "lemmy-js-client";
|
import { Language } from "lemmy-js-client";
|
||||||
import {
|
import {
|
||||||
|
@ -41,15 +41,15 @@ interface MarkdownTextAreaProps {
|
||||||
replyType?: boolean;
|
replyType?: boolean;
|
||||||
focus?: boolean;
|
focus?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
finished?: boolean;
|
|
||||||
/**
|
/**
|
||||||
* Whether to show the language selector
|
* Whether to show the language selector
|
||||||
*/
|
*/
|
||||||
showLanguage?: boolean;
|
showLanguage?: boolean;
|
||||||
hideNavigationWarnings?: boolean;
|
hideNavigationWarnings?: boolean;
|
||||||
onContentChange?(val: string): void;
|
onContentChange?(val: string): void;
|
||||||
|
onContentBlur?(val: string): void;
|
||||||
onReplyCancel?(): void;
|
onReplyCancel?(): void;
|
||||||
onSubmit?(content: string, languageId?: number): void;
|
onSubmit?(content: string, languageId?: number): Promise<boolean>;
|
||||||
allLanguages: Language[]; // TODO should probably be nullable
|
allLanguages: Language[]; // TODO should probably be nullable
|
||||||
siteLanguages: number[]; // TODO same
|
siteLanguages: number[]; // TODO same
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,6 @@ export class MarkdownTextArea extends Component<
|
||||||
private id = `markdown-textarea-${randomStr()}`;
|
private id = `markdown-textarea-${randomStr()}`;
|
||||||
private formId = `markdown-form-${randomStr()}`;
|
private formId = `markdown-form-${randomStr()}`;
|
||||||
|
|
||||||
private tribute: any;
|
|
||||||
|
|
||||||
state: MarkdownTextAreaState = {
|
state: MarkdownTextAreaState = {
|
||||||
content: this.props.initialContent,
|
content: this.props.initialContent,
|
||||||
languageId: this.props.initialLanguageId,
|
languageId: this.props.initialLanguageId,
|
||||||
|
@ -91,17 +89,15 @@ export class MarkdownTextArea extends Component<
|
||||||
|
|
||||||
this.handleLanguageChange = this.handleLanguageChange.bind(this);
|
this.handleLanguageChange = this.handleLanguageChange.bind(this);
|
||||||
this.handleEmoji = this.handleEmoji.bind(this);
|
this.handleEmoji = this.handleEmoji.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
if (isBrowser()) {
|
if (isBrowser()) {
|
||||||
this.tribute = setupTribute();
|
const tribute = await setupTribute();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const textarea: any = document.getElementById(this.id);
|
const textarea: any = document.getElementById(this.id);
|
||||||
if (textarea) {
|
if (textarea) {
|
||||||
autosize(textarea);
|
autosize(textarea);
|
||||||
this.tribute.attach(textarea);
|
tribute.attach(textarea);
|
||||||
textarea.addEventListener("tribute-replaced", () => {
|
textarea.addEventListener("tribute-replaced", () => {
|
||||||
this.setState({ content: textarea.value });
|
this.setState({ content: textarea.value });
|
||||||
autosize.update(textarea);
|
autosize.update(textarea);
|
||||||
|
@ -114,26 +110,6 @@ export class MarkdownTextArea extends Component<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(
|
|
||||||
nextProps: MarkdownTextAreaProps & { children?: InfernoNode },
|
|
||||||
) {
|
|
||||||
if (nextProps.finished) {
|
|
||||||
this.setState({
|
|
||||||
previewMode: false,
|
|
||||||
imageUploadStatus: undefined,
|
|
||||||
loading: false,
|
|
||||||
content: undefined,
|
|
||||||
});
|
|
||||||
if (this.props.replyType) {
|
|
||||||
this.props.onReplyCancel?.();
|
|
||||||
}
|
|
||||||
|
|
||||||
const textarea: any = document.getElementById(this.id);
|
|
||||||
const form: any = document.getElementById(this.formId);
|
|
||||||
form.reset();
|
|
||||||
setTimeout(() => autosize.update(textarea), 10);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -149,8 +125,8 @@ export class MarkdownTextArea extends Component<
|
||||||
message={I18NextService.i18n.t("block_leaving")}
|
message={I18NextService.i18n.t("block_leaving")}
|
||||||
when={
|
when={
|
||||||
!this.props.hideNavigationWarnings &&
|
!this.props.hideNavigationWarnings &&
|
||||||
!!this.state.content &&
|
((!!this.state.content && !this.state.submitted) ||
|
||||||
!this.state.submitted
|
this.state.loading)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
|
@ -237,6 +213,7 @@ export class MarkdownTextArea extends Component<
|
||||||
)}
|
)}
|
||||||
value={this.state.content}
|
value={this.state.content}
|
||||||
onInput={linkEvent(this, this.handleContentChange)}
|
onInput={linkEvent(this, this.handleContentChange)}
|
||||||
|
onBlur={linkEvent(this, this.handleContentBlur)}
|
||||||
onPaste={linkEvent(this, this.handlePaste)}
|
onPaste={linkEvent(this, this.handlePaste)}
|
||||||
onKeyDown={linkEvent(this, this.handleKeyBinds)}
|
onKeyDown={linkEvent(this, this.handleKeyBinds)}
|
||||||
required
|
required
|
||||||
|
@ -246,6 +223,7 @@ export class MarkdownTextArea extends Component<
|
||||||
this.props.maxLength ?? markdownFieldCharacterLimit
|
this.props.maxLength ?? markdownFieldCharacterLimit
|
||||||
}
|
}
|
||||||
placeholder={this.props.placeholder}
|
placeholder={this.props.placeholder}
|
||||||
|
spellCheck
|
||||||
/>
|
/>
|
||||||
{this.state.previewMode && this.state.content && (
|
{this.state.previewMode && this.state.content && (
|
||||||
<div
|
<div
|
||||||
|
@ -279,29 +257,14 @@ export class MarkdownTextArea extends Component<
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 d-flex align-items-center flex-wrap mt-2">
|
<div className="col-12 d-flex align-items-center flex-wrap mt-2">
|
||||||
{this.props.showLanguage && (
|
{this.props.buttonTitle && (
|
||||||
<LanguageSelect
|
|
||||||
iconVersion
|
|
||||||
allLanguages={this.props.allLanguages}
|
|
||||||
selectedLanguageIds={
|
|
||||||
languageId ? Array.of(languageId) : undefined
|
|
||||||
}
|
|
||||||
siteLanguages={this.props.siteLanguages}
|
|
||||||
onChange={this.handleLanguageChange}
|
|
||||||
disabled={this.isDisabled}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* A flex expander */}
|
|
||||||
<div className="flex-grow-1"></div>
|
|
||||||
|
|
||||||
{this.props.replyType && (
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="submit"
|
||||||
className="btn btn-sm btn-secondary ms-2"
|
className="btn btn-sm btn-secondary ms-2"
|
||||||
onClick={linkEvent(this, this.handleReplyCancel)}
|
disabled={this.isDisabled || !this.state.content}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("cancel")}
|
{this.state.loading && <Spinner className="me-1" />}
|
||||||
|
{this.props.buttonTitle}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
|
@ -316,16 +279,31 @@ export class MarkdownTextArea extends Component<
|
||||||
? I18NextService.i18n.t("edit")
|
? I18NextService.i18n.t("edit")
|
||||||
: I18NextService.i18n.t("preview")}
|
: I18NextService.i18n.t("preview")}
|
||||||
</button>
|
</button>
|
||||||
{this.props.buttonTitle && (
|
{this.props.replyType && (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="button"
|
||||||
className="btn btn-sm btn-secondary ms-2"
|
className="btn btn-sm btn-secondary ms-2"
|
||||||
disabled={this.isDisabled || !this.state.content}
|
onClick={linkEvent(this, this.handleReplyCancel)}
|
||||||
>
|
>
|
||||||
{this.state.loading && <Spinner className="me-1" />}
|
{I18NextService.i18n.t("cancel")}
|
||||||
{this.props.buttonTitle}
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* A flex expander */}
|
||||||
|
<div className="flex-grow-1"></div>
|
||||||
|
|
||||||
|
{this.props.showLanguage && (
|
||||||
|
<LanguageSelect
|
||||||
|
iconVersion
|
||||||
|
allLanguages={this.props.allLanguages}
|
||||||
|
selectedLanguageIds={
|
||||||
|
languageId ? Array.of(languageId) : undefined
|
||||||
|
}
|
||||||
|
siteLanguages={this.props.siteLanguages}
|
||||||
|
onChange={this.handleLanguageChange}
|
||||||
|
disabled={this.isDisabled}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -471,7 +449,7 @@ export class MarkdownTextArea extends Component<
|
||||||
}));
|
}));
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch {
|
||||||
errorOccurred = true;
|
errorOccurred = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -479,8 +457,6 @@ export class MarkdownTextArea extends Component<
|
||||||
|
|
||||||
async uploadSingleImage(i: MarkdownTextArea, image: File) {
|
async uploadSingleImage(i: MarkdownTextArea, image: File) {
|
||||||
const res = await HttpService.client.uploadImage({ image });
|
const res = await HttpService.client.uploadImage({ image });
|
||||||
console.log("pictrs upload:");
|
|
||||||
console.log(res);
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
if (res.data.msg === "ok") {
|
if (res.data.msg === "ok") {
|
||||||
const imageMarkdown = `![](${res.data.url})`;
|
const imageMarkdown = `![](${res.data.url})`;
|
||||||
|
@ -518,6 +494,10 @@ export class MarkdownTextArea extends Component<
|
||||||
i.contentChange();
|
i.contentChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleContentBlur(i: MarkdownTextArea, event: any) {
|
||||||
|
i.props.onContentBlur?.(event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
// Keybind handler
|
// Keybind handler
|
||||||
// Keybinds inspired by github comment area
|
// Keybinds inspired by github comment area
|
||||||
handleKeyBinds(i: MarkdownTextArea, event: KeyboardEvent) {
|
handleKeyBinds(i: MarkdownTextArea, event: KeyboardEvent) {
|
||||||
|
@ -575,11 +555,15 @@ export class MarkdownTextArea extends Component<
|
||||||
this.setState({ languageId: val[0] });
|
this.setState({ languageId: val[0] });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmit(i: MarkdownTextArea, event: any) {
|
async handleSubmit(i: MarkdownTextArea, event: any) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (i.state.content) {
|
if (i.state.content) {
|
||||||
i.setState({ loading: true, submitted: true });
|
i.setState({ loading: true, submitted: true });
|
||||||
i.props.onSubmit?.(i.state.content, i.state.languageId);
|
const success = await i.props.onSubmit?.(
|
||||||
|
i.state.content,
|
||||||
|
i.state.languageId,
|
||||||
|
);
|
||||||
|
i.setState({ loading: false, submitted: success ?? true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,7 +760,9 @@ export class MarkdownTextArea extends Component<
|
||||||
getSelectedText(): string {
|
getSelectedText(): string {
|
||||||
const { selectionStart: start, selectionEnd: end } =
|
const { selectionStart: start, selectionEnd: end } =
|
||||||
document.getElementById(this.id) as any;
|
document.getElementById(this.id) as any;
|
||||||
return start !== end ? this.state.content?.substring(start, end) ?? "" : "";
|
return start !== end
|
||||||
|
? (this.state.content?.substring(start, end) ?? "")
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
get isDisabled() {
|
get isDisabled() {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Component, LinkedEvent, createRef, linkEvent } from "inferno";
|
import { Component, LinkedEvent, createRef, linkEvent } from "inferno";
|
||||||
import { modalMixin } from "../mixins/modal-mixin";
|
import { modalMixin } from "../../mixins/modal-mixin";
|
||||||
import { adultConsentCookieKey } from "../../config";
|
import { adultConsentCookieKey } from "../../../config";
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../../markdown";
|
||||||
import { I18NextService } from "../../services";
|
import { I18NextService } from "../../../services";
|
||||||
import { isHttps } from "@utils/env";
|
import { isHttps } from "@utils/env";
|
||||||
import { IsoData } from "../../interfaces";
|
import { IsoData } from "../../../interfaces";
|
||||||
import { setIsoData } from "@utils/app";
|
import { setIsoData } from "@utils/app";
|
||||||
|
|
||||||
interface AdultConsentModalProps {
|
interface AdultConsentModalProps {
|
|
@ -1,20 +1,14 @@
|
||||||
import {
|
import { Component, RefObject, createRef, linkEvent } from "inferno";
|
||||||
Component,
|
import { I18NextService } from "../../../services";
|
||||||
InfernoNode,
|
|
||||||
RefObject,
|
|
||||||
createRef,
|
|
||||||
linkEvent,
|
|
||||||
} from "inferno";
|
|
||||||
import { I18NextService } from "../../services";
|
|
||||||
import type { Modal } from "bootstrap";
|
import type { Modal } from "bootstrap";
|
||||||
import { Spinner } from "./icon";
|
import { Spinner } from "../icon";
|
||||||
import { LoadingEllipses } from "./loading-ellipses";
|
import { LoadingEllipses } from "../loading-ellipses";
|
||||||
import { modalMixin } from "../mixins/modal-mixin";
|
import { modalMixin } from "../../mixins/modal-mixin";
|
||||||
|
import { MouseEventHandler } from "inferno";
|
||||||
|
|
||||||
interface ConfirmationModalProps {
|
interface ConfirmationModalProps {
|
||||||
children?: InfernoNode;
|
|
||||||
onYes: () => Promise<void>;
|
onYes: () => Promise<void>;
|
||||||
onNo: () => void;
|
onNo: MouseEventHandler<HTMLButtonElement>;
|
||||||
message: string;
|
message: string;
|
||||||
loadingMessage: string;
|
loadingMessage: string;
|
||||||
show: boolean;
|
show: boolean;
|
|
@ -0,0 +1,386 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
FormEventHandler,
|
||||||
|
MouseEventHandler,
|
||||||
|
RefObject,
|
||||||
|
createRef,
|
||||||
|
linkEvent,
|
||||||
|
} from "inferno";
|
||||||
|
import type { Modal } from "bootstrap";
|
||||||
|
import { modalMixin } from "../../mixins/modal-mixin";
|
||||||
|
import { I18NextService } from "../../../services/I18NextService";
|
||||||
|
import {
|
||||||
|
CreateOAuthProvider,
|
||||||
|
EditOAuthProvider,
|
||||||
|
OAuthProvider,
|
||||||
|
} from "lemmy-js-client";
|
||||||
|
import { ProviderToEdit } from "@utils/types/oauth";
|
||||||
|
|
||||||
|
export type CreateOrEditOAuthProviderModalData =
|
||||||
|
| { type: "add"; provider?: ProviderToEdit }
|
||||||
|
| { type: "edit" | "add"; provider: OAuthProvider };
|
||||||
|
|
||||||
|
interface CreateOrEditOAuthProviderModalProps {
|
||||||
|
onClose: MouseEventHandler<HTMLButtonElement>;
|
||||||
|
show: boolean;
|
||||||
|
data: CreateOrEditOAuthProviderModalData;
|
||||||
|
onSubmit: (
|
||||||
|
provider: CreateOAuthProvider | EditOAuthProvider,
|
||||||
|
) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CreateOrEditOAuthProviderModalState {
|
||||||
|
changed: boolean;
|
||||||
|
provider: Partial<CreateOAuthProvider>;
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProviderFieldProps {
|
||||||
|
id: string;
|
||||||
|
i18nKey: string;
|
||||||
|
onInput: FormEventHandler<HTMLInputElement>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProviderTextFieldProps extends ProviderFieldProps {
|
||||||
|
disabled?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
type?: "text" | "url" | "password";
|
||||||
|
value?: string;
|
||||||
|
required?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderBooleanProperties =
|
||||||
|
| "enabled"
|
||||||
|
| "account_linking_enabled"
|
||||||
|
| "auto_verify_email";
|
||||||
|
|
||||||
|
interface ProviderCheckboxFieldProps extends ProviderFieldProps {
|
||||||
|
checked?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FORM_ID = "create-or-edit-oauth-provider-form-id";
|
||||||
|
|
||||||
|
function handleTextPropertyChange(
|
||||||
|
{
|
||||||
|
modal,
|
||||||
|
property,
|
||||||
|
}: {
|
||||||
|
modal: CreateOrEditOAuthProviderModal;
|
||||||
|
property: Exclude<keyof CreateOAuthProvider, ProviderBooleanProperties>;
|
||||||
|
},
|
||||||
|
event: any,
|
||||||
|
) {
|
||||||
|
modal.setState(prevState => ({
|
||||||
|
changed: true,
|
||||||
|
provider: {
|
||||||
|
...prevState.provider,
|
||||||
|
[property]: event.target.value,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBooleanPropertyChange({
|
||||||
|
modal,
|
||||||
|
property,
|
||||||
|
}: {
|
||||||
|
modal: CreateOrEditOAuthProviderModal;
|
||||||
|
property: Extract<keyof ProviderToEdit, ProviderBooleanProperties>;
|
||||||
|
}) {
|
||||||
|
modal.setState(prevState => ({
|
||||||
|
changed: true,
|
||||||
|
provider: {
|
||||||
|
...prevState.provider,
|
||||||
|
[property]: !prevState.provider[property],
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProviderTextField({
|
||||||
|
id,
|
||||||
|
i18nKey,
|
||||||
|
type = "text",
|
||||||
|
value,
|
||||||
|
onInput,
|
||||||
|
required = true,
|
||||||
|
disabled,
|
||||||
|
placeholder,
|
||||||
|
}: ProviderTextFieldProps) {
|
||||||
|
return (
|
||||||
|
<div className="col">
|
||||||
|
<label className="form-label" htmlFor={id}>
|
||||||
|
{I18NextService.i18n.t(i18nKey)}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
id={id}
|
||||||
|
className="form-control"
|
||||||
|
value={value}
|
||||||
|
onInput={onInput}
|
||||||
|
required={required}
|
||||||
|
disabled={disabled}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProviderCheckboxField({
|
||||||
|
i18nKey,
|
||||||
|
id,
|
||||||
|
onInput,
|
||||||
|
checked,
|
||||||
|
}: ProviderCheckboxFieldProps) {
|
||||||
|
return (
|
||||||
|
<div className="form-check form-check-inline m-2">
|
||||||
|
<input
|
||||||
|
id={id}
|
||||||
|
type="checkbox"
|
||||||
|
className="form-check-input"
|
||||||
|
checked={checked}
|
||||||
|
onInput={onInput}
|
||||||
|
/>
|
||||||
|
<label htmlFor={id} className="form-check-label">
|
||||||
|
{I18NextService.i18n.t(i18nKey)}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@modalMixin
|
||||||
|
export default class CreateOrEditOAuthProviderModal extends Component<
|
||||||
|
CreateOrEditOAuthProviderModalProps,
|
||||||
|
CreateOrEditOAuthProviderModalState
|
||||||
|
> {
|
||||||
|
readonly modalDivRef: RefObject<HTMLDivElement>;
|
||||||
|
modal?: Modal;
|
||||||
|
|
||||||
|
state: CreateOrEditOAuthProviderModalState = {
|
||||||
|
changed: false,
|
||||||
|
provider: {},
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: CreateOrEditOAuthProviderModalProps, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
this.modalDivRef = createRef();
|
||||||
|
|
||||||
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: Readonly<CreateOrEditOAuthProviderModalProps>) {
|
||||||
|
if (this.props.show && this.props.show !== prevProps.show) {
|
||||||
|
this.setState({ provider: this.props.data.provider ?? {} });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(
|
||||||
|
{ onClose, data }: CreateOrEditOAuthProviderModalProps,
|
||||||
|
{ provider, changed, loading }: CreateOrEditOAuthProviderModalState,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="modal fade"
|
||||||
|
id="create-or-edit-oauth-modal"
|
||||||
|
tabIndex={-1}
|
||||||
|
aria-hidden
|
||||||
|
aria-labelledby="#create-or-edit-oauth-modal-title"
|
||||||
|
data-bs-backdrop="static"
|
||||||
|
data-bs-keyboard="false"
|
||||||
|
ref={this.modalDivRef}
|
||||||
|
>
|
||||||
|
<div className="modal-dialog modal-fullscreen-sm-down">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<h1
|
||||||
|
className="modal-title h4"
|
||||||
|
id="create-or-edit-oauth-modal-title"
|
||||||
|
>
|
||||||
|
{data.type === "edit"
|
||||||
|
? `Edit ${data.provider.display_name}`
|
||||||
|
: "Add OAuth Provider"}
|
||||||
|
</h1>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
aria-label={I18NextService.i18n.t("cancel")}
|
||||||
|
onClick={onClose}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body p-2-!important">
|
||||||
|
<form
|
||||||
|
id={FORM_ID}
|
||||||
|
className="container"
|
||||||
|
onSubmit={this.handleSubmit}
|
||||||
|
>
|
||||||
|
<div className="row row-cols-1 mb-3 gy-2">
|
||||||
|
<ProviderTextField
|
||||||
|
id="display-name"
|
||||||
|
i18nKey="oauth_display_name"
|
||||||
|
value={provider?.display_name}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "display_name" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="issuer"
|
||||||
|
i18nKey="oauth_issuer"
|
||||||
|
value={provider?.issuer}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "issuer" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
type="url"
|
||||||
|
disabled={data.type === "edit"}
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="authorization-endpoint"
|
||||||
|
i18nKey="oauth_authorization_endpoint"
|
||||||
|
value={provider?.authorization_endpoint}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "authorization_endpoint" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
type="url"
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="token-endpoint"
|
||||||
|
i18nKey="oauth_token_endpoint"
|
||||||
|
value={provider?.token_endpoint}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "token_endpoint" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
type="url"
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="userinfo-endpoint"
|
||||||
|
i18nKey="oauth_userinfo_endpoint"
|
||||||
|
value={provider?.userinfo_endpoint}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "userinfo_endpoint" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
type="url"
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="id-claim"
|
||||||
|
i18nKey="oauth_id_claim"
|
||||||
|
value={provider?.id_claim}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "id_claim" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="client-id"
|
||||||
|
i18nKey="oauth_client_id"
|
||||||
|
value={provider?.client_id}
|
||||||
|
disabled={data.type === "edit"}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "client_id" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="client-secret"
|
||||||
|
i18nKey="oauth_client_secret"
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "client_secret" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
type="password"
|
||||||
|
placeholder={
|
||||||
|
data.type === "edit"
|
||||||
|
? I18NextService.i18n.t(
|
||||||
|
"cannot_view_secret_after_saving",
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
required={data.type === "add"}
|
||||||
|
value={provider.client_secret}
|
||||||
|
/>
|
||||||
|
<ProviderTextField
|
||||||
|
id="scopes"
|
||||||
|
i18nKey="oauth_scopes"
|
||||||
|
value={provider?.scopes}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{ modal: this, property: "scopes" },
|
||||||
|
handleTextPropertyChange,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col">
|
||||||
|
<ProviderCheckboxField
|
||||||
|
id="auto-verfiy-email"
|
||||||
|
i18nKey="oauth_auto_verify_email"
|
||||||
|
checked={provider?.auto_verify_email}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{
|
||||||
|
modal: this,
|
||||||
|
property: "auto_verify_email",
|
||||||
|
},
|
||||||
|
handleBooleanPropertyChange,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ProviderCheckboxField
|
||||||
|
id="account-linking-enabled"
|
||||||
|
i18nKey="oauth_account_linking_enabled"
|
||||||
|
checked={provider?.account_linking_enabled}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{
|
||||||
|
modal: this,
|
||||||
|
property: "account_linking_enabled",
|
||||||
|
},
|
||||||
|
handleBooleanPropertyChange,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ProviderCheckboxField
|
||||||
|
id="oauth-enabled"
|
||||||
|
i18nKey="oauth_enabled"
|
||||||
|
checked={provider?.enabled ?? true}
|
||||||
|
onInput={linkEvent(
|
||||||
|
{
|
||||||
|
modal: this,
|
||||||
|
property: "enabled",
|
||||||
|
},
|
||||||
|
handleBooleanPropertyChange,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-danger"
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t("cancel")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
form={FORM_ID}
|
||||||
|
className="btn btn-success"
|
||||||
|
disabled={!changed || loading}
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t(data.type === "edit" ? "edit" : "add")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleSubmit(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.setState({ loading: true });
|
||||||
|
await this.props.onSubmit(this.state.provider as CreateOAuthProvider);
|
||||||
|
this.setState({ loading: false, changed: false, provider: {} });
|
||||||
|
}
|
||||||
|
}
|
77
src/shared/components/common/modal/display-modal.tsx
Normal file
77
src/shared/components/common/modal/display-modal.tsx
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
InfernoNode,
|
||||||
|
MouseEventHandler,
|
||||||
|
RefObject,
|
||||||
|
createRef,
|
||||||
|
} from "inferno";
|
||||||
|
import type { Modal } from "bootstrap";
|
||||||
|
import { Spinner } from "../icon";
|
||||||
|
import { LoadingEllipses } from "../loading-ellipses";
|
||||||
|
import { modalMixin } from "../../mixins/modal-mixin";
|
||||||
|
|
||||||
|
interface DisplayModalProps {
|
||||||
|
children: InfernoNode;
|
||||||
|
loadingMessage?: string;
|
||||||
|
title: string;
|
||||||
|
onClose: MouseEventHandler<HTMLButtonElement>;
|
||||||
|
show: boolean;
|
||||||
|
loading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@modalMixin
|
||||||
|
export default class DisplayModal extends Component<DisplayModalProps, any> {
|
||||||
|
readonly modalDivRef: RefObject<HTMLDivElement>;
|
||||||
|
modal?: Modal;
|
||||||
|
|
||||||
|
constructor(props: DisplayModalProps, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
this.modalDivRef = createRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { children, loadingMessage, title, onClose, loading } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="modal fade"
|
||||||
|
id="display-modal"
|
||||||
|
tabIndex={-1}
|
||||||
|
aria-hidden
|
||||||
|
aria-labelledby="#displayModalTitle"
|
||||||
|
data-bs-backdrop="static"
|
||||||
|
ref={this.modalDivRef}
|
||||||
|
>
|
||||||
|
<div className="modal-dialog modal-fullscreen-sm-down">
|
||||||
|
<div className="modal-content">
|
||||||
|
<header className="modal-header">
|
||||||
|
<h3 className="modal-title" id="displayModalTitle">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
aria-label="Close"
|
||||||
|
onClick={onClose}
|
||||||
|
/>
|
||||||
|
</header>
|
||||||
|
<div className="modal-body">
|
||||||
|
{loading ? (
|
||||||
|
<div class="text-center align-middle text-body">
|
||||||
|
<Spinner large />
|
||||||
|
<div>
|
||||||
|
{loadingMessage}
|
||||||
|
<LoadingEllipses />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
children
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,18 +5,18 @@ import {
|
||||||
createRef,
|
createRef,
|
||||||
linkEvent,
|
linkEvent,
|
||||||
} from "inferno";
|
} from "inferno";
|
||||||
import { I18NextService } from "../../services/I18NextService";
|
import { I18NextService } from "../../../services/I18NextService";
|
||||||
import { PurgeWarning, Spinner } from "./icon";
|
import { PurgeWarning, Spinner } from "../icon";
|
||||||
import { getApubName, randomStr } from "@utils/helpers";
|
import { getApubName, randomStr } from "@utils/helpers";
|
||||||
import type { Modal } from "bootstrap";
|
import type { Modal } from "bootstrap";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Community, Person } from "lemmy-js-client";
|
import { Community, Person } from "lemmy-js-client";
|
||||||
import { LoadingEllipses } from "./loading-ellipses";
|
import { LoadingEllipses } from "../loading-ellipses";
|
||||||
import { modalMixin } from "../mixins/modal-mixin";
|
import { modalMixin } from "../../mixins/modal-mixin";
|
||||||
|
|
||||||
export interface BanUpdateForm {
|
export interface BanUpdateForm {
|
||||||
reason?: string;
|
reason?: string;
|
||||||
shouldRemove?: boolean;
|
shouldRemoveOrRestoreData?: boolean;
|
||||||
daysUntilExpires?: number;
|
daysUntilExpires?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ interface ModActionFormModalPropsCommunityBan {
|
||||||
modActionType: "community-ban";
|
modActionType: "community-ban";
|
||||||
onSubmit: (form: BanUpdateForm) => Promise<void>;
|
onSubmit: (form: BanUpdateForm) => Promise<void>;
|
||||||
creator: Person;
|
creator: Person;
|
||||||
community: Community;
|
community?: Community;
|
||||||
isBanned: boolean;
|
isBanned: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ interface ModActionFormFormState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
reason: string;
|
reason: string;
|
||||||
daysUntilExpire?: number;
|
daysUntilExpire?: number;
|
||||||
shouldRemoveData?: boolean;
|
shouldRemoveOrRestoreData?: boolean;
|
||||||
shouldPermaBan?: boolean;
|
shouldPermaBan?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ function handleExpiryChange(i: ModActionFormModal, event: any) {
|
||||||
function handleToggleRemove(i: ModActionFormModal) {
|
function handleToggleRemove(i: ModActionFormModal) {
|
||||||
i.setState(prev => ({
|
i.setState(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
shouldRemoveData: !prev.shouldRemoveData,
|
shouldRemoveOrRestoreData: !prev.shouldRemoveOrRestoreData,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ async function handleSubmit(i: ModActionFormModal, event: any) {
|
||||||
await i.props.onSubmit({
|
await i.props.onSubmit({
|
||||||
reason: i.state.reason,
|
reason: i.state.reason,
|
||||||
daysUntilExpires: i.state.daysUntilExpire!,
|
daysUntilExpires: i.state.daysUntilExpire!,
|
||||||
shouldRemove: i.state.shouldRemoveData!,
|
shouldRemoveOrRestoreData: i.state.shouldRemoveOrRestoreData!,
|
||||||
} as BanUpdateForm & string); // Need to & string to handle type weirdness
|
} as BanUpdateForm & string); // Need to & string to handle type weirdness
|
||||||
} else {
|
} else {
|
||||||
await i.props.onSubmit(i.state.reason);
|
await i.props.onSubmit(i.state.reason);
|
||||||
|
@ -135,7 +135,7 @@ export default class ModActionFormModal extends Component<
|
||||||
this.reasonRef = createRef();
|
this.reasonRef = createRef();
|
||||||
|
|
||||||
if (this.isBanModal) {
|
if (this.isBanModal) {
|
||||||
this.state.shouldRemoveData = false;
|
this.state.shouldRemoveOrRestoreData = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ export default class ModActionFormModal extends Component<
|
||||||
loading,
|
loading,
|
||||||
reason,
|
reason,
|
||||||
daysUntilExpire,
|
daysUntilExpire,
|
||||||
shouldRemoveData,
|
shouldRemoveOrRestoreData,
|
||||||
shouldPermaBan,
|
shouldPermaBan,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const reasonId = `mod-form-reason-${randomStr()}`;
|
const reasonId = `mod-form-reason-${randomStr()}`;
|
||||||
|
@ -249,7 +249,7 @@ export default class ModActionFormModal extends Component<
|
||||||
<input
|
<input
|
||||||
className="form-check-input user-select-none"
|
className="form-check-input user-select-none"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={shouldRemoveData}
|
checked={shouldRemoveOrRestoreData}
|
||||||
onChange={linkEvent(this, handleToggleRemove)}
|
onChange={linkEvent(this, handleToggleRemove)}
|
||||||
/>
|
/>
|
||||||
{I18NextService.i18n.t("remove_content")}
|
{I18NextService.i18n.t("remove_content")}
|
||||||
|
@ -328,7 +328,12 @@ export default class ModActionFormModal extends Component<
|
||||||
: "ban_from_community_with_name",
|
: "ban_from_community_with_name",
|
||||||
{
|
{
|
||||||
user: getApubName(this.props.creator),
|
user: getApubName(this.props.creator),
|
||||||
community: getApubName(this.props.community),
|
community: getApubName(
|
||||||
|
this.props.community ?? {
|
||||||
|
actor_id: "",
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -6,10 +6,10 @@ import {
|
||||||
createRef,
|
createRef,
|
||||||
linkEvent,
|
linkEvent,
|
||||||
} from "inferno";
|
} from "inferno";
|
||||||
import { I18NextService } from "../../services";
|
import { I18NextService } from "../../../services";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../../toast";
|
||||||
import type { Modal } from "bootstrap";
|
import type { Modal } from "bootstrap";
|
||||||
import { modalMixin } from "../mixins/modal-mixin";
|
import { modalMixin } from "../../mixins/modal-mixin";
|
||||||
|
|
||||||
interface TotpModalProps {
|
interface TotpModalProps {
|
||||||
children?: InfernoNode;
|
children?: InfernoNode;
|
||||||
|
@ -201,7 +201,7 @@ export default class TotpModal extends Component<
|
||||||
this.inputRef.current?.focus();
|
this.inputRef.current?.focus();
|
||||||
|
|
||||||
if (this.props.type === "generate") {
|
if (this.props.type === "generate") {
|
||||||
const { getSVG } = await import("@shortcm/qr-image/lib/svg");
|
const { getSVG } = await import("qreator/lib/svg");
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
qrCode: URL.createObjectURL(
|
qrCode: URL.createObjectURL(
|
|
@ -5,10 +5,10 @@ import {
|
||||||
createRef,
|
createRef,
|
||||||
linkEvent,
|
linkEvent,
|
||||||
} from "inferno";
|
} from "inferno";
|
||||||
import { I18NextService } from "../../services";
|
import { I18NextService } from "../../../services";
|
||||||
import type { Modal } from "bootstrap";
|
import type { Modal } from "bootstrap";
|
||||||
import { Icon, Spinner } from "./icon";
|
import { Icon, Spinner } from "../icon";
|
||||||
import { Paginator } from "../common/paginator";
|
import { Paginator } from "../paginator";
|
||||||
import {
|
import {
|
||||||
ListCommentLikesResponse,
|
ListCommentLikesResponse,
|
||||||
ListPostLikesResponse,
|
ListPostLikesResponse,
|
||||||
|
@ -19,11 +19,12 @@ import {
|
||||||
HttpService,
|
HttpService,
|
||||||
LOADING_REQUEST,
|
LOADING_REQUEST,
|
||||||
RequestState,
|
RequestState,
|
||||||
} from "../../services/HttpService";
|
} from "../../../services/HttpService";
|
||||||
import { fetchLimit } from "../../config";
|
import { fetchLimit } from "../../../config";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../../person/person-listing";
|
||||||
import { modalMixin } from "../mixins/modal-mixin";
|
import { modalMixin } from "../../mixins/modal-mixin";
|
||||||
import { UserBadges } from "./user-badges";
|
import { UserBadges } from "../user-badges";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
interface ViewVotesModalProps {
|
interface ViewVotesModalProps {
|
||||||
children?: InfernoNode;
|
children?: InfernoNode;
|
||||||
|
@ -96,8 +97,8 @@ export default class ViewVotesModal extends Component<
|
||||||
this.handlePageChange = this.handlePageChange.bind(this);
|
this.handlePageChange = this.handlePageChange.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (this.props.show) {
|
if (this.props.show && isBrowser()) {
|
||||||
await this.refetch();
|
await this.refetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ interface PaginatorProps {
|
||||||
page: number;
|
page: number;
|
||||||
onChange(val: number): any;
|
onChange(val: number): any;
|
||||||
nextDisabled: boolean;
|
nextDisabled: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Paginator extends Component<PaginatorProps, any> {
|
export class Paginator extends Component<PaginatorProps, any> {
|
||||||
|
@ -18,6 +19,7 @@ export class Paginator extends Component<PaginatorProps, any> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary me-2"
|
className="btn btn-secondary me-2"
|
||||||
onClick={linkEvent(this, this.handlePrev)}
|
onClick={linkEvent(this, this.handlePrev)}
|
||||||
|
disabled={this.props.disabled}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("prev")}
|
{I18NextService.i18n.t("prev")}
|
||||||
</button>
|
</button>
|
||||||
|
@ -26,6 +28,7 @@ export class Paginator extends Component<PaginatorProps, any> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={linkEvent(this, this.handleNext)}
|
onClick={linkEvent(this, this.handleNext)}
|
||||||
|
disabled={this.props.disabled}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("next")}
|
{I18NextService.i18n.t("next")}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -16,6 +16,7 @@ interface PasswordInputProps {
|
||||||
label?: string | null;
|
label?: string | null;
|
||||||
showForgotLink?: boolean;
|
showForgotLink?: boolean;
|
||||||
isNew?: boolean;
|
isNew?: boolean;
|
||||||
|
required?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PasswordInputState {
|
interface PasswordInputState {
|
||||||
|
@ -77,6 +78,7 @@ class PasswordInput extends Component<PasswordInputProps, PasswordInputState> {
|
||||||
label,
|
label,
|
||||||
showForgotLink,
|
showForgotLink,
|
||||||
isNew,
|
isNew,
|
||||||
|
required,
|
||||||
},
|
},
|
||||||
state: { show },
|
state: { show },
|
||||||
} = this;
|
} = this;
|
||||||
|
@ -98,9 +100,11 @@ class PasswordInput extends Component<PasswordInputProps, PasswordInputState> {
|
||||||
autoComplete={isNew ? "new-password" : "current-password"}
|
autoComplete={isNew ? "new-password" : "current-password"}
|
||||||
onInput={onInput}
|
onInput={onInput}
|
||||||
value={value}
|
value={value}
|
||||||
required
|
required={required !== false}
|
||||||
pattern=".{10,60}"
|
pattern=".+"
|
||||||
title={I18NextService.i18n.t("invalid_password")}
|
title={I18NextService.i18n.t("invalid_password")}
|
||||||
|
minLength={isNew ? 10 : undefined}
|
||||||
|
maxLength={isNew ? 60 : undefined}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="btn btn-outline-dark"
|
className="btn btn-outline-dark"
|
||||||
|
|
|
@ -39,7 +39,7 @@ function handleSearch(i: SearchableSelect, e: ChangeEvent<HTMLInputElement>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusSearch(i: SearchableSelect) {
|
function focusSearch(i: SearchableSelect) {
|
||||||
if (i.toggleButtonRef.current?.ariaExpanded !== "true") {
|
if (i.toggleButtonRef.current?.ariaExpanded === "true") {
|
||||||
i.searchInputRef.current?.focus();
|
i.searchInputRef.current?.focus();
|
||||||
|
|
||||||
if (i.props.onSearch) {
|
if (i.props.onSearch) {
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import { randomStr } from "@utils/helpers";
|
import { randomStr } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { SortType } from "lemmy-js-client";
|
import { PostSortType } from "lemmy-js-client";
|
||||||
import { relTags, sortingHelpUrl } from "../../config";
|
import { relTags, sortingHelpUrl } from "../../config";
|
||||||
import { I18NextService } from "../../services";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
|
||||||
interface SortSelectProps {
|
interface SortSelectProps {
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
onChange(val: SortType): void;
|
onChange(val: PostSortType): void;
|
||||||
hideHot?: boolean;
|
hideHot?: boolean;
|
||||||
hideMostComments?: boolean;
|
hideMostComments?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SortSelectState {
|
interface SortSelectState {
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
||||||
|
@ -47,55 +47,53 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
||||||
{I18NextService.i18n.t("sort_type")}
|
{I18NextService.i18n.t("sort_type")}
|
||||||
</option>
|
</option>
|
||||||
{!this.props.hideHot && [
|
{!this.props.hideHot && [
|
||||||
<option key={"Hot"} value={"Hot"}>
|
<option key="Hot" value="Hot">
|
||||||
{I18NextService.i18n.t("hot")}
|
{I18NextService.i18n.t("hot")}
|
||||||
</option>,
|
</option>,
|
||||||
<option key={"Active"} value={"Active"}>
|
<option key="Active" value="Active">
|
||||||
{I18NextService.i18n.t("active")}
|
{I18NextService.i18n.t("active")}
|
||||||
</option>,
|
</option>,
|
||||||
<option key={"Scaled"} value={"Scaled"}>
|
<option key="Scaled" value="Scaled">
|
||||||
{I18NextService.i18n.t("scaled")}
|
{I18NextService.i18n.t("scaled")}
|
||||||
</option>,
|
</option>,
|
||||||
]}
|
]}
|
||||||
<option value={"Controversial"}>
|
<option value="Controversial">
|
||||||
{I18NextService.i18n.t("controversial")}
|
{I18NextService.i18n.t("controversial")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"New"}>{I18NextService.i18n.t("new")}</option>
|
<option value="New">{I18NextService.i18n.t("new")}</option>
|
||||||
<option value={"Old"}>{I18NextService.i18n.t("old")}</option>
|
<option value="Old">{I18NextService.i18n.t("old")}</option>
|
||||||
{!this.props.hideMostComments && [
|
{!this.props.hideMostComments && [
|
||||||
<option key={"MostComments"} value={"MostComments"}>
|
<option key="MostComments" value="MostComments">
|
||||||
{I18NextService.i18n.t("most_comments")}
|
{I18NextService.i18n.t("most_comments")}
|
||||||
</option>,
|
</option>,
|
||||||
<option key={"NewComments"} value={"NewComments"}>
|
<option key="NewComments" value="NewComments">
|
||||||
{I18NextService.i18n.t("new_comments")}
|
{I18NextService.i18n.t("new_comments")}
|
||||||
</option>,
|
</option>,
|
||||||
]}
|
]}
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
─────
|
─────
|
||||||
</option>
|
</option>
|
||||||
<option value={"TopHour"}>{I18NextService.i18n.t("top_hour")}</option>
|
<option value="TopHour">{I18NextService.i18n.t("top_hour")}</option>
|
||||||
<option value={"TopSixHour"}>
|
<option value="TopSixHour">
|
||||||
{I18NextService.i18n.t("top_six_hours")}
|
{I18NextService.i18n.t("top_six_hours")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"TopTwelveHour"}>
|
<option value="TopTwelveHour">
|
||||||
{I18NextService.i18n.t("top_twelve_hours")}
|
{I18NextService.i18n.t("top_twelve_hours")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"TopDay"}>{I18NextService.i18n.t("top_day")}</option>
|
<option value="TopDay">{I18NextService.i18n.t("top_day")}</option>
|
||||||
<option value={"TopWeek"}>{I18NextService.i18n.t("top_week")}</option>
|
<option value="TopWeek">{I18NextService.i18n.t("top_week")}</option>
|
||||||
<option value={"TopMonth"}>
|
<option value="TopMonth">{I18NextService.i18n.t("top_month")}</option>
|
||||||
{I18NextService.i18n.t("top_month")}
|
<option value="TopThreeMonths">
|
||||||
</option>
|
|
||||||
<option value={"TopThreeMonths"}>
|
|
||||||
{I18NextService.i18n.t("top_three_months")}
|
{I18NextService.i18n.t("top_three_months")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"TopSixMonths"}>
|
<option value="TopSixMonths">
|
||||||
{I18NextService.i18n.t("top_six_months")}
|
{I18NextService.i18n.t("top_six_months")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"TopNineMonths"}>
|
<option value="TopNineMonths">
|
||||||
{I18NextService.i18n.t("top_nine_months")}
|
{I18NextService.i18n.t("top_nine_months")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"TopYear"}>{I18NextService.i18n.t("top_year")}</option>
|
<option value="TopYear">{I18NextService.i18n.t("top_year")}</option>
|
||||||
<option value={"TopAll"}>{I18NextService.i18n.t("top_all")}</option>
|
<option value="TopAll">{I18NextService.i18n.t("top_all")}</option>
|
||||||
</select>
|
</select>
|
||||||
<a
|
<a
|
||||||
className="sort-select-icon text-muted"
|
className="sort-select-icon text-muted"
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { getQueryString, validInstanceTLD } from "@utils/helpers";
|
import { getQueryString, validInstanceTLD } from "@utils/helpers";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { NoOptionI18nKeys } from "i18next";
|
import { NoOptionI18nKeys } from "i18next";
|
||||||
import { Component, MouseEventHandler, linkEvent } from "inferno";
|
import { Component, MouseEventHandler, createRef, linkEvent } from "inferno";
|
||||||
import { CommunityView } from "lemmy-js-client";
|
import { CommunityView } from "lemmy-js-client";
|
||||||
import { I18NextService, UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { VERSION } from "../../version";
|
import { VERSION } from "../../version";
|
||||||
import { Icon, Spinner } from "./icon";
|
import { Icon, Spinner } from "./icon";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
import { modalMixin } from "../mixins/modal-mixin";
|
||||||
|
|
||||||
interface SubscribeButtonProps {
|
interface SubscribeButtonProps {
|
||||||
communityView: CommunityView;
|
communityView: CommunityView;
|
||||||
|
@ -93,6 +94,7 @@ export function SubscribeButton({
|
||||||
|
|
||||||
interface RemoteFetchModalProps {
|
interface RemoteFetchModalProps {
|
||||||
communityActorId: string;
|
communityActorId: string;
|
||||||
|
show?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RemoteFetchModalState {
|
interface RemoteFetchModalState {
|
||||||
|
@ -103,10 +105,6 @@ function handleInput(i: RemoteFetchModal, event: any) {
|
||||||
i.setState({ instanceText: event.target.value });
|
i.setState({ instanceText: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusInput() {
|
|
||||||
document.getElementById("remoteFetchInstance")?.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitRemoteFollow(
|
function submitRemoteFollow(
|
||||||
{ state: { instanceText }, props: { communityActorId } }: RemoteFetchModal,
|
{ state: { instanceText }, props: { communityActorId } }: RemoteFetchModal,
|
||||||
event: Event,
|
event: Event,
|
||||||
|
@ -139,6 +137,7 @@ function submitRemoteFollow(
|
||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@modalMixin
|
||||||
class RemoteFetchModal extends Component<
|
class RemoteFetchModal extends Component<
|
||||||
RemoteFetchModalProps,
|
RemoteFetchModalProps,
|
||||||
RemoteFetchModalState
|
RemoteFetchModalState
|
||||||
|
@ -147,20 +146,15 @@ class RemoteFetchModal extends Component<
|
||||||
instanceText: "",
|
instanceText: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
modalDivRef = createRef<HTMLDivElement>();
|
||||||
|
inputRef = createRef<HTMLInputElement>();
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
handleShow() {
|
||||||
document
|
this.inputRef.current?.focus();
|
||||||
.getElementById("remoteFetchModal")
|
|
||||||
?.addEventListener("shown.bs.modal", focusInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
|
||||||
document
|
|
||||||
.getElementById("remoteFetchModal")
|
|
||||||
?.removeEventListener("shown.bs.modal", focusInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -171,6 +165,7 @@ class RemoteFetchModal extends Component<
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
aria-hidden
|
aria-hidden
|
||||||
aria-labelledby="#remoteFetchModalTitle"
|
aria-labelledby="#remoteFetchModalTitle"
|
||||||
|
ref={this.modalDivRef}
|
||||||
>
|
>
|
||||||
<div className="modal-dialog modal-dialog-centered modal-fullscreen-sm-down">
|
<div className="modal-dialog modal-dialog-centered modal-fullscreen-sm-down">
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
|
@ -203,6 +198,7 @@ class RemoteFetchModal extends Component<
|
||||||
required
|
required
|
||||||
enterKeyHint="go"
|
enterKeyHint="go"
|
||||||
inputMode="url"
|
inputMode="url"
|
||||||
|
ref={this.inputRef}
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
<footer className="modal-footer">
|
<footer className="modal-footer">
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
ListCommunities,
|
ListCommunities,
|
||||||
ListCommunitiesResponse,
|
ListCommunitiesResponse,
|
||||||
ListingType,
|
ListingType,
|
||||||
SortType,
|
PostSortType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { FirstLoadService, I18NextService } from "../../services";
|
import { FirstLoadService, I18NextService } from "../../services";
|
||||||
|
@ -40,6 +40,7 @@ import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
type CommunitiesData = RouteDataResponse<{
|
type CommunitiesData = RouteDataResponse<{
|
||||||
listCommunitiesResponse: ListCommunitiesResponse;
|
listCommunitiesResponse: ListCommunitiesResponse;
|
||||||
|
@ -54,7 +55,7 @@ interface CommunitiesState {
|
||||||
|
|
||||||
interface CommunitiesProps {
|
interface CommunitiesProps {
|
||||||
listingType: ListingType;
|
listingType: ListingType;
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
page: number;
|
page: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +63,8 @@ function getListingTypeFromQuery(listingType?: string): ListingType {
|
||||||
return listingType ? (listingType as ListingType) : "Local";
|
return listingType ? (listingType as ListingType) : "Local";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSortTypeFromQuery(type?: string): SortType {
|
function getSortTypeFromQuery(type?: string): PostSortType {
|
||||||
return type ? (type as SortType) : "TopMonth";
|
return type ? (type as PostSortType) : "TopMonth";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCommunitiesQueryParams(source?: string): CommunitiesProps {
|
export function getCommunitiesQueryParams(source?: string): CommunitiesProps {
|
||||||
|
@ -121,19 +122,23 @@ export class Communities extends Component<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await this.refetch();
|
await this.refetch(this.props);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps: CommunitiesRouteProps) {
|
||||||
|
this.refetch(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${I18NextService.i18n.t("communities")} - ${
|
return `${I18NextService.i18n.t("communities")} - ${
|
||||||
this.state.siteRes.site_view.site.name
|
this.state.siteRes.site_view.site.name
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderListings() {
|
renderListingsTable() {
|
||||||
switch (this.state.listCommunitiesResponse.state) {
|
switch (this.state.listCommunitiesResponse.state) {
|
||||||
case "loading":
|
case "loading":
|
||||||
return (
|
return (
|
||||||
|
@ -142,32 +147,8 @@ export class Communities extends Component<
|
||||||
</h5>
|
</h5>
|
||||||
);
|
);
|
||||||
case "success": {
|
case "success": {
|
||||||
const { listingType, sort, page } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<table id="community_table" className="table table-sm table-hover">
|
||||||
<h1 className="h4 mb-4">
|
|
||||||
{I18NextService.i18n.t("list_of_communities")}
|
|
||||||
</h1>
|
|
||||||
<div className="row g-3 align-items-center mb-2">
|
|
||||||
<div className="col-auto">
|
|
||||||
<ListingTypeSelect
|
|
||||||
type_={listingType}
|
|
||||||
showLocal={showLocal(this.isoData)}
|
|
||||||
showSubscribed
|
|
||||||
onChange={this.handleListingTypeChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="col-auto me-auto">
|
|
||||||
<SortSelect sort={sort} onChange={this.handleSortChange} />
|
|
||||||
</div>
|
|
||||||
<div className="col-auto">{this.searchForm()}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="table-responsive">
|
|
||||||
<table
|
|
||||||
id="community_table"
|
|
||||||
className="table table-sm table-hover"
|
|
||||||
>
|
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{I18NextService.i18n.t("name")}</th>
|
<th>{I18NextService.i18n.t("name")}</th>
|
||||||
|
@ -188,8 +169,7 @@ export class Communities extends Component<
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{this.state.listCommunitiesResponse.data.communities.map(
|
{this.state.listCommunitiesResponse.data.communities.map(cv => (
|
||||||
cv => (
|
|
||||||
<tr key={cv.community.id}>
|
<tr key={cv.community.id}>
|
||||||
<td>
|
<td>
|
||||||
<CommunityLink community={cv.community} />
|
<CommunityLink community={cv.community} />
|
||||||
|
@ -229,33 +209,52 @@ export class Communities extends Component<
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
),
|
))}
|
||||||
)}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
|
||||||
<Paginator
|
|
||||||
page={page}
|
|
||||||
onChange={this.handlePageChange}
|
|
||||||
nextDisabled={
|
|
||||||
communityLimit >
|
|
||||||
this.state.listCommunitiesResponse.data.communities.length
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { listingType, sort, page } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="communities container-lg">
|
<div className="communities container-lg">
|
||||||
<HtmlTags
|
<HtmlTags
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
{this.renderListings()}
|
<div>
|
||||||
|
<h1 className="h4 mb-4">
|
||||||
|
{I18NextService.i18n.t("list_of_communities")}
|
||||||
|
</h1>
|
||||||
|
<div className="row g-3 align-items-center mb-2">
|
||||||
|
<div className="col-auto">
|
||||||
|
<ListingTypeSelect
|
||||||
|
type_={listingType}
|
||||||
|
showLocal={showLocal(this.isoData)}
|
||||||
|
showSubscribed
|
||||||
|
onChange={this.handleListingTypeChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="col-auto me-auto">
|
||||||
|
<SortSelect sort={sort} onChange={this.handleSortChange} />
|
||||||
|
</div>
|
||||||
|
<div className="col-auto">{this.searchForm()}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="table-responsive">{this.renderListingsTable()}</div>
|
||||||
|
<Paginator
|
||||||
|
page={page}
|
||||||
|
onChange={this.handlePageChange}
|
||||||
|
nextDisabled={
|
||||||
|
this.state.listCommunitiesResponse.state !== "success" ||
|
||||||
|
communityLimit >
|
||||||
|
this.state.listCommunitiesResponse.data.communities.length
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -287,29 +286,23 @@ export class Communities extends Component<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUrl({ listingType, sort, page }: Partial<CommunitiesProps>) {
|
async updateUrl(props: Partial<CommunitiesProps>) {
|
||||||
const {
|
const { listingType, sort, page } = { ...this.props, ...props };
|
||||||
listingType: urlListingType,
|
|
||||||
sort: urlSort,
|
|
||||||
page: urlPage,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const queryParams: QueryParams<CommunitiesProps> = {
|
const queryParams: QueryParams<CommunitiesProps> = {
|
||||||
listingType: listingType ?? urlListingType,
|
listingType: listingType,
|
||||||
sort: sort ?? urlSort,
|
sort: sort,
|
||||||
page: (page ?? urlPage)?.toString(),
|
page: page?.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.history.push(`/communities${getQueryString(queryParams)}`);
|
this.props.history.push(`/communities${getQueryString(queryParams)}`);
|
||||||
|
|
||||||
await this.refetch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePageChange(page: number) {
|
handlePageChange(page: number) {
|
||||||
this.updateUrl({ page });
|
this.updateUrl({ page });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortChange(val: SortType) {
|
handleSortChange(val: PostSortType) {
|
||||||
this.updateUrl({ sort: val, page: 1 });
|
this.updateUrl({ sort: val, page: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,19 +361,19 @@ export class Communities extends Component<
|
||||||
data.i.findAndUpdateCommunity(res);
|
data.i.findAndUpdateCommunity(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
async refetch() {
|
fetchToken?: symbol;
|
||||||
|
async refetch({ listingType, sort, page }: CommunitiesProps) {
|
||||||
|
const token = (this.fetchToken = Symbol());
|
||||||
this.setState({ listCommunitiesResponse: LOADING_REQUEST });
|
this.setState({ listCommunitiesResponse: LOADING_REQUEST });
|
||||||
|
const listCommunitiesResponse = await HttpService.client.listCommunities({
|
||||||
const { listingType, sort, page } = this.props;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
listCommunitiesResponse: await HttpService.client.listCommunities({
|
|
||||||
type_: listingType,
|
type_: listingType,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
limit: communityLimit,
|
limit: communityLimit,
|
||||||
page,
|
page,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchToken) {
|
||||||
|
this.setState({ listCommunitiesResponse });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findAndUpdateCommunity(res: RequestState<CommunityResponse>) {
|
findAndUpdateCommunity(res: RequestState<CommunityResponse>) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { ImageUploadForm } from "../common/image-upload-form";
|
||||||
import { LanguageSelect } from "../common/language-select";
|
import { LanguageSelect } from "../common/language-select";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
import { tippyMixin } from "../mixins/tippy-mixin";
|
import { tippyMixin } from "../mixins/tippy-mixin";
|
||||||
|
import { validActorRegexPattern } from "../../config";
|
||||||
|
|
||||||
interface CommunityFormProps {
|
interface CommunityFormProps {
|
||||||
community_view?: CommunityView; // If a community is given, that means this is an edit
|
community_view?: CommunityView; // If a community is given, that means this is an edit
|
||||||
|
@ -129,7 +130,7 @@ export class CommunityForm extends Component<
|
||||||
onInput={linkEvent(this, this.handleCommunityNameChange)}
|
onInput={linkEvent(this, this.handleCommunityNameChange)}
|
||||||
required
|
required
|
||||||
minLength={3}
|
minLength={3}
|
||||||
pattern="[a-z0-9_]+"
|
pattern={validActorRegexPattern}
|
||||||
title={I18NextService.i18n.t("community_reqs")}
|
title={I18NextService.i18n.t("community_reqs")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class CommunityLink extends Component<CommunityLinkProps, any> {
|
||||||
|
|
||||||
const title = useApubName
|
const title = useApubName
|
||||||
? community.name
|
? community.name
|
||||||
: community.title ?? community.name;
|
: (community.title ?? community.name);
|
||||||
|
|
||||||
if (local) {
|
if (local) {
|
||||||
link = `/c/${community.name}`;
|
link = `/c/${community.name}`;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import {
|
import {
|
||||||
commentsToFlatNodes,
|
commentsToFlatNodes,
|
||||||
|
commentToPostSortType,
|
||||||
communityRSSUrl,
|
communityRSSUrl,
|
||||||
editComment,
|
editComment,
|
||||||
editPost,
|
editPost,
|
||||||
editWith,
|
editWith,
|
||||||
enableDownvotes,
|
enableDownvotes,
|
||||||
enableNsfw,
|
enableNsfw,
|
||||||
getCommentParentId,
|
|
||||||
getDataTypeString,
|
getDataTypeString,
|
||||||
postToCommentSortType,
|
postToCommentSortType,
|
||||||
setIsoData,
|
setIsoData,
|
||||||
|
@ -19,11 +19,18 @@ import {
|
||||||
getQueryParams,
|
getQueryParams,
|
||||||
getQueryString,
|
getQueryString,
|
||||||
resourcesSettled,
|
resourcesSettled,
|
||||||
|
bareRoutePush,
|
||||||
} from "@utils/helpers";
|
} from "@utils/helpers";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
import type { QueryParams, StringBoolean } from "@utils/types";
|
import type { QueryParams, StringBoolean } from "@utils/types";
|
||||||
import { RouteDataResponse } from "@utils/types";
|
import { RouteDataResponse } from "@utils/types";
|
||||||
import { Component, RefObject, createRef, linkEvent } from "inferno";
|
import {
|
||||||
|
Component,
|
||||||
|
InfernoNode,
|
||||||
|
RefObject,
|
||||||
|
createRef,
|
||||||
|
linkEvent,
|
||||||
|
} from "inferno";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import {
|
import {
|
||||||
AddAdmin,
|
AddAdmin,
|
||||||
|
@ -35,7 +42,6 @@ import {
|
||||||
BanPersonResponse,
|
BanPersonResponse,
|
||||||
BlockCommunity,
|
BlockCommunity,
|
||||||
BlockPerson,
|
BlockPerson,
|
||||||
CommentId,
|
|
||||||
CommentReplyResponse,
|
CommentReplyResponse,
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
CommunityResponse,
|
CommunityResponse,
|
||||||
|
@ -76,9 +82,10 @@ import {
|
||||||
RemovePost,
|
RemovePost,
|
||||||
SaveComment,
|
SaveComment,
|
||||||
SavePost,
|
SavePost,
|
||||||
SortType,
|
PostSortType,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
|
CommentSortType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit, relTags } from "../../config";
|
import { fetchLimit, relTags } from "../../config";
|
||||||
import {
|
import {
|
||||||
|
@ -100,7 +107,7 @@ import { CommentNodes } from "../comment/comment-nodes";
|
||||||
import { BannerIconHeader } from "../common/banner-icon-header";
|
import { BannerIconHeader } from "../common/banner-icon-header";
|
||||||
import { DataTypeSelect } from "../common/data-type-select";
|
import { DataTypeSelect } from "../common/data-type-select";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon } from "../common/icon";
|
||||||
import { SortSelect } from "../common/sort-select";
|
import { SortSelect } from "../common/sort-select";
|
||||||
import { SiteSidebar } from "../home/site-sidebar";
|
import { SiteSidebar } from "../home/site-sidebar";
|
||||||
import { PostListings } from "../post/post-listings";
|
import { PostListings } from "../post/post-listings";
|
||||||
|
@ -114,6 +121,9 @@ import {
|
||||||
import { Sidebar } from "./sidebar";
|
import { Sidebar } from "./sidebar";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import PostHiddenSelect from "../common/post-hidden-select";
|
import PostHiddenSelect from "../common/post-hidden-select";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import { LoadingEllipses } from "../common/loading-ellipses";
|
||||||
|
import { CommentSortSelect } from "../common/comment-sort-select";
|
||||||
|
|
||||||
type CommunityData = RouteDataResponse<{
|
type CommunityData = RouteDataResponse<{
|
||||||
communityRes: GetCommunityResponse;
|
communityRes: GetCommunityResponse;
|
||||||
|
@ -127,18 +137,17 @@ interface State {
|
||||||
commentsRes: RequestState<GetCommentsResponse>;
|
commentsRes: RequestState<GetCommentsResponse>;
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
showSidebarMobile: boolean;
|
showSidebarMobile: boolean;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
isIsomorphic: boolean;
|
isIsomorphic: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CommunityProps {
|
interface CommunityProps {
|
||||||
dataType: DataType;
|
dataType: DataType;
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
pageCursor?: PaginationCursor;
|
pageCursor?: PaginationCursor;
|
||||||
showHidden?: StringBoolean;
|
showHidden?: StringBoolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fallbacks = { sort: SortType };
|
type Fallbacks = { sort: PostSortType };
|
||||||
|
|
||||||
export function getCommunityQueryParams(
|
export function getCommunityQueryParams(
|
||||||
source: string | undefined,
|
source: string | undefined,
|
||||||
|
@ -156,7 +165,8 @@ export function getCommunityQueryParams(
|
||||||
},
|
},
|
||||||
source,
|
source,
|
||||||
{
|
{
|
||||||
sort: local_user?.default_sort_type ?? local_site.default_sort_type,
|
sort:
|
||||||
|
local_user?.default_post_sort_type ?? local_site.default_post_sort_type,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -165,12 +175,11 @@ function getDataTypeFromQuery(type?: string): DataType {
|
||||||
return type ? DataType[type] : DataType.Post;
|
return type ? DataType[type] : DataType.Post;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSortTypeFromQuery(type?: string): SortType {
|
function getSortTypeFromQuery(
|
||||||
const mySortType =
|
type: string | undefined,
|
||||||
UserService.Instance.myUserInfo?.local_user_view.local_user
|
fallback: PostSortType,
|
||||||
.default_sort_type;
|
): PostSortType {
|
||||||
|
return type ? (type as PostSortType) : fallback;
|
||||||
return type ? (type as SortType) : mySortType ?? "Active";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommunityPathProps = { name: string };
|
type CommunityPathProps = { name: string };
|
||||||
|
@ -192,7 +201,6 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
commentsRes: EMPTY_REQUEST,
|
commentsRes: EMPTY_REQUEST,
|
||||||
siteRes: this.isoData.site_res,
|
siteRes: this.isoData.site_res,
|
||||||
showSidebarMobile: false,
|
showSidebarMobile: false,
|
||||||
finished: new Map(),
|
|
||||||
isIsomorphic: false,
|
isIsomorphic: false,
|
||||||
};
|
};
|
||||||
private readonly mainContentRef: RefObject<HTMLElement>;
|
private readonly mainContentRef: RefObject<HTMLElement>;
|
||||||
|
@ -210,6 +218,7 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleSortChange = this.handleSortChange.bind(this);
|
this.handleSortChange = this.handleSortChange.bind(this);
|
||||||
|
this.handleCommentSortChange = this.handleCommentSortChange.bind(this);
|
||||||
this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
|
this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
|
||||||
this.handlePageNext = this.handlePageNext.bind(this);
|
this.handlePageNext = this.handlePageNext.bind(this);
|
||||||
this.handlePagePrev = this.handlePagePrev.bind(this);
|
this.handlePagePrev = this.handlePagePrev.bind(this);
|
||||||
|
@ -265,21 +274,39 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchCommunity() {
|
fetchCommunityToken?: symbol;
|
||||||
|
async fetchCommunity(props: CommunityRouteProps) {
|
||||||
|
const token = (this.fetchCommunityToken = Symbol());
|
||||||
this.setState({ communityRes: LOADING_REQUEST });
|
this.setState({ communityRes: LOADING_REQUEST });
|
||||||
this.setState({
|
const communityRes = await HttpService.client.getCommunity({
|
||||||
communityRes: await HttpService.client.getCommunity({
|
name: props.match.params.name,
|
||||||
name: this.props.match.params.name,
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchCommunityToken) {
|
||||||
|
this.setState({ communityRes });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await Promise.all([this.fetchCommunity(), this.fetchData()]);
|
await Promise.all([
|
||||||
|
this.fetchCommunity(this.props),
|
||||||
|
this.fetchData(this.props),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(
|
||||||
|
nextProps: CommunityRouteProps & { children?: InfernoNode },
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
bareRoutePush(this.props, nextProps) ||
|
||||||
|
this.props.match.params.name !== nextProps.match.params.name
|
||||||
|
) {
|
||||||
|
this.fetchCommunity(nextProps);
|
||||||
|
}
|
||||||
|
this.fetchData(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
static async fetchInitialData({
|
static async fetchInitialData({
|
||||||
headers,
|
headers,
|
||||||
query: { dataType, pageCursor, sort, showHidden },
|
query: { dataType, pageCursor, sort, showHidden },
|
||||||
|
@ -356,18 +383,12 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCommunity() {
|
renderCommunity() {
|
||||||
switch (this.state.communityRes.state) {
|
const res =
|
||||||
case "loading":
|
this.state.communityRes.state === "success" &&
|
||||||
return (
|
this.state.communityRes.data;
|
||||||
<h5>
|
|
||||||
<Spinner large />
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
case "success": {
|
|
||||||
const res = this.state.communityRes.data;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{res && (
|
||||||
<HtmlTags
|
<HtmlTags
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
|
@ -375,13 +396,9 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
description={res.community_view.community.description}
|
description={res.community_view.community.description}
|
||||||
image={res.community_view.community.icon}
|
image={res.community_view.community.icon}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="row">
|
{this.communityInfo()}
|
||||||
<main
|
|
||||||
className="col-12 col-md-8 col-lg-9"
|
|
||||||
ref={this.mainContentRef}
|
|
||||||
>
|
|
||||||
{this.communityInfo(res)}
|
|
||||||
<div className="d-block d-md-none">
|
<div className="d-block d-md-none">
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary d-inline-block mb-2 me-3"
|
className="btn btn-secondary d-inline-block mb-2 me-3"
|
||||||
|
@ -390,39 +407,43 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
{I18NextService.i18n.t("sidebar")}{" "}
|
{I18NextService.i18n.t("sidebar")}{" "}
|
||||||
<Icon
|
<Icon
|
||||||
icon={
|
icon={
|
||||||
this.state.showSidebarMobile
|
this.state.showSidebarMobile ? `minus-square` : `plus-square`
|
||||||
? `minus-square`
|
|
||||||
: `plus-square`
|
|
||||||
}
|
}
|
||||||
classes="icon-inline"
|
classes="icon-inline"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
{this.state.showSidebarMobile && this.sidebar(res)}
|
{this.state.showSidebarMobile && this.sidebar()}
|
||||||
</div>
|
</div>
|
||||||
{this.selects(res)}
|
</>
|
||||||
{this.listings(res)}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="community container-lg">
|
||||||
|
<div className="row">
|
||||||
|
<main className="col-12 col-md-8 col-lg-9" ref={this.mainContentRef}>
|
||||||
|
{this.renderCommunity()}
|
||||||
|
{this.selects()}
|
||||||
|
{this.listings()}
|
||||||
<PaginatorCursor
|
<PaginatorCursor
|
||||||
nextPage={this.getNextPage}
|
nextPage={this.getNextPage}
|
||||||
onNext={this.handlePageNext}
|
onNext={this.handlePageNext}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<aside className="d-none d-md-block col-md-4 col-lg-3">
|
<aside className="d-none d-md-block col-md-4 col-lg-3">
|
||||||
{this.sidebar(res)}
|
{this.sidebar()}
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="community container-lg">{this.renderCommunity()}</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sidebar(res: GetCommunityResponse) {
|
sidebar() {
|
||||||
|
if (this.state.communityRes.state !== "success") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const res = this.state.communityRes.data;
|
||||||
const siteRes = this.isoData.site_res;
|
const siteRes = this.isoData.site_res;
|
||||||
// For some reason, this returns an empty vec if it matches the site langs
|
// For some reason, this returns an empty vec if it matches the site langs
|
||||||
const communityLangs =
|
const communityLangs =
|
||||||
|
@ -456,7 +477,7 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
listings(communityRes: GetCommunityResponse) {
|
listings() {
|
||||||
const { dataType } = this.props;
|
const { dataType } = this.props;
|
||||||
const siteRes = this.isoData.site_res;
|
const siteRes = this.isoData.site_res;
|
||||||
|
|
||||||
|
@ -468,7 +489,6 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
return (
|
return (
|
||||||
<PostListings
|
<PostListings
|
||||||
posts={this.state.postsRes.data.posts}
|
posts={this.state.postsRes.data.posts}
|
||||||
removeDuplicates
|
|
||||||
enableDownvotes={enableDownvotes(siteRes)}
|
enableDownvotes={enableDownvotes(siteRes)}
|
||||||
voteDisplayMode={voteDisplayMode(siteRes)}
|
voteDisplayMode={voteDisplayMode(siteRes)}
|
||||||
enableNsfw={enableNsfw(siteRes)}
|
enableNsfw={enableNsfw(siteRes)}
|
||||||
|
@ -496,6 +516,9 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (this.state.communityRes.state !== "success") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (this.state.commentsRes.state) {
|
switch (this.state.commentsRes.state) {
|
||||||
case "loading":
|
case "loading":
|
||||||
return <CommentsLoadingSkeleton />;
|
return <CommentsLoadingSkeleton />;
|
||||||
|
@ -504,12 +527,11 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={commentsToFlatNodes(this.state.commentsRes.data.comments)}
|
nodes={commentsToFlatNodes(this.state.commentsRes.data.comments)}
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
finished={this.state.finished}
|
|
||||||
isTopLevel
|
isTopLevel
|
||||||
showContext
|
showContext
|
||||||
enableDownvotes={enableDownvotes(siteRes)}
|
enableDownvotes={enableDownvotes(siteRes)}
|
||||||
voteDisplayMode={voteDisplayMode(siteRes)}
|
voteDisplayMode={voteDisplayMode(siteRes)}
|
||||||
moderators={communityRes.moderators}
|
moderators={this.state.communityRes.data.moderators}
|
||||||
admins={siteRes.admins}
|
admins={siteRes.admins}
|
||||||
allLanguages={siteRes.all_languages}
|
allLanguages={siteRes.all_languages}
|
||||||
siteLanguages={siteRes.discussion_languages}
|
siteLanguages={siteRes.discussion_languages}
|
||||||
|
@ -537,28 +559,40 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
communityInfo(res: GetCommunityResponse) {
|
communityInfo() {
|
||||||
const community = res.community_view.community;
|
const res =
|
||||||
|
(this.state.communityRes.state === "success" &&
|
||||||
|
this.state.communityRes.data) ||
|
||||||
|
undefined;
|
||||||
|
const community = res && res.community_view.community;
|
||||||
|
const urlCommunityName = this.props.match.params.name;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
community && (
|
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
|
{community && (
|
||||||
<BannerIconHeader banner={community.banner} icon={community.icon} />
|
<BannerIconHeader banner={community.banner} icon={community.icon} />
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<h1
|
<h1
|
||||||
className="h4 mb-0 overflow-wrap-anywhere d-inline"
|
className="h4 mb-0 overflow-wrap-anywhere d-inline"
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
community.posting_restricted_to_mods
|
community?.posting_restricted_to_mods
|
||||||
? I18NextService.i18n.t("community_locked")
|
? I18NextService.i18n.t("community_locked")
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{community.title}
|
{community?.title ?? (
|
||||||
|
<>
|
||||||
|
{urlCommunityName}
|
||||||
|
<LoadingEllipses />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
{community.posting_restricted_to_mods && (
|
{community?.posting_restricted_to_mods && (
|
||||||
<Icon icon="lock" inline classes="text-danger fs-4 ms-2" />
|
<Icon icon="lock" inline classes="text-danger fs-4 ms-2" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{(community && (
|
||||||
<CommunityLink
|
<CommunityLink
|
||||||
community={community}
|
community={community}
|
||||||
realLink
|
realLink
|
||||||
|
@ -566,12 +600,16 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
muted
|
muted
|
||||||
hideAvatar
|
hideAvatar
|
||||||
/>
|
/>
|
||||||
|
)) ??
|
||||||
|
urlCommunityName}
|
||||||
</div>
|
</div>
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
selects(res: GetCommunityResponse) {
|
selects() {
|
||||||
|
const res =
|
||||||
|
this.state.communityRes.state === "success" &&
|
||||||
|
this.state.communityRes.data;
|
||||||
const { dataType, sort, showHidden } = this.props;
|
const { dataType, sort, showHidden } = this.props;
|
||||||
const communityRss = res
|
const communityRss = res
|
||||||
? communityRSSUrl(res.community_view.community.actor_id, sort)
|
? communityRSSUrl(res.community_view.community.actor_id, sort)
|
||||||
|
@ -594,7 +632,14 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<span className="me-2">
|
<span className="me-2">
|
||||||
|
{this.props.dataType === DataType.Post ? (
|
||||||
<SortSelect sort={sort} onChange={this.handleSortChange} />
|
<SortSelect sort={sort} onChange={this.handleSortChange} />
|
||||||
|
) : (
|
||||||
|
<CommentSortSelect
|
||||||
|
sort={postToCommentSortType(sort)}
|
||||||
|
onChange={this.handleCommentSortChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
{communityRss && (
|
{communityRss && (
|
||||||
<>
|
<>
|
||||||
|
@ -620,8 +665,18 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
this.updateUrl({ pageCursor: nextPage });
|
this.updateUrl({ pageCursor: nextPage });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortChange(sort: SortType) {
|
handleSortChange(sort: PostSortType) {
|
||||||
this.updateUrl({ sort, pageCursor: undefined });
|
this.updateUrl({
|
||||||
|
sort: sort,
|
||||||
|
pageCursor: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCommentSortChange(sort: CommentSortType) {
|
||||||
|
this.updateUrl({
|
||||||
|
sort: commentToPostSortType(sort),
|
||||||
|
pageCursor: undefined,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDataTypeChange(dataType: DataType) {
|
handleDataTypeChange(dataType: DataType) {
|
||||||
|
@ -641,40 +696,39 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUrl({
|
async updateUrl(props: Partial<CommunityProps>) {
|
||||||
|
const {
|
||||||
dataType,
|
dataType,
|
||||||
pageCursor,
|
pageCursor,
|
||||||
sort,
|
sort,
|
||||||
showHidden,
|
showHidden,
|
||||||
}: Partial<CommunityProps>) {
|
match: {
|
||||||
const {
|
params: { name },
|
||||||
dataType: urlDataType,
|
},
|
||||||
sort: urlSort,
|
} = {
|
||||||
showHidden: urlShowHidden,
|
...this.props,
|
||||||
} = this.props;
|
...props,
|
||||||
|
|
||||||
const queryParams: QueryParams<CommunityProps> = {
|
|
||||||
dataType: getDataTypeString(dataType ?? urlDataType),
|
|
||||||
pageCursor: pageCursor,
|
|
||||||
sort: sort ?? urlSort,
|
|
||||||
showHidden: showHidden ?? urlShowHidden,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.history.push(
|
const queryParams: QueryParams<CommunityProps> = {
|
||||||
`/c/${this.props.match.params.name}${getQueryString(queryParams)}`,
|
dataType: getDataTypeString(dataType ?? DataType.Post),
|
||||||
);
|
pageCursor: pageCursor,
|
||||||
|
sort: sort,
|
||||||
|
showHidden: showHidden,
|
||||||
|
};
|
||||||
|
|
||||||
await this.fetchData();
|
this.props.history.push(`/c/${name}${getQueryString(queryParams)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchData() {
|
fetchDataToken?: symbol;
|
||||||
const { dataType, pageCursor, sort, showHidden } = this.props;
|
async fetchData(props: CommunityRouteProps) {
|
||||||
const { name } = this.props.match.params;
|
const token = (this.fetchDataToken = Symbol());
|
||||||
|
const { dataType, pageCursor, sort, showHidden } = props;
|
||||||
|
const { name } = props.match.params;
|
||||||
|
|
||||||
if (dataType === DataType.Post) {
|
if (dataType === DataType.Post) {
|
||||||
this.setState({ postsRes: LOADING_REQUEST });
|
this.setState({ postsRes: LOADING_REQUEST, commentsRes: EMPTY_REQUEST });
|
||||||
this.setState({
|
const postsRes = await HttpService.client.getPosts({
|
||||||
postsRes: await HttpService.client.getPosts({
|
|
||||||
page_cursor: pageCursor,
|
page_cursor: pageCursor,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
sort,
|
sort,
|
||||||
|
@ -682,19 +736,22 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
community_name: name,
|
community_name: name,
|
||||||
saved_only: false,
|
saved_only: false,
|
||||||
show_hidden: showHidden === "true",
|
show_hidden: showHidden === "true",
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchDataToken) {
|
||||||
|
this.setState({ postsRes });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setState({ commentsRes: LOADING_REQUEST });
|
this.setState({ commentsRes: LOADING_REQUEST, postsRes: EMPTY_REQUEST });
|
||||||
this.setState({
|
const commentsRes = await HttpService.client.getComments({
|
||||||
commentsRes: await HttpService.client.getComments({
|
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
sort: postToCommentSortType(sort),
|
sort: postToCommentSortType(sort),
|
||||||
type_: "All",
|
type_: "All",
|
||||||
community_name: name,
|
community_name: name,
|
||||||
saved_only: false,
|
saved_only: false,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchDataToken) {
|
||||||
|
this.setState({ commentsRes });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,6 +835,9 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
const createCommentRes = await HttpService.client.createComment(form);
|
const createCommentRes = await HttpService.client.createComment(form);
|
||||||
this.createAndUpdateComments(createCommentRes);
|
this.createAndUpdateComments(createCommentRes);
|
||||||
|
|
||||||
|
if (createCommentRes.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(createCommentRes.err.message), "danger");
|
||||||
|
}
|
||||||
return createCommentRes;
|
return createCommentRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,6 +845,9 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
const editCommentRes = await HttpService.client.editComment(form);
|
const editCommentRes = await HttpService.client.editComment(form);
|
||||||
this.findAndUpdateCommentEdit(editCommentRes);
|
this.findAndUpdateCommentEdit(editCommentRes);
|
||||||
|
|
||||||
|
if (editCommentRes.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(editCommentRes.err.message), "danger");
|
||||||
|
}
|
||||||
return editCommentRes;
|
return editCommentRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,7 +1059,6 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
res.data.comment_view,
|
res.data.comment_view,
|
||||||
s.commentsRes.data.comments,
|
s.commentsRes.data.comments,
|
||||||
);
|
);
|
||||||
s.finished.set(res.data.comment_view.comment.id, true);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
@ -1018,12 +1080,6 @@ export class Community extends Component<CommunityRouteProps, State> {
|
||||||
this.setState(s => {
|
this.setState(s => {
|
||||||
if (s.commentsRes.state === "success" && res.state === "success") {
|
if (s.commentsRes.state === "success" && res.state === "success") {
|
||||||
s.commentsRes.data.comments.unshift(res.data.comment_view);
|
s.commentsRes.data.comments.unshift(res.data.comment_view);
|
||||||
|
|
||||||
// Set finished for the parent
|
|
||||||
s.finished.set(
|
|
||||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
|
|
@ -80,6 +80,21 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
this.handleEditCancel = this.handleEditCancel.bind(this);
|
this.handleEditCancel = this.handleEditCancel.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlisten = () => {};
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
// Leave edit mode on navigation
|
||||||
|
this.unlisten = this.context.router.history.listen(() => {
|
||||||
|
if (this.state.showEdit) {
|
||||||
|
this.setState({ showEdit: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
this.unlisten();
|
||||||
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(
|
componentWillReceiveProps(
|
||||||
nextProps: Readonly<{ children?: InfernoNode } & SidebarProps>,
|
nextProps: Readonly<{ children?: InfernoNode } & SidebarProps>,
|
||||||
): void {
|
): void {
|
||||||
|
|
|
@ -3,12 +3,12 @@ import { capitalizeFirstLetter, resourcesSettled } from "@utils/helpers";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
import { RouteDataResponse } from "@utils/types";
|
import { RouteDataResponse } from "@utils/types";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component } from "inferno";
|
||||||
import {
|
import {
|
||||||
BannedPersonsResponse,
|
BannedPersonsResponse,
|
||||||
CreateCustomEmoji,
|
CreateOAuthProvider,
|
||||||
DeleteCustomEmoji,
|
DeleteOAuthProvider,
|
||||||
EditCustomEmoji,
|
EditOAuthProvider,
|
||||||
EditSite,
|
EditSite,
|
||||||
GetFederatedInstancesResponse,
|
GetFederatedInstancesResponse,
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
|
@ -17,7 +17,6 @@ import {
|
||||||
PersonView,
|
PersonView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { removeFromEmojiDataModel, updateEmojiDataModel } from "../../markdown";
|
|
||||||
import { FirstLoadService, I18NextService } from "../../services";
|
import { FirstLoadService, I18NextService } from "../../services";
|
||||||
import {
|
import {
|
||||||
EMPTY_REQUEST,
|
EMPTY_REQUEST,
|
||||||
|
@ -41,6 +40,9 @@ import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import { MediaUploads } from "../common/media-uploads";
|
import { MediaUploads } from "../common/media-uploads";
|
||||||
import { Paginator } from "../common/paginator";
|
import { Paginator } from "../common/paginator";
|
||||||
import { snapToTop } from "@utils/browser";
|
import { snapToTop } from "@utils/browser";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import ConfirmationModal from "../common/modal/confirmation-modal";
|
||||||
|
import OAuthProvidersTab from "./oauth/oauth-providers-tab";
|
||||||
|
|
||||||
type AdminSettingsData = RouteDataResponse<{
|
type AdminSettingsData = RouteDataResponse<{
|
||||||
bannedRes: BannedPersonsResponse;
|
bannedRes: BannedPersonsResponse;
|
||||||
|
@ -51,10 +53,10 @@ type AdminSettingsData = RouteDataResponse<{
|
||||||
interface AdminSettingsState {
|
interface AdminSettingsState {
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
banned: PersonView[];
|
banned: PersonView[];
|
||||||
currentTab: string;
|
|
||||||
instancesRes: RequestState<GetFederatedInstancesResponse>;
|
instancesRes: RequestState<GetFederatedInstancesResponse>;
|
||||||
bannedRes: RequestState<BannedPersonsResponse>;
|
bannedRes: RequestState<BannedPersonsResponse>;
|
||||||
leaveAdminTeamRes: RequestState<GetSiteResponse>;
|
leaveAdminTeamRes: RequestState<GetSiteResponse>;
|
||||||
|
showConfirmLeaveAdmin: boolean;
|
||||||
uploadsRes: RequestState<ListMediaResponse>;
|
uploadsRes: RequestState<ListMediaResponse>;
|
||||||
uploadsPage: number;
|
uploadsPage: number;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
@ -79,10 +81,10 @@ export class AdminSettings extends Component<
|
||||||
state: AdminSettingsState = {
|
state: AdminSettingsState = {
|
||||||
siteRes: this.isoData.site_res,
|
siteRes: this.isoData.site_res,
|
||||||
banned: [],
|
banned: [],
|
||||||
currentTab: "site",
|
|
||||||
bannedRes: EMPTY_REQUEST,
|
bannedRes: EMPTY_REQUEST,
|
||||||
instancesRes: EMPTY_REQUEST,
|
instancesRes: EMPTY_REQUEST,
|
||||||
leaveAdminTeamRes: EMPTY_REQUEST,
|
leaveAdminTeamRes: EMPTY_REQUEST,
|
||||||
|
showConfirmLeaveAdmin: false,
|
||||||
uploadsRes: EMPTY_REQUEST,
|
uploadsRes: EMPTY_REQUEST,
|
||||||
uploadsPage: 1,
|
uploadsPage: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@ -102,10 +104,13 @@ export class AdminSettings extends Component<
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleEditSite = this.handleEditSite.bind(this);
|
this.handleEditSite = this.handleEditSite.bind(this);
|
||||||
this.handleEditEmoji = this.handleEditEmoji.bind(this);
|
|
||||||
this.handleDeleteEmoji = this.handleDeleteEmoji.bind(this);
|
|
||||||
this.handleCreateEmoji = this.handleCreateEmoji.bind(this);
|
|
||||||
this.handleUploadsPageChange = this.handleUploadsPageChange.bind(this);
|
this.handleUploadsPageChange = this.handleUploadsPageChange.bind(this);
|
||||||
|
this.handleToggleShowLeaveAdminConfirmation =
|
||||||
|
this.handleToggleShowLeaveAdminConfirmation.bind(this);
|
||||||
|
this.handleLeaveAdminTeam = this.handleLeaveAdminTeam.bind(this);
|
||||||
|
this.handleEditOAuthProvider = this.handleEditOAuthProvider.bind(this);
|
||||||
|
this.handleDeleteOAuthProvider = this.handleDeleteOAuthProvider.bind(this);
|
||||||
|
this.handleCreateOAuthProvider = this.handleCreateOAuthProvider.bind(this);
|
||||||
|
|
||||||
// Only fetch the data if coming from another route
|
// Only fetch the data if coming from another route
|
||||||
if (FirstLoadService.isFirstLoad) {
|
if (FirstLoadService.isFirstLoad) {
|
||||||
|
@ -134,7 +139,8 @@ export class AdminSettings extends Component<
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
|
if (isBrowser()) {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic) {
|
||||||
await this.fetchData();
|
await this.fetchData();
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,6 +148,7 @@ export class AdminSettings extends Component<
|
||||||
this.setState({ themeList });
|
this.setState({ themeList });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${I18NextService.i18n.t("admin_settings")} - ${
|
return `${I18NextService.i18n.t("admin_settings")} - ${
|
||||||
|
@ -242,11 +249,7 @@ export class AdminSettings extends Component<
|
||||||
id="taglines-tab-pane"
|
id="taglines-tab-pane"
|
||||||
>
|
>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<TaglineForm
|
<TaglineForm />
|
||||||
taglines={this.state.siteRes.taglines}
|
|
||||||
onSaveSite={this.handleEditSite}
|
|
||||||
loading={this.state.loading}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
@ -263,11 +266,7 @@ export class AdminSettings extends Component<
|
||||||
id="emojis-tab-pane"
|
id="emojis-tab-pane"
|
||||||
>
|
>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<EmojiForm
|
<EmojiForm />
|
||||||
onCreate={this.handleCreateEmoji}
|
|
||||||
onDelete={this.handleDeleteEmoji}
|
|
||||||
onEdit={this.handleEditEmoji}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
@ -287,6 +286,28 @@ export class AdminSettings extends Component<
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "auth",
|
||||||
|
label: I18NextService.i18n.t("authentication"),
|
||||||
|
getNode: isSelected => (
|
||||||
|
<div
|
||||||
|
className={classNames("tab-pane", {
|
||||||
|
active: isSelected,
|
||||||
|
})}
|
||||||
|
role="tabpanel"
|
||||||
|
id="auth-tab-pane"
|
||||||
|
>
|
||||||
|
<OAuthProvidersTab
|
||||||
|
oauthProviders={
|
||||||
|
this.state.siteRes.admin_oauth_providers ?? []
|
||||||
|
}
|
||||||
|
onCreate={this.handleCreateOAuthProvider}
|
||||||
|
onDelete={this.handleDeleteOAuthProvider}
|
||||||
|
onEdit={this.handleEditOAuthProvider}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -339,6 +360,13 @@ export class AdminSettings extends Component<
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
{this.leaveAdmin()}
|
{this.leaveAdmin()}
|
||||||
|
<ConfirmationModal
|
||||||
|
message={I18NextService.i18n.t("leave_admin_team_confirmation")}
|
||||||
|
loadingMessage={I18NextService.i18n.t("leaving_admin_team")}
|
||||||
|
onNo={this.handleToggleShowLeaveAdminConfirmation}
|
||||||
|
onYes={this.handleLeaveAdminTeam}
|
||||||
|
show={this.state.showConfirmLeaveAdmin}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -346,7 +374,7 @@ export class AdminSettings extends Component<
|
||||||
leaveAdmin() {
|
leaveAdmin() {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={linkEvent(this, this.handleLeaveAdminTeam)}
|
onClick={this.handleToggleShowLeaveAdminConfirmation}
|
||||||
className="btn btn-danger mb-2"
|
className="btn btn-danger mb-2"
|
||||||
>
|
>
|
||||||
{this.state.leaveAdminTeamRes.state === "loading" ? (
|
{this.state.leaveAdminTeamRes.state === "loading" ? (
|
||||||
|
@ -417,10 +445,12 @@ export class AdminSettings extends Component<
|
||||||
this.setState(s => {
|
this.setState(s => {
|
||||||
s.siteRes.site_view = editRes.data.site_view;
|
s.siteRes.site_view = editRes.data.site_view;
|
||||||
// TODO: Where to get taglines from?
|
// TODO: Where to get taglines from?
|
||||||
s.siteRes.taglines = editRes.data.taglines;
|
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
toast(I18NextService.i18n.t("site_saved"));
|
toast(I18NextService.i18n.t("site_saved"));
|
||||||
|
|
||||||
|
// You need to reload the page, to properly update the siteRes everywhere
|
||||||
|
setTimeout(() => location.reload(), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
@ -428,46 +458,90 @@ export class AdminSettings extends Component<
|
||||||
return editRes;
|
return editRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSwitchTab(i: { ctx: AdminSettings; tab: string }) {
|
handleToggleShowLeaveAdminConfirmation() {
|
||||||
i.ctx.setState({ currentTab: i.tab });
|
this.setState(prev => ({
|
||||||
|
showConfirmLeaveAdmin: !prev.showConfirmLeaveAdmin,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleLeaveAdminTeam(i: AdminSettings) {
|
async handleLeaveAdminTeam() {
|
||||||
i.setState({ leaveAdminTeamRes: LOADING_REQUEST });
|
this.setState({ leaveAdminTeamRes: LOADING_REQUEST });
|
||||||
this.setState({
|
this.setState({
|
||||||
leaveAdminTeamRes: await HttpService.client.leaveAdmin(),
|
leaveAdminTeamRes: await HttpService.client.leaveAdmin(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.state.leaveAdminTeamRes.state === "success") {
|
if (this.state.leaveAdminTeamRes.state === "success") {
|
||||||
toast(I18NextService.i18n.t("left_admin_team"));
|
toast(I18NextService.i18n.t("left_admin_team"));
|
||||||
|
this.setState({ showConfirmLeaveAdmin: false });
|
||||||
this.context.router.history.replace("/");
|
this.context.router.history.replace("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleEditEmoji(form: EditCustomEmoji) {
|
|
||||||
const res = await HttpService.client.editCustomEmoji(form);
|
|
||||||
if (res.state === "success") {
|
|
||||||
updateEmojiDataModel(res.data.custom_emoji);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async handleDeleteEmoji(form: DeleteCustomEmoji) {
|
|
||||||
const res = await HttpService.client.deleteCustomEmoji(form);
|
|
||||||
if (res.state === "success") {
|
|
||||||
removeFromEmojiDataModel(form.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async handleCreateEmoji(form: CreateCustomEmoji) {
|
|
||||||
const res = await HttpService.client.createCustomEmoji(form);
|
|
||||||
if (res.state === "success") {
|
|
||||||
updateEmojiDataModel(res.data.custom_emoji);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async handleUploadsPageChange(val: number) {
|
async handleUploadsPageChange(val: number) {
|
||||||
this.setState({ uploadsPage: val });
|
this.setState({ uploadsPage: val });
|
||||||
snapToTop();
|
snapToTop();
|
||||||
await this.fetchUploadsOnly();
|
await this.fetchUploadsOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleEditOAuthProvider(form: EditOAuthProvider) {
|
||||||
|
this.setState({ loading: true });
|
||||||
|
|
||||||
|
const res = await HttpService.client.editOAuthProvider(form);
|
||||||
|
|
||||||
|
if (res.state === "success") {
|
||||||
|
const newOAuthProvider = res.data;
|
||||||
|
this.setState(s => {
|
||||||
|
s.siteRes.admin_oauth_providers = (
|
||||||
|
s.siteRes.admin_oauth_providers ?? []
|
||||||
|
).map(p => {
|
||||||
|
return p?.id === newOAuthProvider.id ? newOAuthProvider : p;
|
||||||
|
});
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
toast(I18NextService.i18n.t("site_saved"));
|
||||||
|
} else {
|
||||||
|
toast(I18NextService.i18n.t("couldnt_edit_oauth_provider"), "danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleDeleteOAuthProvider(form: DeleteOAuthProvider) {
|
||||||
|
this.setState({ loading: true });
|
||||||
|
|
||||||
|
const res = await HttpService.client.deleteOAuthProvider(form);
|
||||||
|
|
||||||
|
if (res.state === "success") {
|
||||||
|
this.setState(s => {
|
||||||
|
s.siteRes.admin_oauth_providers = (
|
||||||
|
s.siteRes.admin_oauth_providers ?? []
|
||||||
|
).filter(p => p.id !== form.id);
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
toast(I18NextService.i18n.t("site_saved"));
|
||||||
|
} else {
|
||||||
|
toast(I18NextService.i18n.t("couldnt_delete_oauth_provider"), "danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleCreateOAuthProvider(form: CreateOAuthProvider) {
|
||||||
|
this.setState({ loading: true });
|
||||||
|
|
||||||
|
const res = await HttpService.client.createOAuthProvider(form);
|
||||||
|
if (res.state === "success") {
|
||||||
|
this.setState(s => {
|
||||||
|
s.siteRes.admin_oauth_providers = [
|
||||||
|
...(s.siteRes.admin_oauth_providers ?? []),
|
||||||
|
res.data,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
toast(I18NextService.i18n.t("site_saved"));
|
||||||
|
} else {
|
||||||
|
toast(I18NextService.i18n.t("couldnt_create_oauth_provider"), "danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +1,81 @@
|
||||||
import { setIsoData } from "@utils/app";
|
|
||||||
import { capitalizeFirstLetter } from "@utils/helpers";
|
import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import {
|
import { CustomEmojiView } from "lemmy-js-client";
|
||||||
CreateCustomEmoji,
|
import { emojiMartCategories, EmojiMartCategory } from "../../markdown";
|
||||||
DeleteCustomEmoji,
|
|
||||||
EditCustomEmoji,
|
|
||||||
GetSiteResponse,
|
|
||||||
} from "lemmy-js-client";
|
|
||||||
import { customEmojisLookup } from "../../markdown";
|
|
||||||
import { HttpService, I18NextService } from "../../services";
|
import { HttpService, I18NextService } from "../../services";
|
||||||
import { pictrsDeleteToast, toast } from "../../toast";
|
import { pictrsDeleteToast, toast } from "../../toast";
|
||||||
import { EmojiMart } from "../common/emoji-mart";
|
import { EmojiMart } from "../common/emoji-mart";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { Paginator } from "../common/paginator";
|
import { Paginator } from "../common/paginator";
|
||||||
import { tippyMixin } from "../mixins/tippy-mixin";
|
import { tippyMixin } from "../mixins/tippy-mixin";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { amAdmin } from "@utils/roles";
|
||||||
|
import { Prompt } from "inferno-router";
|
||||||
|
|
||||||
interface EmojiFormProps {
|
interface EditableEmoji {
|
||||||
onEdit(form: EditCustomEmoji): void;
|
change?: "update" | "delete" | "create";
|
||||||
onCreate(form: CreateCustomEmoji): void;
|
emoji: CustomEmojiView;
|
||||||
onDelete(form: DeleteCustomEmoji): void;
|
loading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function markForUpdate(editable: EditableEmoji) {
|
||||||
|
if (editable.change !== "create") {
|
||||||
|
editable.change = "update";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EmojiFormState {
|
interface EmojiFormState {
|
||||||
siteRes: GetSiteResponse;
|
emojis: EditableEmoji[]; // Emojis for the current page
|
||||||
customEmojis: CustomEmojiViewForm[];
|
allEmojis: CustomEmojiView[]; // All emojis for emoji lookup across pages
|
||||||
page: number;
|
emojiMartCustom: EmojiMartCategory[];
|
||||||
}
|
emojiMartKey: number;
|
||||||
|
|
||||||
interface CustomEmojiViewForm {
|
|
||||||
id: number;
|
|
||||||
category: string;
|
|
||||||
shortcode: string;
|
|
||||||
image_url: string;
|
|
||||||
alt_text: string;
|
|
||||||
keywords: string;
|
|
||||||
changed: boolean;
|
|
||||||
page: number;
|
page: number;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@tippyMixin
|
@tippyMixin
|
||||||
export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
|
||||||
private isoData = setIsoData(this.context);
|
|
||||||
private itemsPerPage = 15;
|
private itemsPerPage = 15;
|
||||||
private emptyState: EmojiFormState = {
|
private needsRefetch = true;
|
||||||
siteRes: this.isoData.site_res,
|
state: EmojiFormState = {
|
||||||
customEmojis: this.isoData.site_res.custom_emojis.map((x, index) => ({
|
emojis: [],
|
||||||
id: x.custom_emoji.id,
|
allEmojis: [],
|
||||||
category: x.custom_emoji.category,
|
emojiMartCustom: [],
|
||||||
shortcode: x.custom_emoji.shortcode,
|
emojiMartKey: 1,
|
||||||
image_url: x.custom_emoji.image_url,
|
|
||||||
alt_text: x.custom_emoji.alt_text,
|
|
||||||
keywords: x.keywords.map(x => x.keyword).join(" "),
|
|
||||||
changed: false,
|
|
||||||
page: 1 + Math.floor(index / this.itemsPerPage),
|
|
||||||
loading: false,
|
loading: false,
|
||||||
})),
|
|
||||||
page: 1,
|
page: 1,
|
||||||
};
|
};
|
||||||
state: EmojiFormState;
|
|
||||||
private scrollRef: any = {};
|
private scrollRef: any = {};
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.state = this.emptyState;
|
|
||||||
|
|
||||||
this.handlePageChange = this.handlePageChange.bind(this);
|
this.handlePageChange = this.handlePageChange.bind(this);
|
||||||
this.handleEmojiClick = this.handleEmojiClick.bind(this);
|
this.handleEmojiClick = this.handleEmojiClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async componentWillMount() {
|
||||||
|
if (isBrowser()) {
|
||||||
|
this.handlePageChange(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hasPendingChanges() {
|
||||||
|
return this.state.emojis.some(x => x.change);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="home-emojis-form col-12">
|
<div className="home-emojis-form col-12">
|
||||||
|
<Prompt
|
||||||
|
message={I18NextService.i18n.t("block_leaving")}
|
||||||
|
when={this.hasPendingChanges()}
|
||||||
|
/>
|
||||||
<h1 className="h4 mb-4">{I18NextService.i18n.t("custom_emojis")}</h1>
|
<h1 className="h4 mb-4">{I18NextService.i18n.t("custom_emojis")}</h1>
|
||||||
{customEmojisLookup.size > 0 && (
|
{this.state.emojiMartCustom.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<EmojiMart
|
<EmojiMart
|
||||||
|
key={this.state.emojiMartKey}
|
||||||
onEmojiClick={this.handleEmojiClick}
|
onEmojiClick={this.handleEmojiClick}
|
||||||
pickerOptions={this.configurePicker()}
|
pickerOptions={this.configurePicker()}
|
||||||
></EmojiMart>
|
></EmojiMart>
|
||||||
|
@ -87,6 +89,10 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{I18NextService.i18n.t("column_emoji")}</th>
|
<th>{I18NextService.i18n.t("column_emoji")}</th>
|
||||||
|
<th
|
||||||
|
className="text-right"
|
||||||
|
// Upload button
|
||||||
|
/>
|
||||||
<th className="text-right">
|
<th className="text-right">
|
||||||
{I18NextService.i18n.t("column_shortcode")}
|
{I18NextService.i18n.t("column_shortcode")}
|
||||||
</th>
|
</th>
|
||||||
|
@ -102,20 +108,15 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
<th className="text-right d-lg-table-cell">
|
<th className="text-right d-lg-table-cell">
|
||||||
{I18NextService.i18n.t("column_keywords")}
|
{I18NextService.i18n.t("column_keywords")}
|
||||||
</th>
|
</th>
|
||||||
|
<th></th>
|
||||||
<th style="width:121px"></th>
|
<th style="width:121px"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{this.state.customEmojis
|
{this.state.emojis.map((editable: EditableEmoji, index) => {
|
||||||
.slice(
|
const cv = editable.emoji.custom_emoji;
|
||||||
Number((this.state.page - 1) * this.itemsPerPage),
|
return (
|
||||||
Number(
|
<tr key={index}>
|
||||||
(this.state.page - 1) * this.itemsPerPage +
|
|
||||||
this.itemsPerPage,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map((cv, index) => (
|
|
||||||
<tr key={index} ref={e => (this.scrollRef[cv.shortcode] = e)}>
|
|
||||||
<td style="text-align:center;">
|
<td style="text-align:center;">
|
||||||
{cv.image_url.length > 0 && (
|
{cv.image_url.length > 0 && (
|
||||||
<img
|
<img
|
||||||
|
@ -124,7 +125,9 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
alt={cv.alt_text}
|
alt={cv.alt_text}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{cv.image_url.length === 0 && (
|
</td>
|
||||||
|
<td>
|
||||||
|
{
|
||||||
<label
|
<label
|
||||||
// TODO: Fix this linting violation
|
// TODO: Fix this linting violation
|
||||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||||
|
@ -150,7 +153,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
)}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<input
|
<input
|
||||||
|
@ -167,6 +170,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<input
|
<input
|
||||||
|
ref={e => (this.scrollRef[cv.shortcode] = e)}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Category"
|
placeholder="Category"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
|
@ -206,31 +210,54 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Keywords"
|
placeholder="Keywords"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
value={cv.keywords}
|
value={editable.emoji.keywords
|
||||||
|
.map(k => k.keyword)
|
||||||
|
.join(" ")}
|
||||||
onInput={linkEvent(
|
onInput={linkEvent(
|
||||||
{ form: this, index: index },
|
{ form: this, index: index },
|
||||||
this.handleEmojiKeywordChange,
|
this.handleEmojiKeywordChange,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
<td
|
||||||
|
className={classNames("", {
|
||||||
|
"border-info": editable.change === "update",
|
||||||
|
"border-danger": editable.change === "delete",
|
||||||
|
"border-warning": editable.change === "create",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{editable.change === "update" && (
|
||||||
|
<span>
|
||||||
|
<Icon icon="transfer" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{editable.change === "delete" && (
|
||||||
|
<span>
|
||||||
|
<Icon icon="trash" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{editable.change === "create" && (
|
||||||
|
<span>
|
||||||
|
<Icon icon="add" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>
|
<div class="row flex-nowrap g-0">
|
||||||
<span title={this.getEditTooltip(cv)}>
|
<span class="col" title={this.getEditTooltip(editable)}>
|
||||||
<button
|
<button
|
||||||
className={
|
className={classNames("btn btn-link btn-animate", {
|
||||||
(this.canEdit(cv)
|
"text-success": this.canSave(editable),
|
||||||
? "text-success "
|
})}
|
||||||
: "text-muted ") + "btn btn-link btn-animate"
|
|
||||||
}
|
|
||||||
onClick={linkEvent(
|
onClick={linkEvent(
|
||||||
{ i: this, cv: cv },
|
{ i: this, cv: editable },
|
||||||
this.handleEditEmojiClick,
|
this.handleSaveEmojiClick,
|
||||||
)}
|
)}
|
||||||
data-tippy-content={I18NextService.i18n.t("save")}
|
data-tippy-content={I18NextService.i18n.t("save")}
|
||||||
aria-label={I18NextService.i18n.t("save")}
|
aria-label={I18NextService.i18n.t("save")}
|
||||||
disabled={!this.canEdit(cv)}
|
disabled={!this.canSave(editable)}
|
||||||
>
|
>
|
||||||
{cv.loading ? (
|
{editable.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(
|
capitalizeFirstLetter(
|
||||||
|
@ -240,14 +267,14 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="col btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(
|
onClick={linkEvent(
|
||||||
{ i: this, index: index, cv: cv },
|
{ i: this, index: index, cv: editable },
|
||||||
this.handleDeleteEmojiClick,
|
this.handleDeleteEmojiClick,
|
||||||
)}
|
)}
|
||||||
data-tippy-content={I18NextService.i18n.t("delete")}
|
data-tippy-content={I18NextService.i18n.t("delete")}
|
||||||
aria-label={I18NextService.i18n.t("delete")}
|
aria-label={I18NextService.i18n.t("delete")}
|
||||||
disabled={cv.loading}
|
disabled={editable.loading}
|
||||||
title={I18NextService.i18n.t("delete")}
|
title={I18NextService.i18n.t("delete")}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -255,10 +282,28 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
classes="icon-inline text-danger"
|
classes="icon-inline text-danger"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
className={classNames(
|
||||||
|
"col btn btn-link btn-animate",
|
||||||
|
{
|
||||||
|
"text-danger": !!editable.change,
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
onClick={linkEvent(
|
||||||
|
{ i: this, cv: editable },
|
||||||
|
this.handleCancelEmojiClick,
|
||||||
|
)}
|
||||||
|
data-tippy-content={I18NextService.i18n.t("cancel")}
|
||||||
|
aria-label={I18NextService.i18n.t("cancel")}
|
||||||
|
disabled={!editable.change}
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t("cancel")}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br />
|
<br />
|
||||||
|
@ -273,43 +318,91 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
page={this.state.page}
|
page={this.state.page}
|
||||||
onChange={this.handlePageChange}
|
onChange={this.handlePageChange}
|
||||||
nextDisabled={false}
|
nextDisabled={false}
|
||||||
|
disabled={this.hasPendingChanges()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
canEdit(cv: CustomEmojiViewForm) {
|
canSave(cv: EditableEmoji) {
|
||||||
const noEmptyFields =
|
const requiredFields =
|
||||||
cv.alt_text.length > 0 &&
|
cv.emoji.custom_emoji.image_url.length > 0 &&
|
||||||
cv.category.length > 0 &&
|
cv.emoji.custom_emoji.shortcode.length > 0;
|
||||||
cv.image_url.length > 0 &&
|
return requiredFields && !cv.loading;
|
||||||
cv.shortcode.length > 0;
|
|
||||||
const noDuplicateShortCodes =
|
|
||||||
this.state.customEmojis.filter(
|
|
||||||
x => x.shortcode === cv.shortcode && x.id !== cv.id,
|
|
||||||
).length === 0;
|
|
||||||
return noEmptyFields && noDuplicateShortCodes && !cv.loading && cv.changed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditTooltip(cv: CustomEmojiViewForm) {
|
getEditTooltip(cv: EditableEmoji) {
|
||||||
if (this.canEdit(cv)) return I18NextService.i18n.t("save");
|
if (this.canSave(cv)) return I18NextService.i18n.t("save");
|
||||||
else return I18NextService.i18n.t("custom_emoji_save_validation");
|
else return I18NextService.i18n.t("custom_emoji_save_validation");
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePageChange(page: number) {
|
async handlePageChange(page: number) {
|
||||||
this.setState({ page: page });
|
this.setState({ loading: true });
|
||||||
|
let allEmojis: CustomEmojiView[] = this.state.allEmojis;
|
||||||
|
let emojiMartCustom: EmojiMartCategory[] = this.state.emojiMartCustom;
|
||||||
|
let emojiMartKey: number = this.state.emojiMartKey;
|
||||||
|
if (this.needsRefetch) {
|
||||||
|
const emojiRes = await HttpService.client.listCustomEmojis({
|
||||||
|
ignore_page_limits: true,
|
||||||
|
});
|
||||||
|
if (emojiRes.state === "success") {
|
||||||
|
this.needsRefetch = false;
|
||||||
|
allEmojis = emojiRes.data.custom_emojis;
|
||||||
|
allEmojis.sort((a, b) => {
|
||||||
|
const categoryOrder = a.custom_emoji.category.localeCompare(
|
||||||
|
b.custom_emoji.category,
|
||||||
|
);
|
||||||
|
if (categoryOrder === 0) {
|
||||||
|
return a.custom_emoji.shortcode.localeCompare(
|
||||||
|
b.custom_emoji.shortcode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return categoryOrder;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
emojiMartCustom = emojiMartCategories(allEmojis);
|
||||||
|
emojiMartKey++;
|
||||||
|
}
|
||||||
|
if (allEmojis) {
|
||||||
|
const startIndex = (page - 1) * this.itemsPerPage;
|
||||||
|
const emojis = allEmojis
|
||||||
|
.slice(startIndex, startIndex + this.itemsPerPage)
|
||||||
|
.map(x => ({ emoji: structuredClone(x) })); // clone for restore after cancel
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
allEmojis,
|
||||||
|
emojiMartCustom,
|
||||||
|
emojiMartKey,
|
||||||
|
emojis,
|
||||||
|
page,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({ loading: false, page });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEmojiClick(e: any) {
|
async handleEmojiClick(e: any) {
|
||||||
const view = customEmojisLookup.get(e.id);
|
const emojiIndex = this.state.allEmojis.findIndex(
|
||||||
if (view) {
|
x => x.custom_emoji.shortcode === e.id,
|
||||||
const page = this.state.customEmojis.find(
|
);
|
||||||
x => x.id === view.custom_emoji.id,
|
if (emojiIndex >= 0) {
|
||||||
)?.page;
|
const { shortcode } = this.state.allEmojis[emojiIndex].custom_emoji;
|
||||||
if (page) {
|
const page = Math.floor(emojiIndex / this.itemsPerPage) + 1;
|
||||||
this.setState({ page: page });
|
if (page !== this.state.page) {
|
||||||
this.scrollRef[view.custom_emoji.shortcode].scrollIntoView();
|
if (
|
||||||
|
this.hasPendingChanges() &&
|
||||||
|
!confirm(I18NextService.i18n.t("block_leaving"))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.handlePageChange(page);
|
||||||
|
await new Promise(r => setTimeout(r));
|
||||||
|
}
|
||||||
|
if (shortcode) {
|
||||||
|
const categoryInput: HTMLInputElement | undefined =
|
||||||
|
this.scrollRef[shortcode];
|
||||||
|
categoryInput?.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,32 +411,22 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
props: { form: EmojiForm; index: number },
|
props: { form: EmojiForm; index: number },
|
||||||
event: any,
|
event: any,
|
||||||
) {
|
) {
|
||||||
const custom_emojis = [...props.form.state.customEmojis];
|
const editable: EditableEmoji = props.form.state.emojis[props.index];
|
||||||
const pagedIndex =
|
props.form.setState(() => {
|
||||||
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
|
markForUpdate(editable);
|
||||||
const item = {
|
editable.emoji.custom_emoji.category = event.target.value;
|
||||||
...props.form.state.customEmojis[pagedIndex],
|
});
|
||||||
category: event.target.value,
|
|
||||||
changed: true,
|
|
||||||
};
|
|
||||||
custom_emojis[Number(pagedIndex)] = item;
|
|
||||||
props.form.setState({ customEmojis: custom_emojis });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEmojiShortCodeChange(
|
handleEmojiShortCodeChange(
|
||||||
props: { form: EmojiForm; index: number },
|
props: { form: EmojiForm; index: number },
|
||||||
event: any,
|
event: any,
|
||||||
) {
|
) {
|
||||||
const custom_emojis = [...props.form.state.customEmojis];
|
const editable: EditableEmoji = props.form.state.emojis[props.index];
|
||||||
const pagedIndex =
|
props.form.setState(() => {
|
||||||
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
|
markForUpdate(editable);
|
||||||
const item = {
|
editable.emoji.custom_emoji.shortcode = event.target.value;
|
||||||
...props.form.state.customEmojis[pagedIndex],
|
});
|
||||||
shortcode: event.target.value,
|
|
||||||
changed: true,
|
|
||||||
};
|
|
||||||
custom_emojis[Number(pagedIndex)] = item;
|
|
||||||
props.form.setState({ customEmojis: custom_emojis });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEmojiImageUrlChange(
|
handleEmojiImageUrlChange(
|
||||||
|
@ -354,28 +437,11 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
}: { form: EmojiForm; index: number; overrideValue: string | null },
|
}: { form: EmojiForm; index: number; overrideValue: string | null },
|
||||||
event: any,
|
event: any,
|
||||||
) {
|
) {
|
||||||
form.setState(prevState => {
|
const editable: EditableEmoji = form.state.emojis[index];
|
||||||
const custom_emojis = [...form.state.customEmojis];
|
form.setState(() => {
|
||||||
const pagedIndex = (form.state.page - 1) * form.itemsPerPage + index;
|
markForUpdate(editable);
|
||||||
const item = {
|
editable.emoji.custom_emoji.image_url =
|
||||||
...form.state.customEmojis[pagedIndex],
|
overrideValue ?? event.target.value;
|
||||||
image_url: overrideValue ?? event.target.value,
|
|
||||||
changed: true,
|
|
||||||
};
|
|
||||||
custom_emojis[Number(pagedIndex)] = item;
|
|
||||||
return {
|
|
||||||
...prevState,
|
|
||||||
customEmojis: prevState.customEmojis.map((ce, i) =>
|
|
||||||
i === pagedIndex
|
|
||||||
? {
|
|
||||||
...ce,
|
|
||||||
image_url: overrideValue ?? event.target.value,
|
|
||||||
changed: true,
|
|
||||||
loading: false,
|
|
||||||
}
|
|
||||||
: ce,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,98 +449,118 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
props: { form: EmojiForm; index: number },
|
props: { form: EmojiForm; index: number },
|
||||||
event: any,
|
event: any,
|
||||||
) {
|
) {
|
||||||
const custom_emojis = [...props.form.state.customEmojis];
|
const editable: EditableEmoji = props.form.state.emojis[props.index];
|
||||||
const pagedIndex =
|
props.form.setState(() => {
|
||||||
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
|
markForUpdate(editable);
|
||||||
const item = {
|
editable.emoji.custom_emoji.alt_text = event.target.value;
|
||||||
...props.form.state.customEmojis[pagedIndex],
|
});
|
||||||
alt_text: event.target.value,
|
|
||||||
changed: true,
|
|
||||||
};
|
|
||||||
custom_emojis[Number(pagedIndex)] = item;
|
|
||||||
props.form.setState({ customEmojis: custom_emojis });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEmojiKeywordChange(
|
handleEmojiKeywordChange(
|
||||||
props: { form: EmojiForm; index: number },
|
props: { form: EmojiForm; index: number },
|
||||||
event: any,
|
event: any,
|
||||||
) {
|
) {
|
||||||
const custom_emojis = [...props.form.state.customEmojis];
|
const editable: EditableEmoji = props.form.state.emojis[props.index];
|
||||||
const pagedIndex =
|
props.form.setState(() => {
|
||||||
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
|
markForUpdate(editable);
|
||||||
const item = {
|
editable.emoji.keywords = event.target.value
|
||||||
...props.form.state.customEmojis[pagedIndex],
|
.split(" ")
|
||||||
keywords: event.target.value,
|
.map((x: string) => ({ id: -1, keyword: x }));
|
||||||
changed: true,
|
});
|
||||||
};
|
|
||||||
custom_emojis[Number(pagedIndex)] = item;
|
|
||||||
props.form.setState({ customEmojis: custom_emojis });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteEmojiClick(d: {
|
handleDeleteEmojiClick(d: {
|
||||||
i: EmojiForm;
|
i: EmojiForm;
|
||||||
index: number;
|
index: number;
|
||||||
cv: CustomEmojiViewForm;
|
cv: EditableEmoji;
|
||||||
}) {
|
}) {
|
||||||
const pagedIndex = (d.i.state.page - 1) * d.i.itemsPerPage + d.index;
|
if (d.cv.change === "create") {
|
||||||
if (d.cv.id !== 0) {
|
// This drops the entry immediately, other deletes have to be saved.
|
||||||
d.i.props.onDelete({
|
d.i.setState(prev => ({
|
||||||
id: d.cv.id,
|
emojis: prev.emojis.filter(x => x !== d.cv),
|
||||||
});
|
}));
|
||||||
} else {
|
} else {
|
||||||
const custom_emojis = [...d.i.state.customEmojis];
|
d.i.setState(() => {
|
||||||
custom_emojis.splice(Number(pagedIndex), 1);
|
d.cv.change = "delete";
|
||||||
d.i.setState({ customEmojis: custom_emojis });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleEditEmojiClick(d: { i: EmojiForm; cv: CustomEmojiViewForm }) {
|
|
||||||
const keywords = d.cv.keywords
|
|
||||||
.split(" ")
|
|
||||||
.filter(x => x.length > 0) as string[];
|
|
||||||
const uniqueKeywords = Array.from(new Set(keywords));
|
|
||||||
if (d.cv.id !== 0) {
|
|
||||||
d.i.props.onEdit({
|
|
||||||
id: d.cv.id,
|
|
||||||
category: d.cv.category,
|
|
||||||
image_url: d.cv.image_url,
|
|
||||||
alt_text: d.cv.alt_text,
|
|
||||||
keywords: uniqueKeywords,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
d.i.props.onCreate({
|
|
||||||
category: d.cv.category,
|
|
||||||
shortcode: d.cv.shortcode,
|
|
||||||
image_url: d.cv.image_url,
|
|
||||||
alt_text: d.cv.alt_text,
|
|
||||||
keywords: uniqueKeywords,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAddEmojiClick(form: EmojiForm, event: any) {
|
async handleSaveEmojiClick(d: { i: EmojiForm; cv: EditableEmoji }) {
|
||||||
event.preventDefault();
|
d.i.needsRefetch = true;
|
||||||
form.setState(prevState => {
|
const editable = d.cv;
|
||||||
const page =
|
if (editable.change === "update") {
|
||||||
1 + Math.floor(prevState.customEmojis.length / form.itemsPerPage);
|
const resp = await HttpService.client.editCustomEmoji({
|
||||||
const item: CustomEmojiViewForm = {
|
...editable.emoji.custom_emoji,
|
||||||
id: 0,
|
keywords: editable.emoji.keywords.map(x => x.keyword),
|
||||||
shortcode: "",
|
});
|
||||||
alt_text: "",
|
if (resp.state === "success") {
|
||||||
category: "",
|
d.i.setState(() => {
|
||||||
image_url: "",
|
editable.emoji = resp.data.custom_emoji;
|
||||||
keywords: "",
|
editable.change = undefined;
|
||||||
changed: false,
|
});
|
||||||
page: page,
|
}
|
||||||
loading: false,
|
} else if (editable.change === "delete") {
|
||||||
};
|
const resp = await HttpService.client.deleteCustomEmoji(
|
||||||
|
editable.emoji.custom_emoji,
|
||||||
|
);
|
||||||
|
if (resp.state === "success") {
|
||||||
|
d.i.setState(prev => ({
|
||||||
|
emojis: prev.emojis.filter(x => x !== editable),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else if (editable.change === "create") {
|
||||||
|
const resp = await HttpService.client.createCustomEmoji({
|
||||||
|
...editable.emoji.custom_emoji,
|
||||||
|
keywords: editable.emoji.keywords.map(x => x.keyword),
|
||||||
|
});
|
||||||
|
if (resp.state === "success") {
|
||||||
|
d.i.setState(() => {
|
||||||
|
editable.emoji = resp.data.custom_emoji;
|
||||||
|
editable.change = undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleCancelEmojiClick(d: { i: EmojiForm; cv: EditableEmoji }) {
|
||||||
|
if (d.cv.change === "create") {
|
||||||
|
d.i.setState(() => {
|
||||||
return {
|
return {
|
||||||
...prevState,
|
emojis: d.i.state.emojis.filter(x => x !== d.cv),
|
||||||
customEmojis: [...prevState.customEmojis, item],
|
|
||||||
page,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
} else if (d.cv.change === "update" || d.cv.change === "delete") {
|
||||||
|
const original = d.i.state.allEmojis.find(
|
||||||
|
x => x.custom_emoji.id === d.cv.emoji.custom_emoji.id,
|
||||||
|
);
|
||||||
|
if (original) {
|
||||||
|
d.i.setState(() => {
|
||||||
|
d.cv.emoji = structuredClone(original);
|
||||||
|
d.cv.change = undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleAddEmojiClick(form: EmojiForm, event: any) {
|
||||||
|
event.preventDefault();
|
||||||
|
form.setState(prev => {
|
||||||
|
prev.emojis.push({
|
||||||
|
emoji: {
|
||||||
|
custom_emoji: {
|
||||||
|
id: -1,
|
||||||
|
published: "",
|
||||||
|
category: "",
|
||||||
|
shortcode: "",
|
||||||
|
image_url: "",
|
||||||
|
alt_text: "",
|
||||||
|
},
|
||||||
|
keywords: [],
|
||||||
|
},
|
||||||
|
change: "create",
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleImageUpload(
|
handleImageUpload(
|
||||||
|
@ -489,16 +575,15 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
file = event;
|
file = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.setState(prevState => ({
|
const editable = form.state.emojis[index];
|
||||||
...prevState,
|
form.setState(() => {
|
||||||
customEmojis: prevState.customEmojis.map((cv, i) =>
|
editable.loading = true;
|
||||||
i === index ? { ...cv, loading: true } : cv,
|
});
|
||||||
),
|
|
||||||
}));
|
|
||||||
|
|
||||||
HttpService.client.uploadImage({ image: file }).then(res => {
|
HttpService.client.uploadImage({ image: file }).then(res => {
|
||||||
console.log("pictrs upload:");
|
form.setState(() => {
|
||||||
console.log(res);
|
editable.loading = false;
|
||||||
|
});
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
if (res.data.msg === "ok") {
|
if (res.data.msg === "ok") {
|
||||||
pictrsDeleteToast(file.name, res.data.delete_url as string);
|
pictrsDeleteToast(file.name, res.data.delete_url as string);
|
||||||
|
@ -519,10 +604,20 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
configurePicker(): any {
|
configurePicker(): any {
|
||||||
|
const custom = this.state.emojiMartCustom;
|
||||||
|
if (process.env["NODE_ENV"] === "development") {
|
||||||
|
// Once an emoji-mart Picker is initialized with these options, other
|
||||||
|
// instances also only show the custom emojis.
|
||||||
|
console.assert(
|
||||||
|
amAdmin(),
|
||||||
|
"EmojiMart doesn't deal well with differently configured instances.",
|
||||||
|
);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
data: { categories: [], emojis: [], aliases: [] },
|
data: { categories: [], emojis: [], aliases: [] },
|
||||||
maxFrequentRows: 0,
|
maxFrequentRows: 0,
|
||||||
dynamicWidth: true,
|
dynamicWidth: true,
|
||||||
|
custom,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import {
|
import {
|
||||||
commentsToFlatNodes,
|
commentsToFlatNodes,
|
||||||
|
commentToPostSortType,
|
||||||
editComment,
|
editComment,
|
||||||
editPost,
|
editPost,
|
||||||
editWith,
|
editWith,
|
||||||
enableDownvotes,
|
enableDownvotes,
|
||||||
enableNsfw,
|
enableNsfw,
|
||||||
getCommentParentId,
|
|
||||||
getDataTypeString,
|
getDataTypeString,
|
||||||
myAuth,
|
myAuth,
|
||||||
postToCommentSortType,
|
postToCommentSortType,
|
||||||
|
@ -17,15 +17,13 @@ import {
|
||||||
import {
|
import {
|
||||||
getQueryParams,
|
getQueryParams,
|
||||||
getQueryString,
|
getQueryString,
|
||||||
getRandomFromList,
|
|
||||||
resourcesSettled,
|
resourcesSettled,
|
||||||
} from "@utils/helpers";
|
} from "@utils/helpers";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
import { canCreateCommunity } from "@utils/roles";
|
|
||||||
import type { QueryParams, StringBoolean } from "@utils/types";
|
import type { QueryParams, StringBoolean } from "@utils/types";
|
||||||
import { RouteDataResponse } from "@utils/types";
|
import { RouteDataResponse } from "@utils/types";
|
||||||
import { NoOptionI18nKeys } from "i18next";
|
import { NoOptionI18nKeys } from "i18next";
|
||||||
import { Component, MouseEventHandler, linkEvent } from "inferno";
|
import { Component, InfernoNode, MouseEventHandler, linkEvent } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
import {
|
import {
|
||||||
|
@ -36,7 +34,6 @@ import {
|
||||||
BanPerson,
|
BanPerson,
|
||||||
BanPersonResponse,
|
BanPersonResponse,
|
||||||
BlockPerson,
|
BlockPerson,
|
||||||
CommentId,
|
|
||||||
CommentReplyResponse,
|
CommentReplyResponse,
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
CreateComment,
|
CreateComment,
|
||||||
|
@ -57,8 +54,6 @@ import {
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
HidePost,
|
HidePost,
|
||||||
LemmyHttp,
|
LemmyHttp,
|
||||||
ListCommunities,
|
|
||||||
ListCommunitiesResponse,
|
|
||||||
ListingType,
|
ListingType,
|
||||||
LockPost,
|
LockPost,
|
||||||
MarkCommentReplyAsRead,
|
MarkCommentReplyAsRead,
|
||||||
|
@ -72,11 +67,12 @@ import {
|
||||||
RemovePost,
|
RemovePost,
|
||||||
SaveComment,
|
SaveComment,
|
||||||
SavePost,
|
SavePost,
|
||||||
SortType,
|
PostSortType,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
|
CommentSortType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit, relTags, trendingFetchLimit } from "../../config";
|
import { fetchLimit, relTags } from "../../config";
|
||||||
import {
|
import {
|
||||||
CommentViewType,
|
CommentViewType,
|
||||||
DataType,
|
DataType,
|
||||||
|
@ -107,31 +103,28 @@ import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import {
|
import {
|
||||||
CommentsLoadingSkeleton,
|
CommentsLoadingSkeleton,
|
||||||
PostsLoadingSkeleton,
|
PostsLoadingSkeleton,
|
||||||
TrendingCommunitiesLoadingSkeleton,
|
|
||||||
} from "../common/loading-skeleton";
|
} from "../common/loading-skeleton";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import PostHiddenSelect from "../common/post-hidden-select";
|
import PostHiddenSelect from "../common/post-hidden-select";
|
||||||
import { snapToTop } from "@utils/browser";
|
import { isBrowser, snapToTop } from "@utils/browser";
|
||||||
|
import { CommentSortSelect } from "../common/comment-sort-select";
|
||||||
|
|
||||||
interface HomeState {
|
interface HomeState {
|
||||||
postsRes: RequestState<GetPostsResponse>;
|
postsRes: RequestState<GetPostsResponse>;
|
||||||
commentsRes: RequestState<GetCommentsResponse>;
|
commentsRes: RequestState<GetCommentsResponse>;
|
||||||
trendingCommunitiesRes: RequestState<ListCommunitiesResponse>;
|
|
||||||
showSubscribedMobile: boolean;
|
showSubscribedMobile: boolean;
|
||||||
showTrendingMobile: boolean;
|
|
||||||
showSidebarMobile: boolean;
|
showSidebarMobile: boolean;
|
||||||
subscribedCollapsed: boolean;
|
subscribedCollapsed: boolean;
|
||||||
tagline?: string;
|
tagline?: string;
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
isIsomorphic: boolean;
|
isIsomorphic: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HomeProps {
|
interface HomeProps {
|
||||||
listingType?: ListingType;
|
listingType?: ListingType;
|
||||||
dataType: DataType;
|
dataType: DataType;
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
pageCursor?: PaginationCursor;
|
pageCursor?: PaginationCursor;
|
||||||
showHidden?: StringBoolean;
|
showHidden?: StringBoolean;
|
||||||
}
|
}
|
||||||
|
@ -139,10 +132,9 @@ interface HomeProps {
|
||||||
type HomeData = RouteDataResponse<{
|
type HomeData = RouteDataResponse<{
|
||||||
postsRes: GetPostsResponse;
|
postsRes: GetPostsResponse;
|
||||||
commentsRes: GetCommentsResponse;
|
commentsRes: GetCommentsResponse;
|
||||||
trendingCommunitiesRes: ListCommunitiesResponse;
|
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
function getRss(listingType: ListingType, sort: SortType) {
|
function getRss(listingType: ListingType, sort: PostSortType) {
|
||||||
let rss: string | undefined = undefined;
|
let rss: string | undefined = undefined;
|
||||||
|
|
||||||
const queryString = getQueryString({ sort });
|
const queryString = getQueryString({ sort });
|
||||||
|
@ -187,13 +179,13 @@ function getListingTypeFromQuery(
|
||||||
|
|
||||||
function getSortTypeFromQuery(
|
function getSortTypeFromQuery(
|
||||||
type: string | undefined,
|
type: string | undefined,
|
||||||
fallback: SortType,
|
fallback: PostSortType,
|
||||||
): SortType {
|
): PostSortType {
|
||||||
return type ? (type as SortType) : fallback;
|
return type ? (type as PostSortType) : fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fallbacks = {
|
type Fallbacks = {
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
listingType: ListingType;
|
listingType: ListingType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -214,7 +206,8 @@ export function getHomeQueryParams(
|
||||||
},
|
},
|
||||||
source,
|
source,
|
||||||
{
|
{
|
||||||
sort: local_user?.default_sort_type ?? local_site.default_sort_type,
|
sort:
|
||||||
|
local_user?.default_post_sort_type ?? local_site.default_post_sort_type,
|
||||||
listingType:
|
listingType:
|
||||||
local_user?.default_listing_type ??
|
local_user?.default_listing_type ??
|
||||||
local_site.default_post_listing_type,
|
local_site.default_post_listing_type,
|
||||||
|
@ -240,18 +233,6 @@ const MobileButton = ({
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
const LinkButton = ({
|
|
||||||
path,
|
|
||||||
translationKey,
|
|
||||||
}: {
|
|
||||||
path: string;
|
|
||||||
translationKey: NoOptionI18nKeys;
|
|
||||||
}) => (
|
|
||||||
<Link className="btn btn-secondary d-block" to={path}>
|
|
||||||
{I18NextService.i18n.t(translationKey)}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
|
|
||||||
type HomePathProps = Record<string, never>;
|
type HomePathProps = Record<string, never>;
|
||||||
type HomeRouteProps = RouteComponentProps<HomePathProps> & HomeProps;
|
type HomeRouteProps = RouteComponentProps<HomePathProps> & HomeProps;
|
||||||
export type HomeFetchConfig = IRoutePropsWithFetch<
|
export type HomeFetchConfig = IRoutePropsWithFetch<
|
||||||
|
@ -267,19 +248,15 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
state: HomeState = {
|
state: HomeState = {
|
||||||
postsRes: EMPTY_REQUEST,
|
postsRes: EMPTY_REQUEST,
|
||||||
commentsRes: EMPTY_REQUEST,
|
commentsRes: EMPTY_REQUEST,
|
||||||
trendingCommunitiesRes: EMPTY_REQUEST,
|
|
||||||
siteRes: this.isoData.site_res,
|
siteRes: this.isoData.site_res,
|
||||||
showSubscribedMobile: false,
|
showSubscribedMobile: false,
|
||||||
showTrendingMobile: false,
|
|
||||||
showSidebarMobile: false,
|
showSidebarMobile: false,
|
||||||
subscribedCollapsed: false,
|
subscribedCollapsed: false,
|
||||||
finished: new Map(),
|
|
||||||
isIsomorphic: false,
|
isIsomorphic: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
loadingSettled(): boolean {
|
loadingSettled(): boolean {
|
||||||
return resourcesSettled([
|
return resourcesSettled([
|
||||||
this.state.trendingCommunitiesRes,
|
|
||||||
this.props.dataType === DataType.Post
|
this.props.dataType === DataType.Post
|
||||||
? this.state.postsRes
|
? this.state.postsRes
|
||||||
: this.state.commentsRes,
|
: this.state.commentsRes,
|
||||||
|
@ -290,6 +267,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleSortChange = this.handleSortChange.bind(this);
|
this.handleSortChange = this.handleSortChange.bind(this);
|
||||||
|
this.handleCommentSortChange = this.handleCommentSortChange.bind(this);
|
||||||
this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
|
this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
|
||||||
this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
|
this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
|
||||||
this.handleShowHiddenChange = this.handleShowHiddenChange.bind(this);
|
this.handleShowHiddenChange = this.handleShowHiddenChange.bind(this);
|
||||||
|
@ -327,34 +305,37 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
|
|
||||||
// Only fetch the data if coming from another route
|
// Only fetch the data if coming from another route
|
||||||
if (FirstLoadService.isFirstLoad) {
|
if (FirstLoadService.isFirstLoad) {
|
||||||
const { trendingCommunitiesRes, commentsRes, postsRes } =
|
const { commentsRes, postsRes } = this.isoData.routeData;
|
||||||
this.isoData.routeData;
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
...this.state,
|
...this.state,
|
||||||
trendingCommunitiesRes,
|
|
||||||
commentsRes,
|
commentsRes,
|
||||||
postsRes,
|
postsRes,
|
||||||
isIsomorphic: true,
|
isIsomorphic: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state.tagline = getRandomFromList(
|
this.state.tagline = this.state?.siteRes?.tagline?.content;
|
||||||
this.state?.siteRes?.taglines ?? [],
|
|
||||||
)?.content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (
|
if (
|
||||||
!this.state.isIsomorphic ||
|
(!this.state.isIsomorphic ||
|
||||||
!Object.values(this.isoData.routeData).some(
|
!Object.values(this.isoData.routeData).some(
|
||||||
res => res.state === "success" || res.state === "failed",
|
res => res.state === "success" || res.state === "failed",
|
||||||
)
|
)) &&
|
||||||
|
isBrowser()
|
||||||
) {
|
) {
|
||||||
await Promise.all([this.fetchTrendingCommunities(), this.fetchData()]);
|
await this.fetchData(this.props);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(
|
||||||
|
nextProps: HomeRouteProps & { children?: InfernoNode },
|
||||||
|
) {
|
||||||
|
this.fetchData(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
static async fetchInitialData({
|
static async fetchInitialData({
|
||||||
query: { listingType, dataType, sort, pageCursor, showHidden },
|
query: { listingType, dataType, sort, pageCursor, showHidden },
|
||||||
headers,
|
headers,
|
||||||
|
@ -390,24 +371,12 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
commentsFetch = client.getComments(getCommentsForm);
|
commentsFetch = client.getComments(getCommentsForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
const trendingCommunitiesForm: ListCommunities = {
|
const [postsRes, commentsRes] = await Promise.all([
|
||||||
type_: "Local",
|
|
||||||
sort: "Hot",
|
|
||||||
limit: trendingFetchLimit,
|
|
||||||
};
|
|
||||||
|
|
||||||
const trendingCommunitiesFetch = client.listCommunities(
|
|
||||||
trendingCommunitiesForm,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [postsRes, commentsRes, trendingCommunitiesRes] = await Promise.all([
|
|
||||||
postsFetch,
|
postsFetch,
|
||||||
commentsFetch,
|
commentsFetch,
|
||||||
trendingCommunitiesFetch,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
trendingCommunitiesRes,
|
|
||||||
commentsRes,
|
commentsRes,
|
||||||
postsRes,
|
postsRes,
|
||||||
};
|
};
|
||||||
|
@ -470,7 +439,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
admins,
|
admins,
|
||||||
},
|
},
|
||||||
showSubscribedMobile,
|
showSubscribedMobile,
|
||||||
showTrendingMobile,
|
|
||||||
showSidebarMobile,
|
showSidebarMobile,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
|
@ -484,11 +452,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
onClick={linkEvent(this, this.handleShowSubscribedMobile)}
|
onClick={linkEvent(this, this.handleShowSubscribedMobile)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<MobileButton
|
|
||||||
textKey="trending"
|
|
||||||
show={showTrendingMobile}
|
|
||||||
onClick={linkEvent(this, this.handleShowTrendingMobile)}
|
|
||||||
/>
|
|
||||||
<MobileButton
|
<MobileButton
|
||||||
textKey="sidebar"
|
textKey="sidebar"
|
||||||
show={showSidebarMobile}
|
show={showSidebarMobile}
|
||||||
|
@ -503,11 +466,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
isMobile={true}
|
isMobile={true}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{showTrendingMobile && (
|
|
||||||
<div className="card border-secondary mb-3">
|
|
||||||
{this.trendingCommunities()}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{showSubscribedMobile && (
|
{showSubscribedMobile && (
|
||||||
<div className="card border-secondary mb-3">
|
<div className="card border-secondary mb-3">
|
||||||
{this.subscribedCommunities(true)}
|
{this.subscribedCommunities(true)}
|
||||||
|
@ -528,9 +486,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="sidebarContainer">
|
<div id="sidebarContainer">
|
||||||
<section id="sidebarMain" className="card border-secondary mb-3">
|
|
||||||
{this.trendingCommunities()}
|
|
||||||
</section>
|
|
||||||
<SiteSidebar
|
<SiteSidebar
|
||||||
site={site}
|
site={site}
|
||||||
admins={admins}
|
admins={admins}
|
||||||
|
@ -551,51 +506,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
trendingCommunities() {
|
|
||||||
switch (this.state.trendingCommunitiesRes?.state) {
|
|
||||||
case "loading":
|
|
||||||
return <TrendingCommunitiesLoadingSkeleton itemCount={5} />;
|
|
||||||
case "success": {
|
|
||||||
const trending = this.state.trendingCommunitiesRes.data.communities;
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<header className="card-header d-flex align-items-center">
|
|
||||||
<h5 className="mb-0">
|
|
||||||
<T i18nKey="trending_communities">
|
|
||||||
#
|
|
||||||
<Link className="text-body" to="/communities">
|
|
||||||
#
|
|
||||||
</Link>
|
|
||||||
</T>
|
|
||||||
</h5>
|
|
||||||
</header>
|
|
||||||
<div className="card-body">
|
|
||||||
{trending.length > 0 && (
|
|
||||||
<ul className="list-inline">
|
|
||||||
{trending.map(cv => (
|
|
||||||
<li key={cv.community.id} className="list-inline-item">
|
|
||||||
<CommunityLink community={cv.community} />
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
{canCreateCommunity(this.state.siteRes) && (
|
|
||||||
<LinkButton
|
|
||||||
path="/create_community"
|
|
||||||
translationKey="create_a_community"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<LinkButton
|
|
||||||
path="/communities"
|
|
||||||
translationKey="explore_communities"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subscribedCommunities(isMobile = false) {
|
subscribedCommunities(isMobile = false) {
|
||||||
const { subscribedCollapsed } = this.state;
|
const { subscribedCollapsed } = this.state;
|
||||||
|
|
||||||
|
@ -661,34 +571,23 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUrl({
|
async updateUrl(props: Partial<HomeProps>) {
|
||||||
dataType,
|
const { dataType, listingType, pageCursor, sort, showHidden } = {
|
||||||
listingType,
|
...this.props,
|
||||||
pageCursor,
|
...props,
|
||||||
sort,
|
};
|
||||||
showHidden,
|
|
||||||
}: Partial<HomeProps>) {
|
|
||||||
const {
|
|
||||||
dataType: urlDataType,
|
|
||||||
listingType: urlListingType,
|
|
||||||
sort: urlSort,
|
|
||||||
showHidden: urlShowHidden,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const queryParams: QueryParams<HomeProps> = {
|
const queryParams: QueryParams<HomeProps> = {
|
||||||
dataType: getDataTypeString(dataType ?? urlDataType),
|
dataType: getDataTypeString(dataType ?? DataType.Post),
|
||||||
listingType: listingType ?? urlListingType,
|
listingType: listingType,
|
||||||
pageCursor: pageCursor,
|
pageCursor: pageCursor,
|
||||||
sort: sort ?? urlSort,
|
sort: sort,
|
||||||
showHidden: showHidden ?? urlShowHidden,
|
showHidden: showHidden,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.history.push({
|
this.props.history.push({
|
||||||
pathname: "/",
|
pathname: "/",
|
||||||
search: getQueryString(queryParams),
|
search: getQueryString(queryParams),
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.fetchData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get posts() {
|
get posts() {
|
||||||
|
@ -766,7 +665,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={commentsToFlatNodes(comments)}
|
nodes={commentsToFlatNodes(comments)}
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
finished={this.state.finished}
|
|
||||||
isTopLevel
|
isTopLevel
|
||||||
showCommunity
|
showCommunity
|
||||||
showContext
|
showContext
|
||||||
|
@ -830,7 +728,14 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-auto">
|
<div className="col-auto">
|
||||||
|
{this.props.dataType === DataType.Post ? (
|
||||||
<SortSelect sort={sort} onChange={this.handleSortChange} />
|
<SortSelect sort={sort} onChange={this.handleSortChange} />
|
||||||
|
) : (
|
||||||
|
<CommentSortSelect
|
||||||
|
sort={postToCommentSortType(sort)}
|
||||||
|
onChange={this.handleCommentSortChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-auto ps-0">
|
<div className="col-auto ps-0">
|
||||||
{getRss(
|
{getRss(
|
||||||
|
@ -843,42 +748,39 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchTrendingCommunities() {
|
fetchDataToken?: symbol;
|
||||||
this.setState({ trendingCommunitiesRes: LOADING_REQUEST });
|
async fetchData({
|
||||||
this.setState({
|
dataType,
|
||||||
trendingCommunitiesRes: await HttpService.client.listCommunities({
|
pageCursor,
|
||||||
type_: "Local",
|
listingType,
|
||||||
sort: "Hot",
|
sort,
|
||||||
limit: trendingFetchLimit,
|
showHidden,
|
||||||
}),
|
}: HomeProps) {
|
||||||
});
|
const token = (this.fetchDataToken = Symbol());
|
||||||
}
|
|
||||||
|
|
||||||
async fetchData() {
|
|
||||||
const { dataType, pageCursor, listingType, sort, showHidden } = this.props;
|
|
||||||
|
|
||||||
if (dataType === DataType.Post) {
|
if (dataType === DataType.Post) {
|
||||||
this.setState({ postsRes: LOADING_REQUEST });
|
this.setState({ postsRes: LOADING_REQUEST, commentsRes: EMPTY_REQUEST });
|
||||||
this.setState({
|
const postsRes = await HttpService.client.getPosts({
|
||||||
postsRes: await HttpService.client.getPosts({
|
|
||||||
page_cursor: pageCursor,
|
page_cursor: pageCursor,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
sort,
|
sort,
|
||||||
saved_only: false,
|
saved_only: false,
|
||||||
type_: listingType,
|
type_: listingType,
|
||||||
show_hidden: showHidden === "true",
|
show_hidden: showHidden === "true",
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchDataToken) {
|
||||||
|
this.setState({ postsRes });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setState({ commentsRes: LOADING_REQUEST });
|
this.setState({ commentsRes: LOADING_REQUEST, postsRes: EMPTY_REQUEST });
|
||||||
this.setState({
|
const commentsRes = await HttpService.client.getComments({
|
||||||
commentsRes: await HttpService.client.getComments({
|
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
sort: postToCommentSortType(sort),
|
sort: postToCommentSortType(sort),
|
||||||
saved_only: false,
|
saved_only: false,
|
||||||
type_: listingType,
|
type_: listingType,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchDataToken) {
|
||||||
|
this.setState({ commentsRes });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,10 +788,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
i.setState({ showSubscribedMobile: !i.state.showSubscribedMobile });
|
i.setState({ showSubscribedMobile: !i.state.showSubscribedMobile });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShowTrendingMobile(i: Home) {
|
|
||||||
i.setState({ showTrendingMobile: !i.state.showTrendingMobile });
|
|
||||||
}
|
|
||||||
|
|
||||||
handleShowSidebarMobile(i: Home) {
|
handleShowSidebarMobile(i: Home) {
|
||||||
i.setState({ showSidebarMobile: !i.state.showSidebarMobile });
|
i.setState({ showSidebarMobile: !i.state.showSidebarMobile });
|
||||||
}
|
}
|
||||||
|
@ -910,10 +808,14 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
this.updateUrl({ pageCursor: nextPage });
|
this.updateUrl({ pageCursor: nextPage });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortChange(val: SortType) {
|
handleSortChange(val: PostSortType) {
|
||||||
this.updateUrl({ sort: val, pageCursor: undefined });
|
this.updateUrl({ sort: val, pageCursor: undefined });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleCommentSortChange(val: CommentSortType) {
|
||||||
|
this.updateUrl({ sort: commentToPostSortType(val), pageCursor: undefined });
|
||||||
|
}
|
||||||
|
|
||||||
handleListingTypeChange(val: ListingType) {
|
handleListingTypeChange(val: ListingType) {
|
||||||
this.updateUrl({ listingType: val, pageCursor: undefined });
|
this.updateUrl({ listingType: val, pageCursor: undefined });
|
||||||
}
|
}
|
||||||
|
@ -923,7 +825,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShowHiddenChange(show?: StringBoolean) {
|
handleShowHiddenChange(show?: StringBoolean) {
|
||||||
console.log(`Got ${show}`);
|
|
||||||
this.updateUrl({
|
this.updateUrl({
|
||||||
showHidden: show,
|
showHidden: show,
|
||||||
pageCursor: undefined,
|
pageCursor: undefined,
|
||||||
|
@ -961,6 +862,9 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
const createCommentRes = await HttpService.client.createComment(form);
|
const createCommentRes = await HttpService.client.createComment(form);
|
||||||
this.createAndUpdateComments(createCommentRes);
|
this.createAndUpdateComments(createCommentRes);
|
||||||
|
|
||||||
|
if (createCommentRes.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(createCommentRes.err.message), "danger");
|
||||||
|
}
|
||||||
return createCommentRes;
|
return createCommentRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -968,6 +872,9 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
const editCommentRes = await HttpService.client.editComment(form);
|
const editCommentRes = await HttpService.client.editComment(form);
|
||||||
this.findAndUpdateCommentEdit(editCommentRes);
|
this.findAndUpdateCommentEdit(editCommentRes);
|
||||||
|
|
||||||
|
if (editCommentRes.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(editCommentRes.err.message), "danger");
|
||||||
|
}
|
||||||
return editCommentRes;
|
return editCommentRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1156,7 +1063,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
res.data.comment_view,
|
res.data.comment_view,
|
||||||
s.commentsRes.data.comments,
|
s.commentsRes.data.comments,
|
||||||
);
|
);
|
||||||
s.finished.set(res.data.comment_view.comment.id, true);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
@ -1178,12 +1084,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
||||||
this.setState(s => {
|
this.setState(s => {
|
||||||
if (s.commentsRes.state === "success" && res.state === "success") {
|
if (s.commentsRes.state === "success" && res.state === "success") {
|
||||||
s.commentsRes.data.comments.unshift(res.data.comment_view);
|
s.commentsRes.data.comments.unshift(res.data.comment_view);
|
||||||
|
|
||||||
// Set finished for the parent
|
|
||||||
s.finished.set(
|
|
||||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import { resourcesSettled } from "@utils/helpers";
|
import { resourcesSettled } from "@utils/helpers";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
type InstancesData = RouteDataResponse<{
|
type InstancesData = RouteDataResponse<{
|
||||||
federatedInstancesResponse: GetFederatedInstancesResponse;
|
federatedInstancesResponse: GetFederatedInstancesResponse;
|
||||||
|
@ -71,8 +72,8 @@ export class Instances extends Component<InstancesRouteProps, InstancesState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await this.fetchInstances();
|
await this.fetchInstances();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,12 @@ import { isBrowser, refreshTheme } from "@utils/browser";
|
||||||
import { getQueryParams } from "@utils/helpers";
|
import { getQueryParams } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
|
import {
|
||||||
|
GetSiteResponse,
|
||||||
|
LoginResponse,
|
||||||
|
OAuthProvider,
|
||||||
|
PublicOAuthProvider,
|
||||||
|
} from "lemmy-js-client";
|
||||||
import { I18NextService, UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import {
|
import {
|
||||||
EMPTY_REQUEST,
|
EMPTY_REQUEST,
|
||||||
|
@ -15,7 +20,7 @@ import { toast } from "../../toast";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { Spinner } from "../common/icon";
|
import { Spinner } from "../common/icon";
|
||||||
import PasswordInput from "../common/password-input";
|
import PasswordInput from "../common/password-input";
|
||||||
import TotpModal from "../common/totp-modal";
|
import TotpModal from "../common/modal/totp-modal";
|
||||||
import { UnreadCounterService } from "../../services";
|
import { UnreadCounterService } from "../../services";
|
||||||
import { RouteData } from "../../interfaces";
|
import { RouteData } from "../../interfaces";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
|
@ -42,6 +47,7 @@ interface State {
|
||||||
};
|
};
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
show2faModal: boolean;
|
show2faModal: boolean;
|
||||||
|
showOAuthModal: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
|
async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
|
||||||
|
@ -52,16 +58,21 @@ async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
|
||||||
|
|
||||||
if (site.state === "success") {
|
if (site.state === "success") {
|
||||||
UserService.Instance.myUserInfo = site.data.my_user;
|
UserService.Instance.myUserInfo = site.data.my_user;
|
||||||
|
const isoData = setIsoData(i.context);
|
||||||
|
isoData.site_res.oauth_providers = site.data.oauth_providers;
|
||||||
|
isoData.site_res.admin_oauth_providers = site.data.admin_oauth_providers;
|
||||||
refreshTheme();
|
refreshTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { prev } = i.props;
|
const { prev } = i.props;
|
||||||
|
|
||||||
prev
|
if (prev) {
|
||||||
? i.props.history.replace(prev)
|
i.props.history.replace(prev);
|
||||||
: i.props.history.action === "PUSH"
|
} else if (i.props.history.action === "PUSH") {
|
||||||
? i.props.history.back()
|
i.props.history.back();
|
||||||
: i.props.history.replace("/");
|
} else {
|
||||||
|
i.props.history.replace("/");
|
||||||
|
}
|
||||||
|
|
||||||
UnreadCounterService.Instance.updateAll();
|
UnreadCounterService.Instance.updateAll();
|
||||||
}
|
}
|
||||||
|
@ -105,6 +116,45 @@ async function handleLoginSubmit(i: Login, event: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function handleUseOAuthProvider(params: {
|
||||||
|
oauth_provider: OAuthProvider;
|
||||||
|
username?: string;
|
||||||
|
prev?: string;
|
||||||
|
answer?: string;
|
||||||
|
show_nsfw?: boolean;
|
||||||
|
}) {
|
||||||
|
const redirectUri = `${window.location.origin}/oauth/callback`;
|
||||||
|
|
||||||
|
const state = crypto.randomUUID();
|
||||||
|
const requestUri =
|
||||||
|
params.oauth_provider.authorization_endpoint +
|
||||||
|
"?" +
|
||||||
|
[
|
||||||
|
`client_id=${encodeURIComponent(params.oauth_provider.client_id)}`,
|
||||||
|
`response_type=code`,
|
||||||
|
`scope=${encodeURIComponent(params.oauth_provider.scopes)}`,
|
||||||
|
`redirect_uri=${encodeURIComponent(redirectUri)}`,
|
||||||
|
`state=${state}`,
|
||||||
|
].join("&");
|
||||||
|
|
||||||
|
// store state in local storage
|
||||||
|
localStorage.setItem(
|
||||||
|
"oauth_state",
|
||||||
|
JSON.stringify({
|
||||||
|
state,
|
||||||
|
oauth_provider_id: params.oauth_provider.id,
|
||||||
|
redirect_uri: redirectUri,
|
||||||
|
prev: params.prev ?? "/",
|
||||||
|
username: params.username,
|
||||||
|
answer: params.answer,
|
||||||
|
show_nsfw: params.show_nsfw,
|
||||||
|
expires_at: Date.now() + 5 * 60_000,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
window.location.assign(requestUri);
|
||||||
|
}
|
||||||
|
|
||||||
function handleLoginUsernameChange(i: Login, event: any) {
|
function handleLoginUsernameChange(i: Login, event: any) {
|
||||||
i.setState(
|
i.setState(
|
||||||
prevState => (prevState.form.username_or_email = event.target.value.trim()),
|
prevState => (prevState.form.username_or_email = event.target.value.trim()),
|
||||||
|
@ -138,12 +188,14 @@ export class Login extends Component<LoginRouteProps, State> {
|
||||||
},
|
},
|
||||||
siteRes: this.isoData.site_res,
|
siteRes: this.isoData.site_res,
|
||||||
show2faModal: false,
|
show2faModal: false,
|
||||||
|
showOAuthModal: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleSubmitTotp = this.handleSubmitTotp.bind(this);
|
this.handleSubmitTotp = this.handleSubmitTotp.bind(this);
|
||||||
|
this.handleLoginWithProvider = this.handleLoginWithProvider.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
|
@ -172,6 +224,35 @@ export class Login extends Component<LoginRouteProps, State> {
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-lg-6 offset-lg-3">{this.loginForm()}</div>
|
<div className="col-12 col-lg-6 offset-lg-3">{this.loginForm()}</div>
|
||||||
</div>
|
</div>
|
||||||
|
{(this.state.siteRes.oauth_providers?.length || 0) > 0 && (
|
||||||
|
<>
|
||||||
|
<div className="row mt-3 mb-2">
|
||||||
|
<div className="col-12 col-lg-6 offset-lg-3">
|
||||||
|
{I18NextService.i18n.t("or")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col col-12 col-lgl6 offset-lg-3">
|
||||||
|
<h2 className="h4 mb-3">
|
||||||
|
{I18NextService.i18n.t("oauth_login_with_provider")}
|
||||||
|
</h2>
|
||||||
|
{(this.state.siteRes.oauth_providers ?? []).map(
|
||||||
|
(provider: PublicOAuthProvider) => (
|
||||||
|
<button
|
||||||
|
className="btn btn-primary my-2 d-block"
|
||||||
|
onClick={linkEvent(
|
||||||
|
{ oauth_provider: provider },
|
||||||
|
this.handleLoginWithProvider,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{provider.display_name}
|
||||||
|
</button>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -194,6 +275,13 @@ export class Login extends Component<LoginRouteProps, State> {
|
||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleLoginWithProvider(params: { oauth_provider: OAuthProvider }) {
|
||||||
|
handleUseOAuthProvider({
|
||||||
|
oauth_provider: params.oauth_provider,
|
||||||
|
prev: this.props.prev ?? "/",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
loginForm() {
|
loginForm() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
175
src/shared/components/home/oauth/oauth-callback.tsx
Normal file
175
src/shared/components/home/oauth/oauth-callback.tsx
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
import { setIsoData } from "@utils/app";
|
||||||
|
import { Component } from "inferno";
|
||||||
|
import { refreshTheme } from "@utils/browser";
|
||||||
|
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
|
||||||
|
import { Spinner } from "../../common/icon";
|
||||||
|
import { getQueryParams } from "@utils/helpers";
|
||||||
|
import { IRoutePropsWithFetch } from "../../../routes";
|
||||||
|
import { RouteData } from "../../../interfaces";
|
||||||
|
import { I18NextService, UserService } from "../../../services";
|
||||||
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
|
import { UnreadCounterService } from "../../../services";
|
||||||
|
import { HttpService } from "../../../services/HttpService";
|
||||||
|
import { toast } from "../../../toast";
|
||||||
|
|
||||||
|
interface OAuthCallbackProps {
|
||||||
|
code?: string;
|
||||||
|
state?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getOAuthCallbackQueryParams(
|
||||||
|
source?: string,
|
||||||
|
): OAuthCallbackProps {
|
||||||
|
return getQueryParams<OAuthCallbackProps>(
|
||||||
|
{
|
||||||
|
code: (code?: string) => code,
|
||||||
|
state: (state?: string) => state,
|
||||||
|
},
|
||||||
|
source,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type OAuthCallbackRouteProps = RouteComponentProps<Record<string, never>> &
|
||||||
|
OAuthCallbackProps;
|
||||||
|
export type OAuthCallbackConfig = IRoutePropsWithFetch<
|
||||||
|
RouteData,
|
||||||
|
Record<string, never>,
|
||||||
|
OAuthCallbackProps
|
||||||
|
>;
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
siteRes: GetSiteResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class OAuthCallback extends Component<OAuthCallbackRouteProps, State> {
|
||||||
|
private isoData = setIsoData(this.context);
|
||||||
|
|
||||||
|
state: State = {
|
||||||
|
siteRes: this.isoData.site_res,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: any, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
// store state in local storage
|
||||||
|
const local_oauth_state = JSON.parse(
|
||||||
|
localStorage.getItem("oauth_state") || "{}",
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
this.props.state &&
|
||||||
|
this.props.code &&
|
||||||
|
local_oauth_state?.state &&
|
||||||
|
local_oauth_state?.oauth_provider_id &&
|
||||||
|
local_oauth_state?.expires_at &&
|
||||||
|
this.props.state === local_oauth_state.state
|
||||||
|
) ||
|
||||||
|
local_oauth_state.expires_at < Date.now()
|
||||||
|
) {
|
||||||
|
// oauth failed or expired
|
||||||
|
toast(I18NextService.i18n.t("oauth_authorization_invalid"), "danger");
|
||||||
|
this.props.history.replace("/login");
|
||||||
|
} else {
|
||||||
|
const loginRes = await HttpService.client.authenticateWithOAuth({
|
||||||
|
code: this.props.code,
|
||||||
|
oauth_provider_id: local_oauth_state.oauth_provider_id,
|
||||||
|
redirect_uri: local_oauth_state.redirect_uri,
|
||||||
|
show_nsfw: local_oauth_state.show_nsfw,
|
||||||
|
username: local_oauth_state.username,
|
||||||
|
answer: local_oauth_state.answer,
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (loginRes.state) {
|
||||||
|
case "success": {
|
||||||
|
if (loginRes.data.jwt) {
|
||||||
|
handleOAuthLoginSuccess(
|
||||||
|
this,
|
||||||
|
local_oauth_state.prev,
|
||||||
|
loginRes.data,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (loginRes.data.verify_email_sent) {
|
||||||
|
toast(I18NextService.i18n.t("verify_email_sent"));
|
||||||
|
}
|
||||||
|
if (loginRes.data.registration_created) {
|
||||||
|
toast(I18NextService.i18n.t("registration_application_sent"));
|
||||||
|
}
|
||||||
|
this.props.history.push("/login");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "failed": {
|
||||||
|
let err_redirect = "/login";
|
||||||
|
switch (loginRes.err.message) {
|
||||||
|
case "registration_username_required":
|
||||||
|
case "registration_application_answer_required":
|
||||||
|
err_redirect = `/signup?sso_provider_id=${local_oauth_state.oauth_provider_id}`;
|
||||||
|
toast(I18NextService.i18n.t(loginRes.err.message), "danger");
|
||||||
|
break;
|
||||||
|
case "registration_application_is_pending":
|
||||||
|
toast(
|
||||||
|
I18NextService.i18n.t("registration_application_pending"),
|
||||||
|
"danger",
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "registration_denied":
|
||||||
|
case "oauth_authorization_invalid":
|
||||||
|
case "oauth_login_failed":
|
||||||
|
case "oauth_registration_closed":
|
||||||
|
case "email_already_exists":
|
||||||
|
case "username_already_exists":
|
||||||
|
case "no_email_setup":
|
||||||
|
toast(I18NextService.i18n.t(loginRes.err.message), "danger");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
toast(I18NextService.i18n.t("incorrect_login"), "danger");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.props.history.push(err_redirect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get documentTitle(): string {
|
||||||
|
return `${I18NextService.i18n.t("login")} - ${
|
||||||
|
this.state.siteRes.site_view.site.name
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="container-lg">
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleOAuthLoginSuccess(
|
||||||
|
i: OAuthCallback,
|
||||||
|
prev: string,
|
||||||
|
loginRes: LoginResponse,
|
||||||
|
) {
|
||||||
|
UserService.Instance.login({
|
||||||
|
res: loginRes,
|
||||||
|
});
|
||||||
|
const site = await HttpService.client.getSite();
|
||||||
|
|
||||||
|
if (site.state === "success") {
|
||||||
|
UserService.Instance.myUserInfo = site.data.my_user;
|
||||||
|
refreshTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev) {
|
||||||
|
i.props.history.replace(prev);
|
||||||
|
} else if (i.props.history.action === "PUSH") {
|
||||||
|
i.props.history.back();
|
||||||
|
} else {
|
||||||
|
i.props.history.replace("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
UnreadCounterService.Instance.updateAll();
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
import { OAuthProvider } from "lemmy-js-client";
|
||||||
|
import { I18NextService } from "../../../services/I18NextService";
|
||||||
|
import { Icon } from "../../common/icon";
|
||||||
|
import { MouseEventHandler } from "inferno";
|
||||||
|
|
||||||
|
type OAuthProviderListItemProps = {
|
||||||
|
provider: OAuthProvider;
|
||||||
|
onEdit: MouseEventHandler<HTMLButtonElement>;
|
||||||
|
onDelete: MouseEventHandler<HTMLButtonElement>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TextInfoFieldProps = {
|
||||||
|
i18nKey: string;
|
||||||
|
data: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function TextInfoField({ i18nKey, data }: TextInfoFieldProps) {
|
||||||
|
return (
|
||||||
|
<div className="col overflow-auto">
|
||||||
|
<dt>{I18NextService.i18n.t(i18nKey)}</dt>
|
||||||
|
<dd className="text-truncate">{data}</dd>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function boolToYesNo(value?: boolean) {
|
||||||
|
return I18NextService.i18n.t(value ? "yes" : "no");
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function OAuthProviderListItem({
|
||||||
|
provider,
|
||||||
|
onEdit,
|
||||||
|
onDelete,
|
||||||
|
}: OAuthProviderListItemProps) {
|
||||||
|
return (
|
||||||
|
<li className="oauth-item list-group-item">
|
||||||
|
<details>
|
||||||
|
<summary className="d-flex justify-content-between align-items-center">
|
||||||
|
<div className="fw-semibold">
|
||||||
|
<Icon icon="caret-right" classes="oauth-item-caret me-1" />
|
||||||
|
{provider.display_name}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="d-inline-block btn btn-outline-secondary me-2"
|
||||||
|
onClick={onEdit}
|
||||||
|
>
|
||||||
|
<Icon icon="edit" classes="me-1" />
|
||||||
|
{I18NextService.i18n.t("edit")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="d-inline-block btn btn-outline-danger"
|
||||||
|
onClick={onDelete}
|
||||||
|
>
|
||||||
|
<Icon icon="trash" classes="me-1" />
|
||||||
|
{I18NextService.i18n.t("delete")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</summary>
|
||||||
|
<div className="container">
|
||||||
|
<dl className="row row-cols-1 row-cols-sm-2 row-cols-md-3">
|
||||||
|
<TextInfoField i18nKey="oauth_issuer" data={provider.issuer} />
|
||||||
|
<TextInfoField
|
||||||
|
i18nKey="oauth_authorization_endpoint"
|
||||||
|
data={provider.authorization_endpoint}
|
||||||
|
/>
|
||||||
|
<TextInfoField
|
||||||
|
i18nKey="oauth_token_endpoint"
|
||||||
|
data={provider.token_endpoint}
|
||||||
|
/>
|
||||||
|
<TextInfoField
|
||||||
|
i18nKey="oauth_userinfo_endpoint"
|
||||||
|
data={provider.userinfo_endpoint}
|
||||||
|
/>
|
||||||
|
<TextInfoField i18nKey="oauth_id_claim" data={provider.id_claim} />
|
||||||
|
<TextInfoField
|
||||||
|
i18nKey="oauth_client_id"
|
||||||
|
data={provider.client_id}
|
||||||
|
/>
|
||||||
|
<TextInfoField i18nKey="oauth_scopes" data={provider.scopes} />
|
||||||
|
<TextInfoField
|
||||||
|
i18nKey="oauth_auto_verify_email"
|
||||||
|
data={boolToYesNo(provider.auto_verify_email)}
|
||||||
|
/>
|
||||||
|
<TextInfoField
|
||||||
|
i18nKey="oauth_account_linking_enabled"
|
||||||
|
data={boolToYesNo(provider.account_linking_enabled)}
|
||||||
|
/>
|
||||||
|
<TextInfoField
|
||||||
|
i18nKey="oauth_enabled"
|
||||||
|
data={boolToYesNo(provider.enabled)}
|
||||||
|
/>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
204
src/shared/components/home/oauth/oauth-providers-tab.tsx
Normal file
204
src/shared/components/home/oauth/oauth-providers-tab.tsx
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
import { Component, linkEvent } from "inferno";
|
||||||
|
import { I18NextService } from "../../../services/I18NextService";
|
||||||
|
import {
|
||||||
|
CreateOAuthProvider,
|
||||||
|
DeleteOAuthProvider,
|
||||||
|
EditOAuthProvider,
|
||||||
|
OAuthProvider,
|
||||||
|
} from "lemmy-js-client";
|
||||||
|
import OAuthProviderListItem from "./oauth-provider-list-item";
|
||||||
|
import CreateOrEditOAuthProviderModal, {
|
||||||
|
CreateOrEditOAuthProviderModalData,
|
||||||
|
} from "../../common/modal/create-or-edit-oauth-provider-modal";
|
||||||
|
import ConfirmationModal from "../../common/modal/confirmation-modal";
|
||||||
|
import { ProviderToEdit } from "@utils/types/oauth";
|
||||||
|
|
||||||
|
type OAuthProvidersTabProps = {
|
||||||
|
oauthProviders: OAuthProvider[];
|
||||||
|
onEdit(form: EditOAuthProvider): Promise<void>;
|
||||||
|
onCreate(form: CreateOAuthProvider): Promise<void>;
|
||||||
|
onDelete(form: DeleteOAuthProvider): Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type OAuthProvidersTabState = {
|
||||||
|
providerToDelete?: OAuthProvider;
|
||||||
|
createOrEditModalData?: CreateOrEditOAuthProviderModalData;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PRESET_OAUTH_PROVIDERS: ProviderToEdit[] = [
|
||||||
|
{
|
||||||
|
display_name: "Privacy Portal",
|
||||||
|
issuer: "https://api.privacyportal.org/",
|
||||||
|
authorization_endpoint: "https://app.privacyportal.org/oauth/authorize",
|
||||||
|
token_endpoint: "https://api.privacyportal.org/oauth/token",
|
||||||
|
userinfo_endpoint: "https://api.privacyportal.org/oauth/userinfo",
|
||||||
|
id_claim: "sub",
|
||||||
|
scopes: "openid email",
|
||||||
|
auto_verify_email: true,
|
||||||
|
account_linking_enabled: true,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
// additional preset providers can be added here
|
||||||
|
];
|
||||||
|
|
||||||
|
function handleShowCreateOrEditProviderModal({
|
||||||
|
data,
|
||||||
|
tab,
|
||||||
|
}: {
|
||||||
|
tab: OAuthProvidersTab;
|
||||||
|
data: CreateOrEditOAuthProviderModalData;
|
||||||
|
}) {
|
||||||
|
tab.setState({
|
||||||
|
createOrEditModalData: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCloseCreateOrEditModal(tab: OAuthProvidersTab) {
|
||||||
|
tab.setState({
|
||||||
|
createOrEditModalData: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTryDeleteOauthProvider({
|
||||||
|
tab,
|
||||||
|
provider,
|
||||||
|
}: {
|
||||||
|
tab: OAuthProvidersTab;
|
||||||
|
provider: OAuthProvider;
|
||||||
|
}) {
|
||||||
|
tab.setState({ providerToDelete: provider });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCloseDeleteConfirmationModal(tab: OAuthProvidersTab) {
|
||||||
|
tab.setState({ providerToDelete: undefined });
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class OAuthProvidersTab extends Component<
|
||||||
|
OAuthProvidersTabProps,
|
||||||
|
OAuthProvidersTabState
|
||||||
|
> {
|
||||||
|
state: OAuthProvidersTabState = {};
|
||||||
|
|
||||||
|
constructor(props: OAuthProvidersTabProps, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
this.handleDeleteProvider = this.handleDeleteProvider.bind(this);
|
||||||
|
this.handleCreateOrEditProviderSubmit =
|
||||||
|
this.handleCreateOrEditProviderSubmit.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(
|
||||||
|
{ oauthProviders }: Readonly<OAuthProvidersTabProps>,
|
||||||
|
{
|
||||||
|
providerToDelete,
|
||||||
|
createOrEditModalData,
|
||||||
|
}: Readonly<OAuthProvidersTabState>,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<div className="oauth-providers-tab">
|
||||||
|
<h1 className="h4 mb-4">{I18NextService.i18n.t("oauth_config")}</h1>
|
||||||
|
{oauthProviders.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<h2 className="h5 mb-2">
|
||||||
|
{I18NextService.i18n.t("oauth_providers")}
|
||||||
|
</h2>
|
||||||
|
<ul className="list-group">
|
||||||
|
{oauthProviders.map(provider => (
|
||||||
|
<OAuthProviderListItem
|
||||||
|
provider={provider}
|
||||||
|
key={provider.id}
|
||||||
|
onEdit={linkEvent(
|
||||||
|
{ data: { type: "edit", provider }, tab: this },
|
||||||
|
handleShowCreateOrEditProviderModal,
|
||||||
|
)}
|
||||||
|
onDelete={linkEvent(
|
||||||
|
{ provider, tab: this },
|
||||||
|
handleTryDeleteOauthProvider,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div>{I18NextService.i18n.t("no_oauth_providers_blurb")}</div>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-secondary btn-small mt-3"
|
||||||
|
onClick={linkEvent(
|
||||||
|
{ data: { type: "add" }, tab: this },
|
||||||
|
handleShowCreateOrEditProviderModal,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t("add_oauth_provider")}
|
||||||
|
</button>
|
||||||
|
{PRESET_OAUTH_PROVIDERS.length > 0 && (
|
||||||
|
<section className="default-oauth-providers-section mt-4">
|
||||||
|
<h2 className="h5 mb-3">
|
||||||
|
{I18NextService.i18n.t("oauth_provider_presets")}
|
||||||
|
</h2>
|
||||||
|
<ul className="d-flex flex-wrap gap-3 ps-0">
|
||||||
|
{PRESET_OAUTH_PROVIDERS.map(provider => {
|
||||||
|
const isAlreadyUsed = oauthProviders.some(
|
||||||
|
p => p.issuer === provider.issuer,
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={provider.issuer}>
|
||||||
|
<button
|
||||||
|
className="btn btn-secondary btn-small"
|
||||||
|
disabled={isAlreadyUsed}
|
||||||
|
onClick={linkEvent(
|
||||||
|
{ data: { type: "add", provider }, tab: this },
|
||||||
|
handleShowCreateOrEditProviderModal,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{provider.display_name}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
<CreateOrEditOAuthProviderModal
|
||||||
|
show={!!createOrEditModalData}
|
||||||
|
onClose={linkEvent(this, handleCloseCreateOrEditModal)}
|
||||||
|
onSubmit={this.handleCreateOrEditProviderSubmit}
|
||||||
|
data={createOrEditModalData ?? { type: "add" }}
|
||||||
|
/>
|
||||||
|
<ConfirmationModal
|
||||||
|
show={!!providerToDelete}
|
||||||
|
message={I18NextService.i18n.t("delete_oauth_provider_are_you_sure")}
|
||||||
|
loadingMessage={I18NextService.i18n.t("deleting_oauth_provider")}
|
||||||
|
onNo={linkEvent(this, handleCloseDeleteConfirmationModal)}
|
||||||
|
onYes={this.handleDeleteProvider}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleDeleteProvider() {
|
||||||
|
const id = this.state.providerToDelete?.id;
|
||||||
|
|
||||||
|
if (id !== undefined) {
|
||||||
|
await this.props.onDelete({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ providerToDelete: undefined });
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleCreateOrEditProviderSubmit(
|
||||||
|
provider: CreateOAuthProvider | EditOAuthProvider,
|
||||||
|
) {
|
||||||
|
if (this.state.createOrEditModalData?.type === "edit") {
|
||||||
|
await this.props.onEdit(provider as EditOAuthProvider);
|
||||||
|
} else {
|
||||||
|
await this.props.onCreate(provider as CreateOAuthProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
createOrEditModalData: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ import classNames from "classnames";
|
||||||
import { Component, FormEventHandler, linkEvent } from "inferno";
|
import { Component, FormEventHandler, linkEvent } from "inferno";
|
||||||
import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
|
import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
|
||||||
import { I18NextService } from "../../services";
|
import { I18NextService } from "../../services";
|
||||||
import { Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import Tabs from "../common/tabs";
|
import Tabs from "../common/tabs";
|
||||||
|
|
||||||
const rateLimitTypes = [
|
const rateLimitTypes = [
|
||||||
|
@ -144,6 +144,10 @@ export default class RateLimitsForm extends Component<
|
||||||
<h1 className="h4 mb-4">
|
<h1 className="h4 mb-4">
|
||||||
{I18NextService.i18n.t("rate_limit_header")}
|
{I18NextService.i18n.t("rate_limit_header")}
|
||||||
</h1>
|
</h1>
|
||||||
|
<div className="alert small alert-info" role="alert">
|
||||||
|
<Icon icon="info" classes="icon-inline me-2" />
|
||||||
|
{I18NextService.i18n.t("rate_limit_info")}
|
||||||
|
</div>
|
||||||
<Tabs
|
<Tabs
|
||||||
tabs={rateLimitTypes.map(rateLimitType => ({
|
tabs={rateLimitTypes.map(rateLimitType => ({
|
||||||
key: rateLimitType,
|
key: rateLimitType,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import PasswordInput from "../common/password-input";
|
||||||
import { SiteForm } from "./site-form";
|
import { SiteForm } from "./site-form";
|
||||||
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
form: {
|
form: {
|
||||||
|
@ -61,9 +62,11 @@ export class Setup extends Component<
|
||||||
this.handleCreateSite = this.handleCreateSite.bind(this);
|
this.handleCreateSite = this.handleCreateSite.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
|
if (isBrowser()) {
|
||||||
this.setState({ themeList: await fetchThemeList() });
|
this.setState({ themeList: await fetchThemeList() });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${I18NextService.i18n.t("setup")} - Lemmy`;
|
return `${I18NextService.i18n.t("setup")} - Lemmy`;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { setIsoData } from "@utils/app";
|
import { setIsoData } from "@utils/app";
|
||||||
import { isBrowser } from "@utils/browser";
|
import { isBrowser } from "@utils/browser";
|
||||||
import { resourcesSettled, validEmail } from "@utils/helpers";
|
import { getQueryParams, resourcesSettled, validEmail } from "@utils/helpers";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
|
@ -11,7 +11,7 @@ import {
|
||||||
LoginResponse,
|
LoginResponse,
|
||||||
SiteView,
|
SiteView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { joinLemmyUrl } from "../../config";
|
import { joinLemmyUrl, validActorRegexPattern } from "../../config";
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
import { I18NextService, UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import {
|
import {
|
||||||
|
@ -26,6 +26,13 @@ import { Icon, Spinner } from "../common/icon";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
import PasswordInput from "../common/password-input";
|
import PasswordInput from "../common/password-input";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
|
import { RouteData } from "../../interfaces";
|
||||||
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
|
import { handleUseOAuthProvider } from "./login";
|
||||||
|
|
||||||
|
interface SignupProps {
|
||||||
|
sso_provider_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
registerRes: RequestState<LoginResponse>;
|
registerRes: RequestState<LoginResponse>;
|
||||||
|
@ -45,11 +52,25 @@ interface State {
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSignupQueryParams(source?: string): SignupProps {
|
||||||
|
return getQueryParams<SignupProps>(
|
||||||
|
{
|
||||||
|
sso_provider_id: (param?: string) => param,
|
||||||
|
},
|
||||||
|
source,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignupRouteProps = RouteComponentProps<Record<string, never>> &
|
||||||
|
SignupProps;
|
||||||
|
export type SignupFetchConfig = IRoutePropsWithFetch<
|
||||||
|
RouteData,
|
||||||
|
Record<string, never>,
|
||||||
|
SignupProps
|
||||||
|
>;
|
||||||
|
|
||||||
@scrollMixin
|
@scrollMixin
|
||||||
export class Signup extends Component<
|
export class Signup extends Component<SignupRouteProps, State> {
|
||||||
RouteComponentProps<Record<string, never>>,
|
|
||||||
State
|
|
||||||
> {
|
|
||||||
private isoData = setIsoData(this.context);
|
private isoData = setIsoData(this.context);
|
||||||
private audio?: HTMLAudioElement;
|
private audio?: HTMLAudioElement;
|
||||||
|
|
||||||
|
@ -76,8 +97,11 @@ export class Signup extends Component<
|
||||||
this.handleAnswerChange = this.handleAnswerChange.bind(this);
|
this.handleAnswerChange = this.handleAnswerChange.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (this.state.siteRes.site_view.local_site.captcha_enabled) {
|
if (
|
||||||
|
this.state.siteRes.site_view.local_site.captcha_enabled &&
|
||||||
|
isBrowser()
|
||||||
|
) {
|
||||||
await this.fetchCaptcha();
|
await this.fetchCaptcha();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,6 +153,8 @@ export class Signup extends Component<
|
||||||
|
|
||||||
registerForm() {
|
registerForm() {
|
||||||
const siteView = this.state.siteRes.site_view;
|
const siteView = this.state.siteRes.site_view;
|
||||||
|
const oauth_provider = getOAuthProvider(this);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
className="was-validated"
|
className="was-validated"
|
||||||
|
@ -163,14 +189,20 @@ export class Signup extends Component<
|
||||||
onInput={linkEvent(this, this.handleRegisterUsernameChange)}
|
onInput={linkEvent(this, this.handleRegisterUsernameChange)}
|
||||||
required
|
required
|
||||||
minLength={3}
|
minLength={3}
|
||||||
pattern="[a-zA-Z0-9_]+"
|
pattern={validActorRegexPattern}
|
||||||
title={I18NextService.i18n.t("community_reqs")}
|
title={I18NextService.i18n.t("community_reqs")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{!oauth_provider && (
|
||||||
|
<>
|
||||||
|
{
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="register-email">
|
<label
|
||||||
|
className="col-sm-2 col-form-label"
|
||||||
|
htmlFor="register-email"
|
||||||
|
>
|
||||||
{I18NextService.i18n.t("email")}
|
{I18NextService.i18n.t("email")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
|
@ -192,14 +224,22 @@ export class Signup extends Component<
|
||||||
{!siteView.local_site.require_email_verification &&
|
{!siteView.local_site.require_email_verification &&
|
||||||
this.state.form.email &&
|
this.state.form.email &&
|
||||||
!validEmail(this.state.form.email) && (
|
!validEmail(this.state.form.email) && (
|
||||||
<div className="mt-2 mb-0 alert alert-warning" role="alert">
|
<div
|
||||||
<Icon icon="alert-triangle" classes="icon-inline me-2" />
|
className="mt-2 mb-0 alert alert-warning"
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="alert-triangle"
|
||||||
|
classes="icon-inline me-2"
|
||||||
|
/>
|
||||||
{I18NextService.i18n.t("no_password_reset")}
|
{I18NextService.i18n.t("no_password_reset")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
id="register-password"
|
id="register-password"
|
||||||
|
@ -210,16 +250,24 @@ export class Signup extends Component<
|
||||||
isNew
|
isNew
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
id="register-verify-password"
|
id="register-verify-password"
|
||||||
value={this.state.form.password_verify}
|
value={this.state.form.password_verify}
|
||||||
onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
|
onInput={linkEvent(
|
||||||
|
this,
|
||||||
|
this.handleRegisterPasswordVerifyChange,
|
||||||
|
)}
|
||||||
label={I18NextService.i18n.t("verify_password")}
|
label={I18NextService.i18n.t("verify_password")}
|
||||||
isNew
|
isNew
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{siteView.local_site.registration_mode === "RequireApplication" && (
|
{siteView.local_site.registration_mode === "RequireApplication" && (
|
||||||
<>
|
<>
|
||||||
|
@ -293,7 +341,12 @@ export class Signup extends Component<
|
||||||
{this.state.registerRes.state === "loading" ? (
|
{this.state.registerRes.state === "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
this.titleName(siteView)
|
[
|
||||||
|
this.titleName(siteView),
|
||||||
|
...(oauth_provider
|
||||||
|
? [`(${oauth_provider.display_name})`]
|
||||||
|
: []),
|
||||||
|
].join(" ")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -386,6 +439,19 @@ export class Signup extends Component<
|
||||||
password_verify,
|
password_verify,
|
||||||
username,
|
username,
|
||||||
} = i.state.form;
|
} = i.state.form;
|
||||||
|
|
||||||
|
const oauthProvider = getOAuthProvider(i);
|
||||||
|
|
||||||
|
// oauth registration
|
||||||
|
if (username && oauthProvider)
|
||||||
|
return handleUseOAuthProvider({
|
||||||
|
oauth_provider: oauthProvider,
|
||||||
|
username,
|
||||||
|
answer,
|
||||||
|
show_nsfw,
|
||||||
|
});
|
||||||
|
|
||||||
|
// normal registration
|
||||||
if (username && password && password_verify) {
|
if (username && password && password_verify) {
|
||||||
i.setState({ registerRes: LOADING_REQUEST });
|
i.setState({ registerRes: LOADING_REQUEST });
|
||||||
|
|
||||||
|
@ -513,3 +579,9 @@ export class Signup extends Component<
|
||||||
return `data:image/png;base64,${captcha.png}`;
|
return `data:image/png;base64,${captcha.png}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getOAuthProvider(signup: Signup) {
|
||||||
|
return (signup.state.siteRes.oauth_providers ?? []).find(
|
||||||
|
provider => provider.id === Number(signup.props?.sso_provider_id ?? -1),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { capitalizeFirstLetter, validInstanceTLD } from "@utils/helpers";
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
InfernoKeyboardEvent,
|
InfernoKeyboardEvent,
|
||||||
InfernoMouseEvent,
|
|
||||||
InfernoNode,
|
InfernoNode,
|
||||||
linkEvent,
|
linkEvent,
|
||||||
} from "inferno";
|
} from "inferno";
|
||||||
|
@ -64,7 +63,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
description: site.description,
|
description: site.description,
|
||||||
enable_downvotes: ls.enable_downvotes,
|
enable_downvotes: ls.enable_downvotes,
|
||||||
registration_mode: ls.registration_mode,
|
registration_mode: ls.registration_mode,
|
||||||
enable_nsfw: ls.enable_nsfw,
|
oauth_registration: ls.oauth_registration,
|
||||||
community_creation_admin_only: ls.community_creation_admin_only,
|
community_creation_admin_only: ls.community_creation_admin_only,
|
||||||
icon: site.icon,
|
icon: site.icon,
|
||||||
banner: site.banner,
|
banner: site.banner,
|
||||||
|
@ -334,6 +333,25 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<div className="mb-3 row">
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-check">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
id="create-site-oauth-registration"
|
||||||
|
type="checkbox"
|
||||||
|
checked={this.state.siteForm.oauth_registration}
|
||||||
|
onChange={linkEvent(this, this.handleSiteOauthRegistration)}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="form-check-label"
|
||||||
|
htmlFor="create-site-oauth-registration"
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t("oauth_registration")}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
|
@ -783,6 +801,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
enable_downvotes: stateSiteForm.enable_downvotes,
|
enable_downvotes: stateSiteForm.enable_downvotes,
|
||||||
application_question: stateSiteForm.application_question,
|
application_question: stateSiteForm.application_question,
|
||||||
registration_mode: stateSiteForm.registration_mode,
|
registration_mode: stateSiteForm.registration_mode,
|
||||||
|
oauth_registration: stateSiteForm.oauth_registration,
|
||||||
require_email_verification: stateSiteForm.require_email_verification,
|
require_email_verification: stateSiteForm.require_email_verification,
|
||||||
private_instance: stateSiteForm.private_instance,
|
private_instance: stateSiteForm.private_instance,
|
||||||
default_theme: stateSiteForm.default_theme,
|
default_theme: stateSiteForm.default_theme,
|
||||||
|
@ -878,42 +897,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
this.setState(s => ((s.siteForm.legal_information = val), s));
|
this.setState(s => ((s.siteForm.legal_information = val), s));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTaglineChange(i: SiteForm, index: number, val: string) {
|
|
||||||
const taglines = i.state.siteForm.taglines;
|
|
||||||
if (taglines) {
|
|
||||||
taglines[index] = val;
|
|
||||||
i.setState(i.state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleDeleteTaglineClick(
|
|
||||||
i: SiteForm,
|
|
||||||
index: number,
|
|
||||||
event: InfernoMouseEvent<HTMLButtonElement>,
|
|
||||||
) {
|
|
||||||
event.preventDefault();
|
|
||||||
const taglines = i.state.siteForm.taglines;
|
|
||||||
if (taglines) {
|
|
||||||
taglines.splice(index, 1);
|
|
||||||
i.state.siteForm.taglines = undefined;
|
|
||||||
i.setState(i.state);
|
|
||||||
i.state.siteForm.taglines = taglines;
|
|
||||||
i.setState(i.state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleAddTaglineClick(
|
|
||||||
i: SiteForm,
|
|
||||||
event: InfernoMouseEvent<HTMLButtonElement>,
|
|
||||||
) {
|
|
||||||
event.preventDefault();
|
|
||||||
if (!i.state.siteForm.taglines) {
|
|
||||||
i.state.siteForm.taglines = [];
|
|
||||||
}
|
|
||||||
i.state.siteForm.taglines.push("");
|
|
||||||
i.setState(i.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSiteApplicationQuestionChange(val: string) {
|
handleSiteApplicationQuestionChange(val: string) {
|
||||||
this.setState(s => ((s.siteForm.application_question = val), s));
|
this.setState(s => ((s.siteForm.application_question = val), s));
|
||||||
}
|
}
|
||||||
|
@ -933,6 +916,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSiteOauthRegistration(i: SiteForm, event: any) {
|
||||||
|
i.state.siteForm.oauth_registration = event.target.checked;
|
||||||
|
i.setState(i.state);
|
||||||
|
}
|
||||||
|
|
||||||
handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
|
handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
|
||||||
i.state.siteForm.community_creation_admin_only = event.target.checked;
|
i.state.siteForm.community_creation_admin_only = event.target.checked;
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
|
|
|
@ -1,49 +1,84 @@
|
||||||
import { capitalizeFirstLetter } from "@utils/helpers";
|
import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import { Component, InfernoMouseEvent, linkEvent } from "inferno";
|
import { Component, InfernoMouseEvent, linkEvent } from "inferno";
|
||||||
import { EditSite, Tagline } from "lemmy-js-client";
|
import { Tagline } from "lemmy-js-client";
|
||||||
import { I18NextService } from "../../services";
|
import { HttpService, I18NextService } from "../../services";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
import { tippyMixin } from "../mixins/tippy-mixin";
|
import { tippyMixin } from "../mixins/tippy-mixin";
|
||||||
|
import { Paginator } from "../common/paginator";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import { Prompt } from "inferno-router";
|
||||||
|
|
||||||
interface TaglineFormProps {
|
interface EditableTagline {
|
||||||
taglines: Array<Tagline>;
|
change?: "update" | "delete" | "create";
|
||||||
onSaveSite(form: EditSite): void;
|
editMode?: boolean;
|
||||||
loading: boolean;
|
tagline: Tagline;
|
||||||
|
}
|
||||||
|
|
||||||
|
function markForUpdate(editable: EditableTagline) {
|
||||||
|
if (editable.change !== "create") {
|
||||||
|
editable.change = "update";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TaglineFormState {
|
interface TaglineFormState {
|
||||||
taglines: Array<string>;
|
taglines: Array<EditableTagline>;
|
||||||
editingRow?: number;
|
page: number;
|
||||||
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@tippyMixin
|
@tippyMixin
|
||||||
export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
export class TaglineForm extends Component<
|
||||||
|
Record<never, never>,
|
||||||
|
TaglineFormState
|
||||||
|
> {
|
||||||
state: TaglineFormState = {
|
state: TaglineFormState = {
|
||||||
editingRow: undefined,
|
taglines: [],
|
||||||
taglines: this.props.taglines.map(x => x.content),
|
page: 1,
|
||||||
|
loading: false,
|
||||||
};
|
};
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
this.handlePageChange = this.handlePageChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount(): void {
|
||||||
|
if (isBrowser()) {
|
||||||
|
this.handlePageChange(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hasPendingChanges(): boolean {
|
||||||
|
return this.state.taglines.some(x => x.change);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="tagline-form col-12">
|
<div className="tagline-form col-12">
|
||||||
|
<Prompt
|
||||||
|
message={I18NextService.i18n.t("block_leaving")}
|
||||||
|
when={this.hasPendingChanges()}
|
||||||
|
/>
|
||||||
<h1 className="h4 mb-4">{I18NextService.i18n.t("taglines")}</h1>
|
<h1 className="h4 mb-4">{I18NextService.i18n.t("taglines")}</h1>
|
||||||
<div className="table-responsive col-12">
|
<div className="table-responsive col-12">
|
||||||
<table id="taglines_table" className="table table-sm table-hover">
|
<table
|
||||||
|
id="taglines_table"
|
||||||
|
className="table table-sm table-hover align-middle"
|
||||||
|
>
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
<th></th>
|
<th></th>
|
||||||
|
<th style="width:60px"></th>
|
||||||
<th style="width:121px"></th>
|
<th style="width:121px"></th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{this.state.taglines.map((cv, index) => (
|
{this.state.taglines.map((cv, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td>
|
<td>
|
||||||
{this.state.editingRow === index && (
|
{cv.editMode ? (
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
initialContent={cv}
|
initialContent={cv.tagline.content}
|
||||||
|
focus={true}
|
||||||
onContentChange={s =>
|
onContentChange={s =>
|
||||||
this.handleTaglineChange(this, index, s)
|
this.handleTaglineChange(this, index, s)
|
||||||
}
|
}
|
||||||
|
@ -51,8 +86,32 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
allLanguages={[]}
|
allLanguages={[]}
|
||||||
siteLanguages={[]}
|
siteLanguages={[]}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<div>{cv.tagline.content}</div>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className={classNames("text-center", {
|
||||||
|
"border-info": cv.change === "update",
|
||||||
|
"border-danger": cv.change === "delete",
|
||||||
|
"border-warning": cv.change === "create",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{cv.change === "update" && (
|
||||||
|
<span>
|
||||||
|
<Icon icon="transfer" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{cv.change === "delete" && (
|
||||||
|
<span>
|
||||||
|
<Icon icon="trash" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{cv.change === "create" && (
|
||||||
|
<span>
|
||||||
|
<Icon icon="add" inline />
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
{this.state.editingRow !== index && <div>{cv}</div>}
|
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<button
|
<button
|
||||||
|
@ -99,65 +158,153 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
<button
|
<button
|
||||||
onClick={linkEvent(this, this.handleSaveClick)}
|
onClick={linkEvent(this, this.handleSaveClick)}
|
||||||
className="btn btn-secondary me-2"
|
className="btn btn-secondary me-2"
|
||||||
disabled={this.props.loading}
|
disabled={this.state.loading || !this.hasPendingChanges()}
|
||||||
>
|
>
|
||||||
{this.props.loading ? (
|
{this.state.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
{this.hasPendingChanges() && (
|
||||||
|
<button
|
||||||
|
onClick={linkEvent(this, this.handleCancelClick)}
|
||||||
|
className="btn btn-secondary me-2"
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t("cancel")}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<Paginator
|
||||||
|
page={this.state.page}
|
||||||
|
onChange={this.handlePageChange}
|
||||||
|
nextDisabled={false}
|
||||||
|
disabled={this.hasPendingChanges()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTaglineChange(i: TaglineForm, index: number, val: string) {
|
handleTaglineChange(i: TaglineForm, index: number, val: string) {
|
||||||
if (i.state.taglines) {
|
const editable = i.state.taglines[index];
|
||||||
i.setState(prev => ({
|
i.setState(() => {
|
||||||
...prev,
|
markForUpdate(editable);
|
||||||
taglines: prev.taglines.map((tl, i) => (i === index ? val : tl)),
|
const tagline: Tagline = editable.tagline;
|
||||||
}));
|
tagline.content = val;
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteTaglineClick(d: { i: TaglineForm; index: number }, event: any) {
|
async handleDeleteTaglineClick(
|
||||||
|
d: { i: TaglineForm; index: number },
|
||||||
|
event: any,
|
||||||
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
d.i.setState(prev => ({
|
const editable = d.i.state.taglines[d.index];
|
||||||
...prev,
|
if (editable.change === "create") {
|
||||||
taglines: prev.taglines.filter((_, i) => i !== d.index),
|
// This drops the entry immediately, other deletes have to be saved.
|
||||||
editingRow: undefined,
|
d.i.setState(prev => {
|
||||||
}));
|
return { taglines: prev.taglines.filter(x => x !== editable) };
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
d.i.setState(() => {
|
||||||
|
editable.change = "delete";
|
||||||
|
editable.editMode = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEditTaglineClick(d: { i: TaglineForm; index: number }, event: any) {
|
handleEditTaglineClick(d: { i: TaglineForm; index: number }, event: any) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (d.i.state.editingRow === d.index) {
|
const editable = d.i.state.taglines[d.index];
|
||||||
d.i.setState({ editingRow: undefined });
|
d.i.setState(prev => {
|
||||||
} else {
|
prev.taglines
|
||||||
d.i.setState({ editingRow: d.index });
|
.filter(x => x !== editable)
|
||||||
}
|
.forEach(x => {
|
||||||
}
|
x.editMode = false;
|
||||||
|
});
|
||||||
async handleSaveClick(i: TaglineForm) {
|
editable.editMode = !editable.editMode;
|
||||||
i.props.onSaveSite({
|
|
||||||
taglines: i.state.taglines,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAddTaglineClick(
|
async handleSaveClick(i: TaglineForm) {
|
||||||
|
const promises: Promise<any>[] = [];
|
||||||
|
for (const editable of i.state.taglines) {
|
||||||
|
if (editable.change === "update") {
|
||||||
|
promises.push(
|
||||||
|
HttpService.client.editTagline(editable.tagline).then(res => {
|
||||||
|
if (res.state === "success") {
|
||||||
|
i.setState(() => {
|
||||||
|
editable.change = undefined;
|
||||||
|
editable.tagline = res.data.tagline;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else if (editable.change === "delete") {
|
||||||
|
promises.push(
|
||||||
|
HttpService.client.deleteTagline(editable.tagline).then(res => {
|
||||||
|
if (res.state === "success") {
|
||||||
|
i.setState(() => {
|
||||||
|
editable.change = undefined;
|
||||||
|
return {
|
||||||
|
taglines: this.state.taglines.filter(x => x !== editable),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else if (editable.change === "create") {
|
||||||
|
promises.push(
|
||||||
|
HttpService.client.createTagline(editable.tagline).then(res => {
|
||||||
|
if (res.state === "success") {
|
||||||
|
i.setState(() => {
|
||||||
|
editable.change = undefined;
|
||||||
|
editable.tagline = res.data.tagline;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleCancelClick(i: TaglineForm) {
|
||||||
|
i.handlePageChange(i.state.page);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleAddTaglineClick(
|
||||||
i: TaglineForm,
|
i: TaglineForm,
|
||||||
event: InfernoMouseEvent<HTMLButtonElement>,
|
event: InfernoMouseEvent<HTMLButtonElement>,
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const newTaglines = [...i.state.taglines];
|
i.setState(prev => {
|
||||||
newTaglines.push("");
|
prev.taglines.forEach(x => {
|
||||||
|
x.editMode = false;
|
||||||
i.setState({
|
});
|
||||||
taglines: newTaglines,
|
prev.taglines.push({
|
||||||
editingRow: newTaglines.length - 1,
|
tagline: { id: -1, content: "", published: "" },
|
||||||
|
change: "create",
|
||||||
|
editMode: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handlePageChange(val: number) {
|
||||||
|
this.setState({ loading: true });
|
||||||
|
const taglineRes = await HttpService.client.listTaglines({ page: val });
|
||||||
|
if (taglineRes.state === "success") {
|
||||||
|
this.setState({
|
||||||
|
page: val,
|
||||||
|
loading: false,
|
||||||
|
taglines: taglineRes.data.taglines.map(t => ({ tagline: t })),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Modal } from "bootstrap";
|
||||||
import { Component, InfernoNode, RefObject } from "inferno";
|
import { Component, InfernoNode, RefObject } from "inferno";
|
||||||
|
|
||||||
export function modalMixin<
|
export function modalMixin<
|
||||||
P extends { show: boolean },
|
P extends { show?: boolean },
|
||||||
S,
|
S,
|
||||||
Base extends new (...args: any[]) => Component<P, S> & {
|
Base extends new (...args: any[]) => Component<P, S> & {
|
||||||
readonly modalDivRef: RefObject<HTMLDivElement>;
|
readonly modalDivRef: RefObject<HTMLDivElement>;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { isBrowser, nextUserAction, snapToTop } from "../../utils/browser";
|
import { isBrowser, nextUserAction, snapToTop } from "../../utils/browser";
|
||||||
import { Component, InfernoNode } from "inferno";
|
import { Component, InfernoNode } from "inferno";
|
||||||
import { Location } from "history";
|
import { Location, History, Action } from "history";
|
||||||
|
|
||||||
function restoreScrollPosition(props: { location: Location }) {
|
function restoreScrollPosition(props: { location: Location }) {
|
||||||
const key: string = props.location.key;
|
const key: string = props.location.key;
|
||||||
|
@ -25,7 +25,7 @@ function dropScrollPosition(props: { location: Location }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scrollMixin<
|
export function scrollMixin<
|
||||||
P extends { location: Location },
|
P extends { location: Location; history: History },
|
||||||
S,
|
S,
|
||||||
Base extends new (
|
Base extends new (
|
||||||
...args: any
|
...args: any
|
||||||
|
@ -68,11 +68,12 @@ export function scrollMixin<
|
||||||
nextProps: Readonly<{ children?: InfernoNode } & P>,
|
nextProps: Readonly<{ children?: InfernoNode } & P>,
|
||||||
nextContext: any,
|
nextContext: any,
|
||||||
) {
|
) {
|
||||||
// Currently this is hypothetical. Components unmount before route changes.
|
|
||||||
if (this.props.location.key !== nextProps.location.key) {
|
if (this.props.location.key !== nextProps.location.key) {
|
||||||
|
if (nextProps.history.action !== Action.Replace) {
|
||||||
this.saveFinalPosition();
|
this.saveFinalPosition();
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return super.componentWillReceiveProps?.(nextProps, nextContext);
|
return super.componentWillReceiveProps?.(nextProps, nextContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ export function scrollMixin<
|
||||||
}
|
}
|
||||||
|
|
||||||
export function simpleScrollMixin<
|
export function simpleScrollMixin<
|
||||||
P extends { location: Location },
|
P extends { location: Location; history: History },
|
||||||
S,
|
S,
|
||||||
Base extends new (...args: any) => Component<P, S>,
|
Base extends new (...args: any) => Component<P, S>,
|
||||||
>(base: Base, _context?: ClassDecoratorContext<Base>) {
|
>(base: Base, _context?: ClassDecoratorContext<Base>) {
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
import {
|
import { fetchUsers, personToChoice, setIsoData } from "@utils/app";
|
||||||
fetchUsers,
|
|
||||||
getUpdatedSearchId,
|
|
||||||
personToChoice,
|
|
||||||
setIsoData,
|
|
||||||
} from "@utils/app";
|
|
||||||
import {
|
import {
|
||||||
debounce,
|
debounce,
|
||||||
formatPastDate,
|
formatPastDate,
|
||||||
|
@ -12,6 +7,7 @@ import {
|
||||||
getQueryParams,
|
getQueryParams,
|
||||||
getQueryString,
|
getQueryString,
|
||||||
resourcesSettled,
|
resourcesSettled,
|
||||||
|
bareRoutePush,
|
||||||
} from "@utils/helpers";
|
} from "@utils/helpers";
|
||||||
import { scrollMixin } from "./mixins/scroll-mixin";
|
import { scrollMixin } from "./mixins/scroll-mixin";
|
||||||
import { amAdmin, amMod } from "@utils/roles";
|
import { amAdmin, amMod } from "@utils/roles";
|
||||||
|
@ -66,6 +62,8 @@ import { CommunityLink } from "./community/community-link";
|
||||||
import { PersonListing } from "./person/person-listing";
|
import { PersonListing } from "./person/person-listing";
|
||||||
import { getHttpBaseInternal } from "../utils/env";
|
import { getHttpBaseInternal } from "../utils/env";
|
||||||
import { IRoutePropsWithFetch } from "../routes";
|
import { IRoutePropsWithFetch } from "../routes";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import { LoadingEllipses } from "./common/loading-ellipses";
|
||||||
|
|
||||||
type FilterType = "mod" | "user";
|
type FilterType = "mod" | "user";
|
||||||
|
|
||||||
|
@ -703,40 +701,68 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
const { modId, userId } = this.props;
|
await Promise.all([
|
||||||
const promises = [this.refetch()];
|
this.fetchModlog(this.props),
|
||||||
|
this.fetchCommunity(this.props),
|
||||||
|
this.fetchUser(this.props),
|
||||||
|
this.fetchMod(this.props),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps: ModlogRouteProps) {
|
||||||
|
this.fetchModlog(nextProps);
|
||||||
|
|
||||||
|
const reload = bareRoutePush(this.props, nextProps);
|
||||||
|
|
||||||
|
if (nextProps.modId !== this.props.modId || reload) {
|
||||||
|
this.fetchMod(nextProps);
|
||||||
|
}
|
||||||
|
if (nextProps.userId !== this.props.userId || reload) {
|
||||||
|
this.fetchUser(nextProps);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
nextProps.match.params.communityId !==
|
||||||
|
this.props.match.params.communityId ||
|
||||||
|
reload
|
||||||
|
) {
|
||||||
|
this.fetchCommunity(nextProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUserToken?: symbol;
|
||||||
|
async fetchUser(props: ModlogRouteProps) {
|
||||||
|
const token = (this.fetchUserToken = Symbol());
|
||||||
|
const { userId } = props;
|
||||||
|
|
||||||
if (userId) {
|
if (userId) {
|
||||||
promises.push(
|
const res = await HttpService.client.getPersonDetails({
|
||||||
HttpService.client
|
person_id: userId,
|
||||||
.getPersonDetails({ person_id: userId })
|
});
|
||||||
.then(res => {
|
if (res.state === "success" && token === this.fetchUserToken) {
|
||||||
if (res.state === "success") {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
userSearchOptions: [personToChoice(res.data.person_view)],
|
userSearchOptions: [personToChoice(res.data.person_view)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchModToken?: symbol;
|
||||||
|
async fetchMod(props: ModlogRouteProps) {
|
||||||
|
const token = (this.fetchModToken = Symbol());
|
||||||
|
const { modId } = props;
|
||||||
|
|
||||||
if (modId) {
|
if (modId) {
|
||||||
promises.push(
|
const res = await HttpService.client.getPersonDetails({
|
||||||
HttpService.client
|
person_id: modId,
|
||||||
.getPersonDetails({ person_id: modId })
|
});
|
||||||
.then(res => {
|
if (res.state === "success" && token === this.fetchModToken) {
|
||||||
if (res.state === "success") {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
modSearchOptions: [personToChoice(res.data.person_view)],
|
modSearchOptions: [personToChoice(res.data.person_view)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,6 +819,11 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
modSearchOptions,
|
modSearchOptions,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { actionType, modId, userId } = this.props;
|
const { actionType, modId, userId } = this.props;
|
||||||
|
const { communityId } = this.props.match.params;
|
||||||
|
|
||||||
|
const communityState = this.state.communityRes.state;
|
||||||
|
const communityResp =
|
||||||
|
communityState === "success" && this.state.communityRes.data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="modlog container-lg">
|
<div className="modlog container-lg">
|
||||||
|
@ -816,15 +847,26 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
#<strong>#</strong>#
|
#<strong>#</strong>#
|
||||||
</T>
|
</T>
|
||||||
</div>
|
</div>
|
||||||
{this.state.communityRes.state === "success" && (
|
{communityId && (
|
||||||
<h5>
|
<h5>
|
||||||
|
{communityResp ? (
|
||||||
|
<>
|
||||||
<Link
|
<Link
|
||||||
className="text-body"
|
className="text-body"
|
||||||
to={`/c/${this.state.communityRes.data.community_view.community.name}`}
|
to={`/c/${communityResp.community_view.community.name}`}
|
||||||
>
|
>
|
||||||
/c/{this.state.communityRes.data.community_view.community.name}{" "}
|
/c/{communityResp.community_view.community.name}
|
||||||
</Link>
|
</Link>{" "}
|
||||||
<span>{I18NextService.i18n.t("modlog")}</span>
|
<span>{I18NextService.i18n.t("modlog")}</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
communityState === "loading" && (
|
||||||
|
<>
|
||||||
|
<LoadingEllipses />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
)}
|
)}
|
||||||
<div className="row mb-2">
|
<div className="row mb-2">
|
||||||
|
@ -865,8 +907,9 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
options={userSearchOptions}
|
options={userSearchOptions}
|
||||||
loading={loadingUserSearch}
|
loading={loadingUserSearch}
|
||||||
/>
|
/>
|
||||||
{!this.isoData.site_res.site_view.local_site
|
{(this.amAdminOrMod ||
|
||||||
.hide_modlog_mod_names && (
|
!this.isoData.site_res.site_view.local_site
|
||||||
|
.hide_modlog_mod_names) && (
|
||||||
<Filter
|
<Filter
|
||||||
filterType="mod"
|
filterType="mod"
|
||||||
onChange={this.handleModChange}
|
onChange={this.handleModChange}
|
||||||
|
@ -935,6 +978,10 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearchUsers = debounce(async (text: string) => {
|
handleSearchUsers = debounce(async (text: string) => {
|
||||||
|
if (!text.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { userId } = this.props;
|
const { userId } = this.props;
|
||||||
const { userSearchOptions } = this.state;
|
const { userSearchOptions } = this.state;
|
||||||
this.setState({ loadingUserSearch: true });
|
this.setState({ loadingUserSearch: true });
|
||||||
|
@ -952,6 +999,10 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
});
|
});
|
||||||
|
|
||||||
handleSearchMods = debounce(async (text: string) => {
|
handleSearchMods = debounce(async (text: string) => {
|
||||||
|
if (!text.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { modId } = this.props;
|
const { modId } = this.props;
|
||||||
const { modSearchOptions } = this.state;
|
const { modSearchOptions } = this.state;
|
||||||
this.setState({ loadingModSearch: true });
|
this.setState({ loadingModSearch: true });
|
||||||
|
@ -968,40 +1019,40 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async updateUrl({ actionType, modId, page, userId }: Partial<ModlogProps>) {
|
async updateUrl(props: Partial<ModlogProps>) {
|
||||||
const {
|
const {
|
||||||
page: urlPage,
|
actionType,
|
||||||
actionType: urlActionType,
|
modId,
|
||||||
modId: urlModId,
|
page,
|
||||||
userId: urlUserId,
|
userId,
|
||||||
} = this.props;
|
match: {
|
||||||
|
params: { communityId },
|
||||||
|
},
|
||||||
|
} = { ...this.props, ...props };
|
||||||
|
|
||||||
const queryParams: QueryParams<ModlogProps> = {
|
const queryParams: QueryParams<ModlogProps> = {
|
||||||
page: (page ?? urlPage).toString(),
|
page: page.toString(),
|
||||||
actionType: actionType ?? urlActionType,
|
actionType: actionType,
|
||||||
modId: getUpdatedSearchId(modId, urlModId),
|
modId: modId?.toString(),
|
||||||
userId: getUpdatedSearchId(userId, urlUserId),
|
userId: userId?.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const communityId = this.props.match.params.communityId;
|
|
||||||
|
|
||||||
this.props.history.push(
|
this.props.history.push(
|
||||||
`/modlog${communityId ? `/${communityId}` : ""}${getQueryString(
|
`/modlog${communityId ? `/${communityId}` : ""}${getQueryString(
|
||||||
queryParams,
|
queryParams,
|
||||||
)}`,
|
)}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.refetch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async refetch() {
|
fetchModlogToken?: symbol;
|
||||||
const { actionType, page, modId, userId, postId, commentId } = this.props;
|
async fetchModlog(props: ModlogRouteProps) {
|
||||||
const { communityId: urlCommunityId } = this.props.match.params;
|
const token = (this.fetchModlogToken = Symbol());
|
||||||
|
const { actionType, page, modId, userId, postId, commentId } = props;
|
||||||
|
const { communityId: urlCommunityId } = props.match.params;
|
||||||
const communityId = getIdFromString(urlCommunityId);
|
const communityId = getIdFromString(urlCommunityId);
|
||||||
|
|
||||||
this.setState({ res: LOADING_REQUEST });
|
this.setState({ res: LOADING_REQUEST });
|
||||||
this.setState({
|
const res = await HttpService.client.getModlog({
|
||||||
res: await HttpService.client.getModlog({
|
|
||||||
community_id: communityId,
|
community_id: communityId,
|
||||||
page,
|
page,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
|
@ -1013,16 +1064,28 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
|
||||||
: undefined,
|
: undefined,
|
||||||
comment_id: commentId,
|
comment_id: commentId,
|
||||||
post_id: postId,
|
post_id: postId,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchModlogToken) {
|
||||||
|
this.setState({ res });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCommunityToken?: symbol;
|
||||||
|
async fetchCommunity(props: ModlogRouteProps) {
|
||||||
|
const token = (this.fetchCommunityToken = Symbol());
|
||||||
|
const { communityId: urlCommunityId } = props.match.params;
|
||||||
|
const communityId = getIdFromString(urlCommunityId);
|
||||||
|
|
||||||
if (communityId) {
|
if (communityId) {
|
||||||
this.setState({ communityRes: LOADING_REQUEST });
|
this.setState({ communityRes: LOADING_REQUEST });
|
||||||
this.setState({
|
const communityRes = await HttpService.client.getCommunity({
|
||||||
communityRes: await HttpService.client.getCommunity({
|
|
||||||
id: communityId,
|
id: communityId,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchCommunityToken) {
|
||||||
|
this.setState({ communityRes });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.setState({ communityRes: EMPTY_REQUEST });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
editPrivateMessage,
|
editPrivateMessage,
|
||||||
editWith,
|
editWith,
|
||||||
enableDownvotes,
|
enableDownvotes,
|
||||||
getCommentParentId,
|
|
||||||
myAuth,
|
myAuth,
|
||||||
setIsoData,
|
setIsoData,
|
||||||
updatePersonBlock,
|
updatePersonBlock,
|
||||||
|
@ -28,7 +27,6 @@ import {
|
||||||
BanPerson,
|
BanPerson,
|
||||||
BanPersonResponse,
|
BanPersonResponse,
|
||||||
BlockPerson,
|
BlockPerson,
|
||||||
CommentId,
|
|
||||||
CommentReplyResponse,
|
CommentReplyResponse,
|
||||||
CommentReplyView,
|
CommentReplyView,
|
||||||
CommentReportResponse,
|
CommentReportResponse,
|
||||||
|
@ -89,6 +87,7 @@ import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { CommentsLoadingSkeleton } from "../common/loading-skeleton";
|
import { CommentsLoadingSkeleton } from "../common/loading-skeleton";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
enum UnreadOrAll {
|
enum UnreadOrAll {
|
||||||
Unread,
|
Unread,
|
||||||
|
@ -131,7 +130,6 @@ interface InboxState {
|
||||||
sort: CommentSortType;
|
sort: CommentSortType;
|
||||||
page: number;
|
page: number;
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
isIsomorphic: boolean;
|
isIsomorphic: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +154,6 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
mentionsRes: EMPTY_REQUEST,
|
mentionsRes: EMPTY_REQUEST,
|
||||||
messagesRes: EMPTY_REQUEST,
|
messagesRes: EMPTY_REQUEST,
|
||||||
markAllAsReadRes: EMPTY_REQUEST,
|
markAllAsReadRes: EMPTY_REQUEST,
|
||||||
finished: new Map(),
|
|
||||||
isIsomorphic: false,
|
isIsomorphic: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -213,8 +210,8 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await this.refetch();
|
await this.refetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,7 +508,6 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
{ comment_view: i.view as CommentView, children: [], depth: 0 },
|
{ comment_view: i.view as CommentView, children: [], depth: 0 },
|
||||||
]}
|
]}
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
finished={this.state.finished}
|
|
||||||
markable
|
markable
|
||||||
showCommunity
|
showCommunity
|
||||||
showContext
|
showContext
|
||||||
|
@ -550,7 +546,6 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
depth: 0,
|
depth: 0,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
finished={this.state.finished}
|
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
markable
|
markable
|
||||||
showCommunity
|
showCommunity
|
||||||
|
@ -622,7 +617,6 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={commentsToFlatNodes(replies)}
|
nodes={commentsToFlatNodes(replies)}
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
finished={this.state.finished}
|
|
||||||
markable
|
markable
|
||||||
showCommunity
|
showCommunity
|
||||||
showContext
|
showContext
|
||||||
|
@ -669,7 +663,6 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
key={umv.person_mention.id}
|
key={umv.person_mention.id}
|
||||||
nodes={[{ comment_view: umv, children: [], depth: 0 }]}
|
nodes={[{ comment_view: umv, children: [], depth: 0 }]}
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
finished={this.state.finished}
|
|
||||||
markable
|
markable
|
||||||
showCommunity
|
showCommunity
|
||||||
showContext
|
showContext
|
||||||
|
@ -784,40 +777,60 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
return inboxData;
|
return inboxData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refetchToken?: symbol;
|
||||||
async refetch() {
|
async refetch() {
|
||||||
|
const token = (this.refetchToken = Symbol());
|
||||||
const sort = this.state.sort;
|
const sort = this.state.sort;
|
||||||
const unread_only = this.state.unreadOrAll === UnreadOrAll.Unread;
|
const unread_only = this.state.unreadOrAll === UnreadOrAll.Unread;
|
||||||
const page = this.state.page;
|
const page = this.state.page;
|
||||||
const limit = fetchLimit;
|
const limit = fetchLimit;
|
||||||
|
|
||||||
this.setState({ repliesRes: LOADING_REQUEST });
|
|
||||||
this.setState({
|
this.setState({
|
||||||
repliesRes: await HttpService.client.getReplies({
|
repliesRes: LOADING_REQUEST,
|
||||||
|
mentionsRes: LOADING_REQUEST,
|
||||||
|
messagesRes: LOADING_REQUEST,
|
||||||
|
});
|
||||||
|
const repliesPromise = HttpService.client
|
||||||
|
.getReplies({
|
||||||
sort,
|
sort,
|
||||||
unread_only,
|
unread_only,
|
||||||
page,
|
page,
|
||||||
limit,
|
limit,
|
||||||
}),
|
})
|
||||||
|
.then(repliesRes => {
|
||||||
|
if (token === this.refetchToken) {
|
||||||
|
this.setState({
|
||||||
|
repliesRes,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({ mentionsRes: LOADING_REQUEST });
|
const mentionsPromise = HttpService.client
|
||||||
this.setState({
|
.getPersonMentions({
|
||||||
mentionsRes: await HttpService.client.getPersonMentions({
|
|
||||||
sort,
|
sort,
|
||||||
unread_only,
|
unread_only,
|
||||||
page,
|
page,
|
||||||
limit,
|
limit,
|
||||||
}),
|
})
|
||||||
|
.then(mentionsRes => {
|
||||||
|
if (token === this.refetchToken) {
|
||||||
|
this.setState({ mentionsRes });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({ messagesRes: LOADING_REQUEST });
|
const messagesPromise = HttpService.client
|
||||||
this.setState({
|
.getPrivateMessages({
|
||||||
messagesRes: await HttpService.client.getPrivateMessages({
|
|
||||||
unread_only,
|
unread_only,
|
||||||
page,
|
page,
|
||||||
limit,
|
limit,
|
||||||
}),
|
})
|
||||||
|
.then(messagesRes => {
|
||||||
|
if (token === this.refetchToken) {
|
||||||
|
this.setState({ messagesRes });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await Promise.all([repliesPromise, mentionsPromise, messagesPromise]);
|
||||||
UnreadCounterService.Instance.updateInboxCounts();
|
UnreadCounterService.Instance.updateInboxCounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -975,9 +988,13 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
this.findAndUpdateMessage(res);
|
this.findAndUpdateMessage(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleEditMessage(form: EditPrivateMessage) {
|
async handleEditMessage(form: EditPrivateMessage): Promise<boolean> {
|
||||||
const res = await HttpService.client.editPrivateMessage(form);
|
const res = await HttpService.client.editPrivateMessage(form);
|
||||||
this.findAndUpdateMessage(res);
|
this.findAndUpdateMessage(res);
|
||||||
|
if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
|
}
|
||||||
|
return res.state !== "failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleMarkMessageAsRead(form: MarkPrivateMessageAsRead) {
|
async handleMarkMessageAsRead(form: MarkPrivateMessageAsRead) {
|
||||||
|
@ -994,7 +1011,7 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
this.reportToast(res);
|
this.reportToast(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleCreateMessage(form: CreatePrivateMessage) {
|
async handleCreateMessage(form: CreatePrivateMessage): Promise<boolean> {
|
||||||
const res = await HttpService.client.createPrivateMessage(form);
|
const res = await HttpService.client.createPrivateMessage(form);
|
||||||
this.setState(s => {
|
this.setState(s => {
|
||||||
if (s.messagesRes.state === "success" && res.state === "success") {
|
if (s.messagesRes.state === "success" && res.state === "success") {
|
||||||
|
@ -1005,6 +1022,10 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
|
}
|
||||||
|
return res.state !== "failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
findAndUpdateMessage(res: RequestState<PrivateMessageResponse>) {
|
findAndUpdateMessage(res: RequestState<PrivateMessageResponse>) {
|
||||||
|
@ -1073,6 +1094,8 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
) {
|
) {
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
toast(I18NextService.i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
|
} else if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,11 +1115,6 @@ export class Inbox extends Component<InboxRouteProps, InboxState> {
|
||||||
s.mentionsRes.data.mentions,
|
s.mentionsRes.data.mentions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Set finished for the parent
|
|
||||||
s.finished.set(
|
|
||||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
BanFromCommunity,
|
BanFromCommunity,
|
||||||
BanPerson,
|
BanPerson,
|
||||||
BlockPerson,
|
BlockPerson,
|
||||||
CommentId,
|
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
CommentView,
|
CommentView,
|
||||||
CreateComment,
|
CreateComment,
|
||||||
|
@ -38,7 +37,7 @@ import {
|
||||||
RemovePost,
|
RemovePost,
|
||||||
SaveComment,
|
SaveComment,
|
||||||
SavePost,
|
SavePost,
|
||||||
SortType,
|
PostSortType,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { CommentViewType, PersonDetailsView } from "../../interfaces";
|
import { CommentViewType, PersonDetailsView } from "../../interfaces";
|
||||||
|
@ -49,13 +48,12 @@ import { RequestState } from "../../services/HttpService";
|
||||||
|
|
||||||
interface PersonDetailsProps {
|
interface PersonDetailsProps {
|
||||||
personRes: GetPersonDetailsResponse;
|
personRes: GetPersonDetailsResponse;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
admins: PersonView[];
|
admins: PersonView[];
|
||||||
allLanguages: Language[];
|
allLanguages: Language[];
|
||||||
siteLanguages: number[];
|
siteLanguages: number[];
|
||||||
page: number;
|
page: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
enableDownvotes: boolean;
|
enableDownvotes: boolean;
|
||||||
voteDisplayMode: LocalUserVoteDisplayMode;
|
voteDisplayMode: LocalUserVoteDisplayMode;
|
||||||
enableNsfw: boolean;
|
enableNsfw: boolean;
|
||||||
|
@ -153,7 +151,6 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
|
||||||
key={i.id}
|
key={i.id}
|
||||||
nodes={[{ comment_view: c, children: [], depth: 0 }]}
|
nodes={[{ comment_view: c, children: [], depth: 0 }]}
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
finished={this.props.finished}
|
|
||||||
admins={this.props.admins}
|
admins={this.props.admins}
|
||||||
noBorder
|
noBorder
|
||||||
showCommunity
|
showCommunity
|
||||||
|
@ -266,7 +263,6 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
|
||||||
nodes={commentsToFlatNodes(this.props.personRes.comments)}
|
nodes={commentsToFlatNodes(this.props.personRes.comments)}
|
||||||
viewType={CommentViewType.Flat}
|
viewType={CommentViewType.Flat}
|
||||||
admins={this.props.admins}
|
admins={this.props.admins}
|
||||||
finished={this.props.finished}
|
|
||||||
isTopLevel
|
isTopLevel
|
||||||
showCommunity
|
showCommunity
|
||||||
showContext
|
showContext
|
||||||
|
|
|
@ -29,7 +29,9 @@ export class PersonListing extends Component<PersonListingProps, any> {
|
||||||
let link: string;
|
let link: string;
|
||||||
let serverStr: string | undefined = undefined;
|
let serverStr: string | undefined = undefined;
|
||||||
|
|
||||||
const name = useApubName ? person.name : person.display_name ?? person.name;
|
const name = useApubName
|
||||||
|
? person.name
|
||||||
|
: (person.display_name ?? person.name);
|
||||||
|
|
||||||
if (local) {
|
if (local) {
|
||||||
link = `/u/${person.name}`;
|
link = `/u/${person.name}`;
|
||||||
|
|
|
@ -4,7 +4,6 @@ import {
|
||||||
editWith,
|
editWith,
|
||||||
enableDownvotes,
|
enableDownvotes,
|
||||||
enableNsfw,
|
enableNsfw,
|
||||||
getCommentParentId,
|
|
||||||
setIsoData,
|
setIsoData,
|
||||||
updatePersonBlock,
|
updatePersonBlock,
|
||||||
voteDisplayMode,
|
voteDisplayMode,
|
||||||
|
@ -19,12 +18,13 @@ import {
|
||||||
numToSI,
|
numToSI,
|
||||||
randomStr,
|
randomStr,
|
||||||
resourcesSettled,
|
resourcesSettled,
|
||||||
|
bareRoutePush,
|
||||||
} from "@utils/helpers";
|
} from "@utils/helpers";
|
||||||
import { canMod } from "@utils/roles";
|
import { amAdmin, canMod } from "@utils/roles";
|
||||||
import type { QueryParams } from "@utils/types";
|
import type { QueryParams } from "@utils/types";
|
||||||
import { RouteDataResponse } from "@utils/types";
|
import { RouteDataResponse } from "@utils/types";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { format, parseISO } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { NoOptionI18nKeys } from "i18next";
|
import { NoOptionI18nKeys } from "i18next";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
|
@ -37,7 +37,6 @@ import {
|
||||||
BanPerson,
|
BanPerson,
|
||||||
BanPersonResponse,
|
BanPersonResponse,
|
||||||
BlockPerson,
|
BlockPerson,
|
||||||
CommentId,
|
|
||||||
CommentReplyResponse,
|
CommentReplyResponse,
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
Community,
|
Community,
|
||||||
|
@ -71,9 +70,10 @@ import {
|
||||||
RemovePost,
|
RemovePost,
|
||||||
SaveComment,
|
SaveComment,
|
||||||
SavePost,
|
SavePost,
|
||||||
SortType,
|
PostSortType,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
|
RegistrationApplicationResponse,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit, relTags } from "../../config";
|
import { fetchLimit, relTags } from "../../config";
|
||||||
import { InitialFetchRequest, PersonDetailsView } from "../../interfaces";
|
import { InitialFetchRequest, PersonDetailsView } from "../../interfaces";
|
||||||
|
@ -99,6 +99,9 @@ import { PersonListing } from "./person-listing";
|
||||||
import { getHttpBaseInternal } from "../../utils/env";
|
import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import { MediaUploads } from "../common/media-uploads";
|
import { MediaUploads } from "../common/media-uploads";
|
||||||
|
import { cakeDate } from "@utils/helpers";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import DisplayModal from "../common/modal/display-modal";
|
||||||
|
|
||||||
type ProfileData = RouteDataResponse<{
|
type ProfileData = RouteDataResponse<{
|
||||||
personRes: GetPersonDetailsResponse;
|
personRes: GetPersonDetailsResponse;
|
||||||
|
@ -107,20 +110,24 @@ type ProfileData = RouteDataResponse<{
|
||||||
|
|
||||||
interface ProfileState {
|
interface ProfileState {
|
||||||
personRes: RequestState<GetPersonDetailsResponse>;
|
personRes: RequestState<GetPersonDetailsResponse>;
|
||||||
|
// personRes and personDetailsRes point to `===` identical data. This allows
|
||||||
|
// to render the start of the profile while the new details are loading.
|
||||||
|
personDetailsRes: RequestState<GetPersonDetailsResponse>;
|
||||||
uploadsRes: RequestState<ListMediaResponse>;
|
uploadsRes: RequestState<ListMediaResponse>;
|
||||||
|
registrationRes: RequestState<RegistrationApplicationResponse>;
|
||||||
personBlocked: boolean;
|
personBlocked: boolean;
|
||||||
banReason?: string;
|
banReason?: string;
|
||||||
banExpireDays?: number;
|
banExpireDays?: number;
|
||||||
showBanDialog: boolean;
|
showBanDialog: boolean;
|
||||||
removeData: boolean;
|
removeOrRestoreData: boolean;
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
isIsomorphic: boolean;
|
isIsomorphic: boolean;
|
||||||
|
showRegistrationDialog: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProfileProps {
|
interface ProfileProps {
|
||||||
view: PersonDetailsView;
|
view: PersonDetailsView;
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
page: number;
|
page: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,13 +142,13 @@ export function getProfileQueryParams(source?: string): ProfileProps {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSortTypeFromQuery(sort?: string): SortType {
|
function getSortTypeFromQuery(sort?: string): PostSortType {
|
||||||
return sort ? (sort as SortType) : "New";
|
return sort ? (sort as PostSortType) : "New";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getViewFromProps(view?: string): PersonDetailsView {
|
function getViewFromProps(view?: string): PersonDetailsView {
|
||||||
return view
|
return view
|
||||||
? PersonDetailsView[view] ?? PersonDetailsView.Overview
|
? (PersonDetailsView[view] ?? PersonDetailsView.Overview)
|
||||||
: PersonDetailsView.Overview;
|
: PersonDetailsView.Overview;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +182,7 @@ function isPersonBlocked(personRes: RequestState<GetPersonDetailsResponse>) {
|
||||||
return (
|
return (
|
||||||
(personRes.state === "success" &&
|
(personRes.state === "success" &&
|
||||||
UserService.Instance.myUserInfo?.person_blocks.some(
|
UserService.Instance.myUserInfo?.person_blocks.some(
|
||||||
({ target: { id } }) => id === personRes.data.person_view.person.id,
|
({ id }) => id === personRes.data.person_view.person.id,
|
||||||
)) ??
|
)) ??
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
@ -194,17 +201,24 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
private isoData = setIsoData<ProfileData>(this.context);
|
private isoData = setIsoData<ProfileData>(this.context);
|
||||||
state: ProfileState = {
|
state: ProfileState = {
|
||||||
personRes: EMPTY_REQUEST,
|
personRes: EMPTY_REQUEST,
|
||||||
|
personDetailsRes: EMPTY_REQUEST,
|
||||||
uploadsRes: EMPTY_REQUEST,
|
uploadsRes: EMPTY_REQUEST,
|
||||||
personBlocked: false,
|
personBlocked: false,
|
||||||
siteRes: this.isoData.site_res,
|
siteRes: this.isoData.site_res,
|
||||||
showBanDialog: false,
|
showBanDialog: false,
|
||||||
removeData: false,
|
removeOrRestoreData: false,
|
||||||
finished: new Map(),
|
|
||||||
isIsomorphic: false,
|
isIsomorphic: false,
|
||||||
|
showRegistrationDialog: false,
|
||||||
|
registrationRes: EMPTY_REQUEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
loadingSettled() {
|
loadingSettled() {
|
||||||
return resourcesSettled([this.state.personRes]);
|
return resourcesSettled([
|
||||||
|
this.state.personRes,
|
||||||
|
this.props.view === PersonDetailsView.Uploads
|
||||||
|
? this.state.uploadsRes
|
||||||
|
: this.state.personDetailsRes,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props: ProfileRouteProps, context: any) {
|
constructor(props: ProfileRouteProps, context: any) {
|
||||||
|
@ -244,6 +258,8 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
this.handlePurgePost = this.handlePurgePost.bind(this);
|
this.handlePurgePost = this.handlePurgePost.bind(this);
|
||||||
this.handleFeaturePost = this.handleFeaturePost.bind(this);
|
this.handleFeaturePost = this.handleFeaturePost.bind(this);
|
||||||
this.handleModBanSubmit = this.handleModBanSubmit.bind(this);
|
this.handleModBanSubmit = this.handleModBanSubmit.bind(this);
|
||||||
|
this.handleRegistrationShow = this.handleRegistrationShow.bind(this);
|
||||||
|
this.handleRegistrationClose = this.handleRegistrationClose.bind(this);
|
||||||
|
|
||||||
// Only fetch the data if coming from another route
|
// Only fetch the data if coming from another route
|
||||||
if (FirstLoadService.isFirstLoad) {
|
if (FirstLoadService.isFirstLoad) {
|
||||||
|
@ -252,6 +268,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
this.state = {
|
this.state = {
|
||||||
...this.state,
|
...this.state,
|
||||||
personRes,
|
personRes,
|
||||||
|
personDetailsRes: personRes,
|
||||||
uploadsRes,
|
uploadsRes,
|
||||||
isIsomorphic: true,
|
isIsomorphic: true,
|
||||||
personBlocked: isPersonBlocked(personRes),
|
personBlocked: isPersonBlocked(personRes),
|
||||||
|
@ -259,37 +276,100 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await this.fetchUserData();
|
await this.fetchUserData(this.props, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchUserData() {
|
componentWillReceiveProps(nextProps: ProfileRouteProps) {
|
||||||
const { page, sort, view } = this.props;
|
// Overview, Posts and Comments views can use the same data.
|
||||||
|
const sharedViewTypes = [nextProps.view, this.props.view].every(
|
||||||
|
v =>
|
||||||
|
v === PersonDetailsView.Overview ||
|
||||||
|
v === PersonDetailsView.Posts ||
|
||||||
|
v === PersonDetailsView.Comments,
|
||||||
|
);
|
||||||
|
|
||||||
|
const reload = bareRoutePush(this.props, nextProps);
|
||||||
|
|
||||||
|
const newUsername =
|
||||||
|
nextProps.match.params.username !== this.props.match.params.username;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(nextProps.view !== this.props.view && !sharedViewTypes) ||
|
||||||
|
nextProps.sort !== this.props.sort ||
|
||||||
|
nextProps.page !== this.props.page ||
|
||||||
|
newUsername ||
|
||||||
|
reload
|
||||||
|
) {
|
||||||
|
this.fetchUserData(nextProps, reload || newUsername);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUploadsToken?: symbol;
|
||||||
|
async fetchUploads(props: ProfileRouteProps) {
|
||||||
|
if (!this.amCurrentUser) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = (this.fetchUploadsToken = Symbol());
|
||||||
|
const { page } = props;
|
||||||
|
this.setState({ uploadsRes: LOADING_REQUEST });
|
||||||
|
const form: ListMedia = {
|
||||||
|
// userId?
|
||||||
|
page,
|
||||||
|
limit: fetchLimit,
|
||||||
|
};
|
||||||
|
const uploadsRes = await HttpService.client.listMedia(form);
|
||||||
|
if (token === this.fetchUploadsToken) {
|
||||||
|
this.setState({ uploadsRes });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUserDataToken?: symbol;
|
||||||
|
async fetchUserData(props: ProfileRouteProps, showBothLoading = false) {
|
||||||
|
const token = (this.fetchUploadsToken = this.fetchUserDataToken = Symbol());
|
||||||
|
const { page, sort, view } = props;
|
||||||
|
|
||||||
|
if (view === PersonDetailsView.Uploads) {
|
||||||
|
this.fetchUploads(props);
|
||||||
|
if (!showBothLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
personRes: LOADING_REQUEST,
|
||||||
|
personDetailsRes: LOADING_REQUEST,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (showBothLoading) {
|
||||||
|
this.setState({
|
||||||
|
personRes: LOADING_REQUEST,
|
||||||
|
personDetailsRes: LOADING_REQUEST,
|
||||||
|
uploadsRes: EMPTY_REQUEST,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
personDetailsRes: LOADING_REQUEST,
|
||||||
|
uploadsRes: EMPTY_REQUEST,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ personRes: LOADING_REQUEST });
|
|
||||||
const personRes = await HttpService.client.getPersonDetails({
|
const personRes = await HttpService.client.getPersonDetails({
|
||||||
username: this.props.match.params.username,
|
username: props.match.params.username,
|
||||||
sort,
|
sort,
|
||||||
saved_only: view === PersonDetailsView.Saved,
|
saved_only: view === PersonDetailsView.Saved,
|
||||||
page,
|
page,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (token === this.fetchUserDataToken) {
|
||||||
this.setState({
|
this.setState({
|
||||||
personRes,
|
personRes,
|
||||||
|
personDetailsRes: personRes,
|
||||||
personBlocked: isPersonBlocked(personRes),
|
personBlocked: isPersonBlocked(personRes),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (view === PersonDetailsView.Uploads) {
|
|
||||||
this.setState({ uploadsRes: LOADING_REQUEST });
|
|
||||||
const form: ListMedia = {
|
|
||||||
page,
|
|
||||||
limit: fetchLimit,
|
|
||||||
};
|
|
||||||
const uploadsRes = await HttpService.client.listMedia(form);
|
|
||||||
this.setState({ uploadsRes });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +463,10 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
const personRes = this.state.personRes.data;
|
const personRes = this.state.personRes.data;
|
||||||
const { page, sort, view } = this.props;
|
const { page, sort, view } = this.props;
|
||||||
|
|
||||||
|
const personDetailsState = this.state.personDetailsRes.state;
|
||||||
|
const personDetailsRes =
|
||||||
|
personDetailsState === "success" && this.state.personDetailsRes.data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-md-8">
|
<div className="col-12 col-md-8">
|
||||||
|
@ -402,13 +486,19 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
|
|
||||||
{this.renderUploadsRes()}
|
{this.renderUploadsRes()}
|
||||||
|
|
||||||
|
{personDetailsState === "loading" &&
|
||||||
|
this.props.view !== PersonDetailsView.Uploads ? (
|
||||||
|
<h5>
|
||||||
|
<Spinner large />
|
||||||
|
</h5>
|
||||||
|
) : (
|
||||||
|
personDetailsRes && (
|
||||||
<PersonDetails
|
<PersonDetails
|
||||||
personRes={personRes}
|
personRes={personDetailsRes}
|
||||||
admins={siteRes.admins}
|
admins={siteRes.admins}
|
||||||
sort={sort}
|
sort={sort}
|
||||||
page={page}
|
page={page}
|
||||||
limit={fetchLimit}
|
limit={fetchLimit}
|
||||||
finished={this.state.finished}
|
|
||||||
enableDownvotes={enableDownvotes(siteRes)}
|
enableDownvotes={enableDownvotes(siteRes)}
|
||||||
voteDisplayMode={voteDisplayMode(siteRes)}
|
voteDisplayMode={voteDisplayMode(siteRes)}
|
||||||
enableNsfw={enableNsfw(siteRes)}
|
enableNsfw={enableNsfw(siteRes)}
|
||||||
|
@ -446,6 +536,8 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
onFeaturePost={this.handleFeaturePost}
|
onFeaturePost={this.handleFeaturePost}
|
||||||
onMarkPostAsRead={() => {}}
|
onMarkPostAsRead={() => {}}
|
||||||
/>
|
/>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-md-4">
|
<div className="col-12 col-md-4">
|
||||||
|
@ -473,7 +565,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
{this.getRadio(PersonDetailsView.Comments)}
|
{this.getRadio(PersonDetailsView.Comments)}
|
||||||
{this.getRadio(PersonDetailsView.Posts)}
|
{this.getRadio(PersonDetailsView.Posts)}
|
||||||
{this.amCurrentUser && this.getRadio(PersonDetailsView.Saved)}
|
{this.amCurrentUser && this.getRadio(PersonDetailsView.Saved)}
|
||||||
{this.getRadio(PersonDetailsView.Uploads)}
|
{this.amCurrentUser && this.getRadio(PersonDetailsView.Uploads)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -544,6 +636,8 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
personBlocked,
|
personBlocked,
|
||||||
siteRes: { admins },
|
siteRes: { admins },
|
||||||
showBanDialog,
|
showBanDialog,
|
||||||
|
showRegistrationDialog,
|
||||||
|
registrationRes,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -587,15 +681,27 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
<div className="flex-grow-1 unselectable pointer mx-2"></div>
|
<div className="flex-grow-1 unselectable pointer mx-2"></div>
|
||||||
{!this.amCurrentUser && UserService.Instance.myUserInfo && (
|
{!this.amCurrentUser && UserService.Instance.myUserInfo && (
|
||||||
<>
|
<>
|
||||||
|
{amAdmin() && (
|
||||||
|
<Link
|
||||||
|
className={
|
||||||
|
"d-flex align-self-start btn btn-secondary me-2"
|
||||||
|
}
|
||||||
|
to={`/modlog?userId=${pv.person.id}`}
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t("user_moderation_history", {
|
||||||
|
user: pv.person.name,
|
||||||
|
})}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
{pv.person.matrix_user_id && (
|
||||||
<a
|
<a
|
||||||
className={`d-flex align-self-start btn btn-secondary me-2 ${
|
className={`d-flex align-self-start btn btn-secondary me-2`}
|
||||||
!pv.person.matrix_user_id && "invisible"
|
|
||||||
}`}
|
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
|
href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("send_secure_message")}
|
{I18NextService.i18n.t("send_secure_message")}
|
||||||
</a>
|
</a>
|
||||||
|
)}
|
||||||
<Link
|
<Link
|
||||||
className={
|
className={
|
||||||
"d-flex align-self-start btn btn-secondary me-2"
|
"d-flex align-self-start btn btn-secondary me-2"
|
||||||
|
@ -656,6 +762,46 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
{capitalizeFirstLetter(I18NextService.i18n.t("unban"))}
|
{capitalizeFirstLetter(I18NextService.i18n.t("unban"))}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
{amAdmin() && (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
className={
|
||||||
|
"d-flex registration-self-start btn btn-secondary me-2"
|
||||||
|
}
|
||||||
|
aria-label={I18NextService.i18n.t("view_registration")}
|
||||||
|
onClick={this.handleRegistrationShow}
|
||||||
|
>
|
||||||
|
{I18NextService.i18n.t("view_registration")}
|
||||||
|
</button>
|
||||||
|
{showRegistrationDialog && (
|
||||||
|
<DisplayModal
|
||||||
|
onClose={this.handleRegistrationClose}
|
||||||
|
loadingMessage={I18NextService.i18n.t(
|
||||||
|
"loading_registration",
|
||||||
|
)}
|
||||||
|
title={I18NextService.i18n.t("registration_for_user", {
|
||||||
|
name: pv.person.display_name ?? pv.person.name,
|
||||||
|
})}
|
||||||
|
show={showRegistrationDialog}
|
||||||
|
loading={registrationRes.state === "loading"}
|
||||||
|
>
|
||||||
|
{registrationRes.state === "success" ? (
|
||||||
|
<article
|
||||||
|
dangerouslySetInnerHTML={mdToHtml(
|
||||||
|
registrationRes.data.registration_application
|
||||||
|
.registration_application.answer,
|
||||||
|
() => this.forceUpdate(),
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
) : registrationRes.state === "failed" ? (
|
||||||
|
I18NextService.i18n.t("fetch_registration_error")
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</DisplayModal>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{pv.person.bio && (
|
{pv.person.bio && (
|
||||||
<div className="d-flex align-items-center mb-2">
|
<div className="d-flex align-items-center mb-2">
|
||||||
|
@ -695,7 +841,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
<Icon icon="cake" />
|
<Icon icon="cake" />
|
||||||
<span className="ms-2">
|
<span className="ms-2">
|
||||||
{I18NextService.i18n.t("cake_day_title")}{" "}
|
{I18NextService.i18n.t("cake_day_title")}{" "}
|
||||||
{format(parseISO(pv.person.published), "PPP")}
|
{format(cakeDate(pv.person.published), "PPP")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{!UserService.Instance.myUserInfo && (
|
{!UserService.Instance.myUserInfo && (
|
||||||
|
@ -745,7 +891,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
className="form-check-input"
|
className="form-check-input"
|
||||||
id="mod-ban-remove-data"
|
id="mod-ban-remove-data"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={this.state.removeData}
|
checked={this.state.removeOrRestoreData}
|
||||||
onChange={linkEvent(this, this.handleModRemoveDataChange)}
|
onChange={linkEvent(this, this.handleModRemoveDataChange)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
|
@ -787,26 +933,30 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUrl({ page, sort, view }: Partial<ProfileProps>) {
|
async updateUrl(props: Partial<ProfileRouteProps>) {
|
||||||
const { page: urlPage, sort: urlSort, view: urlView } = this.props;
|
const {
|
||||||
|
page,
|
||||||
|
sort,
|
||||||
|
view,
|
||||||
|
match: {
|
||||||
|
params: { username },
|
||||||
|
},
|
||||||
|
} = { ...this.props, ...props };
|
||||||
|
|
||||||
const queryParams: QueryParams<ProfileProps> = {
|
const queryParams: QueryParams<ProfileProps> = {
|
||||||
page: (page ?? urlPage).toString(),
|
page: page?.toString(),
|
||||||
sort: sort ?? urlSort,
|
sort,
|
||||||
view: view ?? urlView,
|
view,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { username } = this.props.match.params;
|
|
||||||
|
|
||||||
this.props.history.push(`/u/${username}${getQueryString(queryParams)}`);
|
this.props.history.push(`/u/${username}${getQueryString(queryParams)}`);
|
||||||
await this.fetchUserData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePageChange(page: number) {
|
handlePageChange(page: number) {
|
||||||
this.updateUrl({ page });
|
this.updateUrl({ page });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortChange(sort: SortType) {
|
handleSortChange(sort: PostSortType) {
|
||||||
this.updateUrl({ sort, page: 1 });
|
this.updateUrl({ sort, page: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,16 +980,42 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleModRemoveDataChange(i: Profile, event: any) {
|
handleModRemoveDataChange(i: Profile, event: any) {
|
||||||
i.setState({ removeData: event.target.checked });
|
i.setState({ removeOrRestoreData: event.target.checked });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleModBanSubmitCancel(i: Profile) {
|
handleModBanSubmitCancel(i: Profile) {
|
||||||
i.setState({ showBanDialog: false });
|
i.setState({ showBanDialog: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleRegistrationShow() {
|
||||||
|
if (this.state.registrationRes.state !== "success") {
|
||||||
|
this.setState({ registrationRes: LOADING_REQUEST });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ showRegistrationDialog: true });
|
||||||
|
|
||||||
|
if (this.state.personDetailsRes.state === "success") {
|
||||||
|
HttpService.client
|
||||||
|
.getRegistrationApplication({
|
||||||
|
person_id: this.state.personDetailsRes.data.person_view.person.id,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
this.setState({ registrationRes: res });
|
||||||
|
|
||||||
|
if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t("fetch_registration_error"), "danger");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRegistrationClose() {
|
||||||
|
this.setState({ showRegistrationDialog: false });
|
||||||
|
}
|
||||||
|
|
||||||
async handleModBanSubmit(i: Profile, event: any) {
|
async handleModBanSubmit(i: Profile, event: any) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const { removeData, banReason, banExpireDays } = i.state;
|
const { banReason, banExpireDays } = i.state;
|
||||||
|
|
||||||
const personRes = i.state.personRes;
|
const personRes = i.state.personRes;
|
||||||
|
|
||||||
|
@ -849,13 +1025,13 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
|
|
||||||
// If its an unban, restore all their data
|
// If its an unban, restore all their data
|
||||||
if (!ban) {
|
if (!ban) {
|
||||||
i.setState({ removeData: false });
|
i.setState({ removeOrRestoreData: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await HttpService.client.banPerson({
|
const res = await HttpService.client.banPerson({
|
||||||
person_id: person.id,
|
person_id: person.id,
|
||||||
ban,
|
ban,
|
||||||
remove_data: removeData,
|
remove_or_restore_data: i.state.removeOrRestoreData,
|
||||||
reason: banReason,
|
reason: banReason,
|
||||||
expires: futureDaysToUnixTime(banExpireDays),
|
expires: futureDaysToUnixTime(banExpireDays),
|
||||||
});
|
});
|
||||||
|
@ -1089,7 +1265,6 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
res.data.comment_view,
|
res.data.comment_view,
|
||||||
s.personRes.data.comments,
|
s.personRes.data.comments,
|
||||||
);
|
);
|
||||||
s.finished.set(res.data.comment_view.comment.id, true);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
@ -1111,11 +1286,6 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
|
||||||
this.setState(s => {
|
this.setState(s => {
|
||||||
if (s.personRes.state === "success" && res.state === "success") {
|
if (s.personRes.state === "success" && res.state === "success") {
|
||||||
s.personRes.data.comments.unshift(res.data.comment_view);
|
s.personRes.data.comments.unshift(res.data.comment_view);
|
||||||
// Set finished for the parent
|
|
||||||
s.finished.set(
|
|
||||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { UnreadCounterService } from "../../services";
|
||||||
import { getHttpBaseInternal } from "../../utils/env";
|
import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
enum RegistrationState {
|
enum RegistrationState {
|
||||||
Unread,
|
Unread,
|
||||||
|
@ -92,8 +93,8 @@ export class RegistrationApplications extends Component<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await this.refetch();
|
await this.refetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,15 +109,11 @@ export class RegistrationApplications extends Component<
|
||||||
}
|
}
|
||||||
|
|
||||||
renderApps() {
|
renderApps() {
|
||||||
switch (this.state.appsRes.state) {
|
const appsState = this.state.appsRes.state;
|
||||||
case "loading":
|
const apps =
|
||||||
return (
|
appsState === "success" &&
|
||||||
<h5>
|
this.state.appsRes.data.registration_applications;
|
||||||
<Spinner large />
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
case "success": {
|
|
||||||
const apps = this.state.appsRes.data.registration_applications;
|
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
|
@ -128,18 +125,26 @@ export class RegistrationApplications extends Component<
|
||||||
{I18NextService.i18n.t("registration_applications")}
|
{I18NextService.i18n.t("registration_applications")}
|
||||||
</h1>
|
</h1>
|
||||||
{this.selects()}
|
{this.selects()}
|
||||||
|
{apps ? (
|
||||||
|
<>
|
||||||
{this.applicationList(apps)}
|
{this.applicationList(apps)}
|
||||||
<Paginator
|
<Paginator
|
||||||
page={this.state.page}
|
page={this.state.page}
|
||||||
onChange={this.handlePageChange}
|
onChange={this.handlePageChange}
|
||||||
nextDisabled={fetchLimit > apps.length}
|
nextDisabled={fetchLimit > apps.length}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
appsState === "loading" && (
|
||||||
|
<div className="text-center">
|
||||||
|
<Spinner large />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -263,19 +268,22 @@ export class RegistrationApplications extends Component<
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refetchToken?: symbol;
|
||||||
async refetch() {
|
async refetch() {
|
||||||
|
const token = (this.refetchToken = Symbol());
|
||||||
const unread_only =
|
const unread_only =
|
||||||
this.state.registrationState === RegistrationState.Unread;
|
this.state.registrationState === RegistrationState.Unread;
|
||||||
this.setState({
|
this.setState({
|
||||||
appsRes: LOADING_REQUEST,
|
appsRes: LOADING_REQUEST,
|
||||||
});
|
});
|
||||||
this.setState({
|
const appsRes = await HttpService.client.listRegistrationApplications({
|
||||||
appsRes: await HttpService.client.listRegistrationApplications({
|
|
||||||
unread_only: unread_only,
|
unread_only: unread_only,
|
||||||
page: this.state.page,
|
page: this.state.page,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.refetchToken) {
|
||||||
|
this.setState({ appsRes });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleApproveApplication(form: ApproveRegistrationApplication) {
|
async handleApproveApplication(form: ApproveRegistrationApplication) {
|
||||||
|
|
|
@ -56,6 +56,7 @@ import { UnreadCounterService } from "../../services";
|
||||||
import { getHttpBaseInternal } from "../../utils/env";
|
import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
enum UnreadOrAll {
|
enum UnreadOrAll {
|
||||||
Unread,
|
Unread,
|
||||||
|
@ -160,8 +161,8 @@ export class Reports extends Component<ReportsRouteProps, ReportsState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await this.refetch();
|
await this.refetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,9 +453,22 @@ export class Reports extends Component<ReportsRouteProps, ReportsState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
all() {
|
all() {
|
||||||
|
const combined = this.buildCombined;
|
||||||
|
if (
|
||||||
|
combined.length === 0 &&
|
||||||
|
(this.state.commentReportsRes.state === "loading" ||
|
||||||
|
this.state.postReportsRes.state === "loading" ||
|
||||||
|
this.state.messageReportsRes.state === "loading")
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<Spinner large />
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.buildCombined.map(i => (
|
{combined.map(i => (
|
||||||
<>
|
<>
|
||||||
<hr />
|
<hr />
|
||||||
{this.renderItemType(i)}
|
{this.renderItemType(i)}
|
||||||
|
@ -575,6 +589,7 @@ export class Reports extends Component<ReportsRouteProps, ReportsState> {
|
||||||
|
|
||||||
static async fetchInitialData({
|
static async fetchInitialData({
|
||||||
headers,
|
headers,
|
||||||
|
site,
|
||||||
}: InitialFetchRequest): Promise<ReportsData> {
|
}: InitialFetchRequest): Promise<ReportsData> {
|
||||||
const client = wrapClient(
|
const client = wrapClient(
|
||||||
new LemmyHttp(getHttpBaseInternal(), { headers }),
|
new LemmyHttp(getHttpBaseInternal(), { headers }),
|
||||||
|
@ -601,7 +616,7 @@ export class Reports extends Component<ReportsRouteProps, ReportsState> {
|
||||||
messageReportsRes: EMPTY_REQUEST,
|
messageReportsRes: EMPTY_REQUEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (amAdmin()) {
|
if (amAdmin(site.my_user)) {
|
||||||
const privateMessageReportsForm: ListPrivateMessageReports = {
|
const privateMessageReportsForm: ListPrivateMessageReports = {
|
||||||
unresolved_only,
|
unresolved_only,
|
||||||
page,
|
page,
|
||||||
|
@ -616,7 +631,9 @@ export class Reports extends Component<ReportsRouteProps, ReportsState> {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refetchToken?: symbol;
|
||||||
async refetch() {
|
async refetch() {
|
||||||
|
const token = (this.refetchToken = Symbol());
|
||||||
const unresolved_only = this.state.unreadOrAll === UnreadOrAll.Unread;
|
const unresolved_only = this.state.unreadOrAll === UnreadOrAll.Unread;
|
||||||
const page = this.state.page;
|
const page = this.state.page;
|
||||||
const limit = fetchLimit;
|
const limit = fetchLimit;
|
||||||
|
@ -636,19 +653,32 @@ export class Reports extends Component<ReportsRouteProps, ReportsState> {
|
||||||
limit,
|
limit,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setState({
|
const commentReportPromise = HttpService.client
|
||||||
commentReportsRes: await HttpService.client.listCommentReports(form),
|
.listCommentReports(form)
|
||||||
postReportsRes: await HttpService.client.listPostReports(form),
|
.then(commentReportsRes => {
|
||||||
|
if (token === this.refetchToken) {
|
||||||
|
this.setState({ commentReportsRes });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const postReportPromise = HttpService.client
|
||||||
|
.listPostReports(form)
|
||||||
|
.then(postReportsRes => {
|
||||||
|
if (token === this.refetchToken) {
|
||||||
|
this.setState({ postReportsRes });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (amAdmin()) {
|
if (amAdmin()) {
|
||||||
this.setState({
|
const messageReportsRes =
|
||||||
messageReportsRes:
|
await HttpService.client.listPrivateMessageReports(form);
|
||||||
await HttpService.client.listPrivateMessageReports(form),
|
if (token === this.refetchToken) {
|
||||||
});
|
this.setState({ messageReportsRes });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await Promise.all([commentReportPromise, postReportPromise]);
|
||||||
|
}
|
||||||
|
|
||||||
async handleResolveCommentReport(form: ResolveCommentReport) {
|
async handleResolveCommentReport(form: ResolveCommentReport) {
|
||||||
const res = await HttpService.client.resolveCommentReport(form);
|
const res = await HttpService.client.resolveCommentReport(form);
|
||||||
this.findAndUpdateCommentReport(res);
|
this.findAndUpdateCommentReport(res);
|
||||||
|
|
|
@ -22,17 +22,17 @@ import {
|
||||||
BlockCommunityResponse,
|
BlockCommunityResponse,
|
||||||
BlockInstanceResponse,
|
BlockInstanceResponse,
|
||||||
BlockPersonResponse,
|
BlockPersonResponse,
|
||||||
CommunityBlockView,
|
CommentSortType,
|
||||||
|
Community,
|
||||||
GenerateTotpSecretResponse,
|
GenerateTotpSecretResponse,
|
||||||
GetFederatedInstancesResponse,
|
GetFederatedInstancesResponse,
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
Instance,
|
Instance,
|
||||||
InstanceBlockView,
|
|
||||||
LemmyHttp,
|
LemmyHttp,
|
||||||
ListingType,
|
ListingType,
|
||||||
LoginResponse,
|
LoginResponse,
|
||||||
PersonBlockView,
|
Person,
|
||||||
SortType,
|
PostSortType,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
UpdateTotpResponse,
|
UpdateTotpResponse,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
|
@ -65,13 +65,19 @@ import Tabs from "../common/tabs";
|
||||||
import { CommunityLink } from "../community/community-link";
|
import { CommunityLink } from "../community/community-link";
|
||||||
import { PersonListing } from "./person-listing";
|
import { PersonListing } from "./person-listing";
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import TotpModal from "../common/totp-modal";
|
import TotpModal from "../common/modal/totp-modal";
|
||||||
import { LoadingEllipses } from "../common/loading-ellipses";
|
import { LoadingEllipses } from "../common/loading-ellipses";
|
||||||
import { refreshTheme, setThemeOverride, snapToTop } from "../../utils/browser";
|
import {
|
||||||
|
isBrowser,
|
||||||
|
refreshTheme,
|
||||||
|
setThemeOverride,
|
||||||
|
snapToTop,
|
||||||
|
} from "../../utils/browser";
|
||||||
import { getHttpBaseInternal } from "../../utils/env";
|
import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
||||||
|
import { CommentSortSelect } from "../common/comment-sort-select";
|
||||||
|
|
||||||
type SettingsData = RouteDataResponse<{
|
type SettingsData = RouteDataResponse<{
|
||||||
instancesRes: GetFederatedInstancesResponse;
|
instancesRes: GetFederatedInstancesResponse;
|
||||||
|
@ -90,7 +96,8 @@ interface SettingsState {
|
||||||
blur_nsfw?: boolean;
|
blur_nsfw?: boolean;
|
||||||
auto_expand?: boolean;
|
auto_expand?: boolean;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
default_sort_type?: SortType;
|
default_post_sort_type?: PostSortType;
|
||||||
|
default_comment_sort_type?: CommentSortType;
|
||||||
default_listing_type?: ListingType;
|
default_listing_type?: ListingType;
|
||||||
interface_language?: string;
|
interface_language?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
|
@ -108,7 +115,6 @@ interface SettingsState {
|
||||||
bot_account?: boolean;
|
bot_account?: boolean;
|
||||||
show_bot_accounts?: boolean;
|
show_bot_accounts?: boolean;
|
||||||
show_read_posts?: boolean;
|
show_read_posts?: boolean;
|
||||||
show_new_post_notifs?: boolean;
|
|
||||||
discussion_languages?: number[];
|
discussion_languages?: number[];
|
||||||
open_links_in_new_tab?: boolean;
|
open_links_in_new_tab?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -121,9 +127,9 @@ interface SettingsState {
|
||||||
delete_content?: boolean;
|
delete_content?: boolean;
|
||||||
password?: string;
|
password?: string;
|
||||||
};
|
};
|
||||||
personBlocks: PersonBlockView[];
|
personBlocks: Person[];
|
||||||
communityBlocks: CommunityBlockView[];
|
communityBlocks: Community[];
|
||||||
instanceBlocks: InstanceBlockView[];
|
instanceBlocks: Instance[];
|
||||||
currentTab: string;
|
currentTab: string;
|
||||||
themeList: string[];
|
themeList: string[];
|
||||||
deleteAccountShowConfirm: boolean;
|
deleteAccountShowConfirm: boolean;
|
||||||
|
@ -245,7 +251,9 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleSortTypeChange = this.handleSortTypeChange.bind(this);
|
this.handlePostSortTypeChange = this.handlePostSortTypeChange.bind(this);
|
||||||
|
this.handleCommentSortTypeChange =
|
||||||
|
this.handleCommentSortTypeChange.bind(this);
|
||||||
this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
|
this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
|
||||||
this.handleBioChange = this.handleBioChange.bind(this);
|
this.handleBioChange = this.handleBioChange.bind(this);
|
||||||
this.handleDiscussionLanguageChange =
|
this.handleDiscussionLanguageChange =
|
||||||
|
@ -273,9 +281,9 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
local_user: {
|
local_user: {
|
||||||
show_nsfw,
|
show_nsfw,
|
||||||
blur_nsfw,
|
blur_nsfw,
|
||||||
auto_expand,
|
|
||||||
theme,
|
theme,
|
||||||
default_sort_type,
|
default_post_sort_type,
|
||||||
|
default_comment_sort_type,
|
||||||
default_listing_type,
|
default_listing_type,
|
||||||
interface_language,
|
interface_language,
|
||||||
show_avatars,
|
show_avatars,
|
||||||
|
@ -310,9 +318,9 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
...this.state.saveUserSettingsForm,
|
...this.state.saveUserSettingsForm,
|
||||||
show_nsfw,
|
show_nsfw,
|
||||||
blur_nsfw,
|
blur_nsfw,
|
||||||
auto_expand,
|
|
||||||
theme: theme ?? "browser",
|
theme: theme ?? "browser",
|
||||||
default_sort_type,
|
default_post_sort_type,
|
||||||
|
default_comment_sort_type,
|
||||||
default_listing_type,
|
default_listing_type,
|
||||||
interface_language,
|
interface_language,
|
||||||
discussion_languages: mui.discussion_languages,
|
discussion_languages: mui.discussion_languages,
|
||||||
|
@ -348,7 +356,8 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
|
if (isBrowser()) {
|
||||||
this.setState({ themeList: await fetchThemeList() });
|
this.setState({ themeList: await fetchThemeList() });
|
||||||
|
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic) {
|
||||||
|
@ -361,6 +370,7 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
componentWillUnmount(): void {
|
||||||
// In case `interface_language` change wasn't saved.
|
// In case `interface_language` change wasn't saved.
|
||||||
|
@ -509,6 +519,7 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
value={this.state.changePasswordForm.old_password}
|
value={this.state.changePasswordForm.old_password}
|
||||||
onInput={linkEvent(this, this.handleOldPasswordChange)}
|
onInput={linkEvent(this, this.handleOldPasswordChange)}
|
||||||
label={I18NextService.i18n.t("old_password")}
|
label={I18NextService.i18n.t("old_password")}
|
||||||
|
required={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
|
@ -550,14 +561,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
<>
|
<>
|
||||||
<h2 className="h5">{I18NextService.i18n.t("blocked_users")}</h2>
|
<h2 className="h5">{I18NextService.i18n.t("blocked_users")}</h2>
|
||||||
<ul className="list-unstyled mb-0">
|
<ul className="list-unstyled mb-0">
|
||||||
{this.state.personBlocks.map(pb => (
|
{this.state.personBlocks.map(p => (
|
||||||
<li key={pb.target.id}>
|
<li key={p.id}>
|
||||||
<span>
|
<span>
|
||||||
<PersonListing person={pb.target} />
|
<PersonListing person={p} />
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm"
|
className="btn btn-sm"
|
||||||
onClick={linkEvent(
|
onClick={linkEvent(
|
||||||
{ ctx: this, recipientId: pb.target.id },
|
{ ctx: this, recipientId: p.id },
|
||||||
this.handleUnblockPerson,
|
this.handleUnblockPerson,
|
||||||
)}
|
)}
|
||||||
data-tippy-content={I18NextService.i18n.t("unblock_user")}
|
data-tippy-content={I18NextService.i18n.t("unblock_user")}
|
||||||
|
@ -594,14 +605,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
<>
|
<>
|
||||||
<h2 className="h5">{I18NextService.i18n.t("blocked_communities")}</h2>
|
<h2 className="h5">{I18NextService.i18n.t("blocked_communities")}</h2>
|
||||||
<ul className="list-unstyled mb-0">
|
<ul className="list-unstyled mb-0">
|
||||||
{this.state.communityBlocks.map(cb => (
|
{this.state.communityBlocks.map(c => (
|
||||||
<li key={cb.community.id}>
|
<li key={c.id}>
|
||||||
<span>
|
<span>
|
||||||
<CommunityLink community={cb.community} />
|
<CommunityLink community={c} />
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm"
|
className="btn btn-sm"
|
||||||
onClick={linkEvent(
|
onClick={linkEvent(
|
||||||
{ ctx: this, communityId: cb.community.id },
|
{ ctx: this, communityId: c.id },
|
||||||
this.handleUnblockCommunity,
|
this.handleUnblockCommunity,
|
||||||
)}
|
)}
|
||||||
data-tippy-content={I18NextService.i18n.t(
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
|
@ -639,14 +650,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
<>
|
<>
|
||||||
<h2 className="h5">{I18NextService.i18n.t("blocked_instances")}</h2>
|
<h2 className="h5">{I18NextService.i18n.t("blocked_instances")}</h2>
|
||||||
<ul className="list-unstyled mb-0">
|
<ul className="list-unstyled mb-0">
|
||||||
{this.state.instanceBlocks.map(ib => (
|
{this.state.instanceBlocks.map(i => (
|
||||||
<li key={ib.instance.id}>
|
<li key={i.id}>
|
||||||
<span>
|
<span>
|
||||||
{ib.instance.domain}
|
{i.domain}
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm"
|
className="btn btn-sm"
|
||||||
onClick={linkEvent(
|
onClick={linkEvent(
|
||||||
{ ctx: this, instanceId: ib.instance.id },
|
{ ctx: this, instanceId: i.id },
|
||||||
this.handleUnblockInstance,
|
this.handleUnblockInstance,
|
||||||
)}
|
)}
|
||||||
data-tippy-content={I18NextService.i18n.t("unblock_instance")}
|
data-tippy-content={I18NextService.i18n.t("unblock_instance")}
|
||||||
|
@ -900,14 +911,29 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
</form>
|
</form>
|
||||||
<form className="mb-3 row">
|
<form className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label">
|
<label className="col-sm-3 col-form-label">
|
||||||
{I18NextService.i18n.t("sort_type")}
|
{I18NextService.i18n.t("post_sort_type")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<SortSelect
|
<SortSelect
|
||||||
sort={
|
sort={
|
||||||
this.state.saveUserSettingsForm.default_sort_type ?? "Active"
|
this.state.saveUserSettingsForm.default_post_sort_type ??
|
||||||
|
"Active"
|
||||||
}
|
}
|
||||||
onChange={this.handleSortTypeChange}
|
onChange={this.handlePostSortTypeChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form className="mb-3 row">
|
||||||
|
<label className="col-sm-3 col-form-label">
|
||||||
|
{I18NextService.i18n.t("comment_sort_type")}
|
||||||
|
</label>
|
||||||
|
<div className="col-sm-9">
|
||||||
|
<CommentSortSelect
|
||||||
|
sort={
|
||||||
|
this.state.saveUserSettingsForm.default_comment_sort_type ??
|
||||||
|
"Hot"
|
||||||
|
}
|
||||||
|
onChange={this.handleCommentSortTypeChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1086,23 +1112,6 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-group mb-3">
|
|
||||||
<div className="form-check">
|
|
||||||
<input
|
|
||||||
className="form-check-input"
|
|
||||||
id="user-show-new-post-notifs"
|
|
||||||
type="checkbox"
|
|
||||||
checked={this.state.saveUserSettingsForm.show_new_post_notifs}
|
|
||||||
onChange={linkEvent(this, this.handleShowNewPostNotifs)}
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
className="form-check-label"
|
|
||||||
htmlFor="user-show-new-post-notifs"
|
|
||||||
>
|
|
||||||
{I18NextService.i18n.t("show_new_post_notifs")}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
<input
|
<input
|
||||||
|
@ -1360,7 +1369,7 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
instance =>
|
instance =>
|
||||||
instance.domain.toLowerCase().includes(text.toLowerCase()) &&
|
instance.domain.toLowerCase().includes(text.toLowerCase()) &&
|
||||||
!this.state.instanceBlocks.some(
|
!this.state.instanceBlocks.some(
|
||||||
blockedInstance => blockedInstance.instance.id === instance.id,
|
blockedInstance => blockedInstance.id === instance.id,
|
||||||
),
|
),
|
||||||
) ?? [];
|
) ?? [];
|
||||||
}
|
}
|
||||||
|
@ -1489,14 +1498,6 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShowNewPostNotifs(i: Settings, event: any) {
|
|
||||||
i.setState(
|
|
||||||
s => (
|
|
||||||
(s.saveUserSettingsForm.show_new_post_notifs = event.target.checked), s
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpenInNewTab(i: Settings, event: any) {
|
handleOpenInNewTab(i: Settings, event: any) {
|
||||||
i.setState(
|
i.setState(
|
||||||
s => (
|
s => (
|
||||||
|
@ -1600,8 +1601,16 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortTypeChange(val: SortType) {
|
handlePostSortTypeChange(val: PostSortType) {
|
||||||
this.setState(s => ((s.saveUserSettingsForm.default_sort_type = val), s));
|
this.setState(
|
||||||
|
s => ((s.saveUserSettingsForm.default_post_sort_type = val), s),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCommentSortTypeChange(val: CommentSortType) {
|
||||||
|
this.setState(
|
||||||
|
s => ((s.saveUserSettingsForm.default_comment_sort_type = val), s),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleListingTypeChange(val: ListingType) {
|
handleListingTypeChange(val: ListingType) {
|
||||||
|
@ -1701,12 +1710,12 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
const { new_password, new_password_verify, old_password } =
|
const { new_password, new_password_verify, old_password } =
|
||||||
i.state.changePasswordForm;
|
i.state.changePasswordForm;
|
||||||
|
|
||||||
if (new_password && old_password && new_password_verify) {
|
if (new_password && new_password_verify) {
|
||||||
i.setState({ changePasswordRes: LOADING_REQUEST });
|
i.setState({ changePasswordRes: LOADING_REQUEST });
|
||||||
const changePasswordRes = await HttpService.client.changePassword({
|
const changePasswordRes = await HttpService.client.changePassword({
|
||||||
new_password,
|
new_password,
|
||||||
new_password_verify,
|
new_password_verify,
|
||||||
old_password,
|
old_password: old_password || "",
|
||||||
});
|
});
|
||||||
if (changePasswordRes.state === "success") {
|
if (changePasswordRes.state === "success") {
|
||||||
snapToTop();
|
snapToTop();
|
||||||
|
@ -1763,14 +1772,13 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
local_user: {
|
local_user: {
|
||||||
show_nsfw,
|
show_nsfw,
|
||||||
blur_nsfw,
|
blur_nsfw,
|
||||||
auto_expand,
|
|
||||||
theme,
|
theme,
|
||||||
default_sort_type,
|
default_post_sort_type,
|
||||||
|
default_comment_sort_type,
|
||||||
default_listing_type,
|
default_listing_type,
|
||||||
interface_language,
|
interface_language,
|
||||||
show_avatars,
|
show_avatars,
|
||||||
show_bot_accounts,
|
show_bot_accounts,
|
||||||
show_scores,
|
|
||||||
show_read_posts,
|
show_read_posts,
|
||||||
send_notifications_to_email,
|
send_notifications_to_email,
|
||||||
email,
|
email,
|
||||||
|
@ -1803,18 +1811,17 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
|
||||||
display_name,
|
display_name,
|
||||||
bio,
|
bio,
|
||||||
matrix_user_id,
|
matrix_user_id,
|
||||||
auto_expand,
|
|
||||||
blur_nsfw,
|
blur_nsfw,
|
||||||
bot_account,
|
bot_account,
|
||||||
default_listing_type,
|
default_listing_type,
|
||||||
default_sort_type,
|
default_post_sort_type,
|
||||||
|
default_comment_sort_type,
|
||||||
discussion_languages: siteRes.data.my_user?.discussion_languages,
|
discussion_languages: siteRes.data.my_user?.discussion_languages,
|
||||||
email,
|
email,
|
||||||
interface_language,
|
interface_language,
|
||||||
open_links_in_new_tab,
|
open_links_in_new_tab,
|
||||||
send_notifications_to_email,
|
send_notifications_to_email,
|
||||||
show_read_posts,
|
show_read_posts,
|
||||||
show_scores,
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { HtmlTags } from "../common/html-tags";
|
||||||
import { Spinner } from "../common/icon";
|
import { Spinner } from "../common/icon";
|
||||||
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
verifyRes: RequestState<SuccessResponse>;
|
verifyRes: RequestState<SuccessResponse>;
|
||||||
|
@ -52,9 +53,11 @@ export class VerifyEmail extends Component<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
|
if (isBrowser()) {
|
||||||
await this.verify();
|
await this.verify();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${I18NextService.i18n.t("verify_email")} - ${
|
return `${I18NextService.i18n.t("verify_email")} - ${
|
||||||
|
|
|
@ -5,8 +5,19 @@ import {
|
||||||
setIsoData,
|
setIsoData,
|
||||||
voteDisplayMode,
|
voteDisplayMode,
|
||||||
} from "@utils/app";
|
} from "@utils/app";
|
||||||
import { getIdFromString, getQueryParams } from "@utils/helpers";
|
import {
|
||||||
import { Choice, RouteDataResponse } from "@utils/types";
|
bareRoutePush,
|
||||||
|
getIdFromString,
|
||||||
|
getQueryParams,
|
||||||
|
getQueryString,
|
||||||
|
} from "@utils/helpers";
|
||||||
|
import {
|
||||||
|
Choice,
|
||||||
|
CrossPostParams,
|
||||||
|
QueryParams,
|
||||||
|
RouteDataResponse,
|
||||||
|
StringBoolean,
|
||||||
|
} from "@utils/types";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import {
|
import {
|
||||||
|
@ -27,14 +38,22 @@ import {
|
||||||
wrapClient,
|
wrapClient,
|
||||||
} from "../../services/HttpService";
|
} from "../../services/HttpService";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { Spinner } from "../common/icon";
|
|
||||||
import { PostForm } from "./post-form";
|
import { PostForm } from "./post-form";
|
||||||
import { getHttpBaseInternal } from "../../utils/env";
|
import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
import { simpleScrollMixin } from "../mixins/scroll-mixin";
|
||||||
|
import { toast } from "../../toast";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
export interface CreatePostProps {
|
export interface CreatePostProps {
|
||||||
communityId?: number;
|
communityId?: number;
|
||||||
|
url?: string;
|
||||||
|
title?: string;
|
||||||
|
body?: string;
|
||||||
|
languageId?: number;
|
||||||
|
nsfw?: StringBoolean;
|
||||||
|
customThumbnailUrl?: string;
|
||||||
|
altText?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatePostData = RouteDataResponse<{
|
type CreatePostData = RouteDataResponse<{
|
||||||
|
@ -46,6 +65,13 @@ export function getCreatePostQueryParams(source?: string): CreatePostProps {
|
||||||
return getQueryParams<CreatePostProps>(
|
return getQueryParams<CreatePostProps>(
|
||||||
{
|
{
|
||||||
communityId: getIdFromString,
|
communityId: getIdFromString,
|
||||||
|
url: (url?: string) => url,
|
||||||
|
body: (body?: string) => body,
|
||||||
|
languageId: getIdFromString,
|
||||||
|
nsfw: (nsfw?: StringBoolean) => nsfw,
|
||||||
|
customThumbnailUrl: (customThumbnailUrl?: string) => customThumbnailUrl,
|
||||||
|
title: (title?: string) => title,
|
||||||
|
altText: (altText?: string) => altText,
|
||||||
},
|
},
|
||||||
source,
|
source,
|
||||||
);
|
);
|
||||||
|
@ -55,12 +81,17 @@ function fetchCommunitiesForOptions(client: WrappedLemmyHttp) {
|
||||||
return client.listCommunities({ limit: 30, sort: "TopMonth", type_: "All" });
|
return client.listCommunities({ limit: 30, sort: "TopMonth", type_: "All" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stringAsQueryParam(param?: string) {
|
||||||
|
return (param?.length ?? 0) > 0 ? param : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
interface CreatePostState {
|
interface CreatePostState {
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
selectedCommunityChoice?: Choice;
|
selectedCommunityChoice?: Choice;
|
||||||
initialCommunitiesRes: RequestState<ListCommunitiesResponse>;
|
initialCommunitiesRes: RequestState<ListCommunitiesResponse>;
|
||||||
isIsomorphic: boolean;
|
isIsomorphic: boolean;
|
||||||
|
resetCounter: number; // resets PostForm when changed
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatePostPathProps = Record<string, never>;
|
type CreatePostPathProps = Record<string, never>;
|
||||||
|
@ -80,9 +111,10 @@ export class CreatePost extends Component<
|
||||||
private isoData = setIsoData<CreatePostData>(this.context);
|
private isoData = setIsoData<CreatePostData>(this.context);
|
||||||
state: CreatePostState = {
|
state: CreatePostState = {
|
||||||
siteRes: this.isoData.site_res,
|
siteRes: this.isoData.site_res,
|
||||||
loading: true,
|
loading: false,
|
||||||
initialCommunitiesRes: EMPTY_REQUEST,
|
initialCommunitiesRes: EMPTY_REQUEST,
|
||||||
isIsomorphic: false,
|
isIsomorphic: false,
|
||||||
|
resetCounter: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: CreatePostRouteProps, context: any) {
|
constructor(props: CreatePostRouteProps, context: any) {
|
||||||
|
@ -91,8 +123,16 @@ export class CreatePost extends Component<
|
||||||
this.handlePostCreate = this.handlePostCreate.bind(this);
|
this.handlePostCreate = this.handlePostCreate.bind(this);
|
||||||
this.handleSelectedCommunityChange =
|
this.handleSelectedCommunityChange =
|
||||||
this.handleSelectedCommunityChange.bind(this);
|
this.handleSelectedCommunityChange.bind(this);
|
||||||
|
this.handleTitleBlur = this.handleTitleBlur.bind(this);
|
||||||
|
this.handleUrlBlur = this.handleUrlBlur.bind(this);
|
||||||
|
this.handleBodyBlur = this.handleBodyBlur.bind(this);
|
||||||
|
this.handleLanguageChange = this.handleLanguageChange.bind(this);
|
||||||
|
this.handleNsfwChange = this.handleNsfwChange.bind(this);
|
||||||
|
this.handleThumbnailUrlBlur = this.handleThumbnailUrlBlur.bind(this);
|
||||||
|
this.handleAltTextBlur = this.handleAltTextBlur.bind(this);
|
||||||
|
this.handleCopySuggestedTitle = this.handleCopySuggestedTitle.bind(this);
|
||||||
|
|
||||||
// Only fetch the data if coming from another route
|
// Only fetch the data if coming from another routeupdate
|
||||||
if (FirstLoadService.isFirstLoad) {
|
if (FirstLoadService.isFirstLoad) {
|
||||||
const { communityResponse: communityRes, initialCommunitiesRes } =
|
const { communityResponse: communityRes, initialCommunitiesRes } =
|
||||||
this.isoData.routeData;
|
this.isoData.routeData;
|
||||||
|
@ -131,9 +171,9 @@ export class CreatePost extends Component<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
// TODO test this
|
// TODO test this
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
const { communityId } = this.props;
|
const { communityId } = this.props;
|
||||||
|
|
||||||
const initialCommunitiesRes = await fetchCommunitiesForOptions(
|
const initialCommunitiesRes = await fetchCommunitiesForOptions(
|
||||||
|
@ -154,6 +194,30 @@ export class CreatePost extends Component<
|
||||||
loading: false,
|
loading: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const locationState = this.props.history.location.state as
|
||||||
|
| CrossPostParams
|
||||||
|
| undefined;
|
||||||
|
if (locationState) {
|
||||||
|
this.updateUrl({
|
||||||
|
title: locationState.name,
|
||||||
|
url: locationState.url,
|
||||||
|
body: locationState.body,
|
||||||
|
altText: locationState.altText,
|
||||||
|
nsfw: locationState.nsfw,
|
||||||
|
languageId: locationState.languageId,
|
||||||
|
});
|
||||||
|
this.setState(s => ({ resetCounter: s.resetCounter + 1 }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps: CreatePostRouteProps) {
|
||||||
|
if (bareRoutePush(this.props, nextProps)) {
|
||||||
|
this.setState(s => ({ resetCounter: s.resetCounter + 1 }));
|
||||||
|
}
|
||||||
|
if (this.props.communityId !== nextProps.communityId) {
|
||||||
|
this.fetchCommunity(nextProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,11 +228,28 @@ export class CreatePost extends Component<
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { selectedCommunityChoice, siteRes } = this.state;
|
const { selectedCommunityChoice, siteRes, loading } = this.state;
|
||||||
|
const {
|
||||||
|
body,
|
||||||
|
communityId,
|
||||||
|
customThumbnailUrl,
|
||||||
|
languageId,
|
||||||
|
title,
|
||||||
|
nsfw,
|
||||||
|
url,
|
||||||
|
altText,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
const locationState = this.props.history.location.state as
|
const params: PostFormParams = {
|
||||||
| PostFormParams
|
name: title,
|
||||||
| undefined;
|
url,
|
||||||
|
body,
|
||||||
|
community_id: communityId,
|
||||||
|
custom_thumbnail: customThumbnailUrl,
|
||||||
|
language_id: languageId,
|
||||||
|
nsfw: nsfw === "true",
|
||||||
|
alt_text: altText,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="create-post container-lg">
|
<div className="create-post container-lg">
|
||||||
|
@ -176,22 +257,13 @@ export class CreatePost extends Component<
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
{this.state.loading ? (
|
|
||||||
<h5>
|
|
||||||
<Spinner large />
|
|
||||||
</h5>
|
|
||||||
) : (
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div
|
<div id="createPostForm" className="col-12 col-lg-6 offset-lg-3 mb-4">
|
||||||
id="createPostForm"
|
<h1 className="h4 mb-4">{I18NextService.i18n.t("create_post")}</h1>
|
||||||
className="col-12 col-lg-6 offset-lg-3 mb-4"
|
|
||||||
>
|
|
||||||
<h1 className="h4 mb-4">
|
|
||||||
{I18NextService.i18n.t("create_post")}
|
|
||||||
</h1>
|
|
||||||
<PostForm
|
<PostForm
|
||||||
|
key={this.state.resetCounter}
|
||||||
onCreate={this.handlePostCreate}
|
onCreate={this.handlePostCreate}
|
||||||
params={locationState}
|
params={params}
|
||||||
enableDownvotes={enableDownvotes(siteRes)}
|
enableDownvotes={enableDownvotes(siteRes)}
|
||||||
voteDisplayMode={voteDisplayMode(siteRes)}
|
voteDisplayMode={voteDisplayMode(siteRes)}
|
||||||
enableNsfw={enableNsfw(siteRes)}
|
enableNsfw={enableNsfw(siteRes)}
|
||||||
|
@ -204,31 +276,52 @@ export class CreatePost extends Component<
|
||||||
? this.state.initialCommunitiesRes.data.communities
|
? this.state.initialCommunitiesRes.data.communities
|
||||||
: []
|
: []
|
||||||
}
|
}
|
||||||
|
loading={loading}
|
||||||
|
onBodyBlur={this.handleBodyBlur}
|
||||||
|
onLanguageChange={this.handleLanguageChange}
|
||||||
|
onTitleBlur={this.handleTitleBlur}
|
||||||
|
onUrlBlur={this.handleUrlBlur}
|
||||||
|
onThumbnailUrlBlur={this.handleThumbnailUrlBlur}
|
||||||
|
onNsfwChange={this.handleNsfwChange}
|
||||||
|
onAltTextBlur={this.handleAltTextBlur}
|
||||||
|
onCopySuggestedTitle={this.handleCopySuggestedTitle}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUrl({ communityId }: Partial<CreatePostProps>) {
|
async updateUrl(props: Partial<CreatePostProps>) {
|
||||||
const locationState = this.props.history.location.state as
|
const {
|
||||||
| PostFormParams
|
body,
|
||||||
| undefined;
|
communityId,
|
||||||
|
customThumbnailUrl,
|
||||||
|
languageId,
|
||||||
|
nsfw,
|
||||||
|
url,
|
||||||
|
title,
|
||||||
|
altText,
|
||||||
|
} = {
|
||||||
|
...this.props,
|
||||||
|
...props,
|
||||||
|
};
|
||||||
|
|
||||||
const url = new URL(location.href);
|
const createPostQueryParams: QueryParams<CreatePostProps> = {
|
||||||
|
body: stringAsQueryParam(body),
|
||||||
|
communityId: communityId?.toString(),
|
||||||
|
customThumbnailUrl: stringAsQueryParam(customThumbnailUrl),
|
||||||
|
languageId: languageId?.toString(),
|
||||||
|
title: stringAsQueryParam(title),
|
||||||
|
nsfw,
|
||||||
|
url: stringAsQueryParam(url),
|
||||||
|
altText: stringAsQueryParam(altText),
|
||||||
|
};
|
||||||
|
|
||||||
const newId = communityId?.toString();
|
this.props.history.replace({
|
||||||
|
pathname: "/create_post",
|
||||||
if (newId !== undefined) {
|
search: getQueryString(createPostQueryParams),
|
||||||
url.searchParams.set("communityId", newId);
|
});
|
||||||
} else {
|
|
||||||
url.searchParams.delete("communityId");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This bypasses the router and doesn't update the query props.
|
|
||||||
window.history.replaceState(locationState, "", url);
|
|
||||||
|
|
||||||
await this.fetchCommunity({ communityId });
|
await this.fetchCommunity({ communityId });
|
||||||
}
|
}
|
||||||
|
@ -239,16 +332,51 @@ export class CreatePost extends Component<
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async handlePostCreate(form: CreatePostI) {
|
handleTitleBlur(title: string) {
|
||||||
|
this.updateUrl({ title });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleUrlBlur(url: string) {
|
||||||
|
this.updateUrl({ url });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBodyBlur(body: string) {
|
||||||
|
this.updateUrl({ body });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLanguageChange(languageId: number) {
|
||||||
|
this.updateUrl({ languageId });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNsfwChange(nsfw: StringBoolean) {
|
||||||
|
this.updateUrl({ nsfw });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleThumbnailUrlBlur(customThumbnailUrl: string) {
|
||||||
|
this.updateUrl({ customThumbnailUrl });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAltTextBlur(altText: string) {
|
||||||
|
this.updateUrl({ altText });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCopySuggestedTitle(url: string, title: string) {
|
||||||
|
this.updateUrl({ url, title });
|
||||||
|
}
|
||||||
|
|
||||||
|
async handlePostCreate(form: CreatePostI, bypassNavWarning: () => void) {
|
||||||
|
this.setState({ loading: true });
|
||||||
const res = await HttpService.client.createPost(form);
|
const res = await HttpService.client.createPost(form);
|
||||||
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
const postId = res.data.post_view.post.id;
|
const postId = res.data.post_view.post.id;
|
||||||
|
bypassNavWarning();
|
||||||
this.props.history.replace(`/post/${postId}`);
|
this.props.history.replace(`/post/${postId}`);
|
||||||
} else {
|
} else if (res.state === "failed") {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
});
|
});
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@ import {
|
||||||
validURL,
|
validURL,
|
||||||
} from "@utils/helpers";
|
} from "@utils/helpers";
|
||||||
import { isImage } from "@utils/media";
|
import { isImage } from "@utils/media";
|
||||||
import { Choice } from "@utils/types";
|
import { Choice, StringBoolean } from "@utils/types";
|
||||||
import autosize from "autosize";
|
import autosize from "autosize";
|
||||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
import { Component, InfernoNode, createRef, linkEvent } from "inferno";
|
||||||
import { Prompt } from "inferno-router";
|
import { Prompt } from "inferno-router";
|
||||||
import {
|
import {
|
||||||
CommunityView,
|
CommunityView,
|
||||||
|
@ -27,7 +27,7 @@ import {
|
||||||
ghostArchiveUrl,
|
ghostArchiveUrl,
|
||||||
postMarkdownFieldCharacterLimit,
|
postMarkdownFieldCharacterLimit,
|
||||||
relTags,
|
relTags,
|
||||||
trendingFetchLimit,
|
similarPostFetchLimit,
|
||||||
webArchiveUrl,
|
webArchiveUrl,
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { PostFormParams } from "../../interfaces";
|
import { PostFormParams } from "../../interfaces";
|
||||||
|
@ -44,6 +44,15 @@ import { LanguageSelect } from "../common/language-select";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
import { SearchableSelect } from "../common/searchable-select";
|
import { SearchableSelect } from "../common/searchable-select";
|
||||||
import { PostListings } from "./post-listings";
|
import { PostListings } from "./post-listings";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import isMagnetLink, {
|
||||||
|
extractMagnetLinkDownloadName,
|
||||||
|
} from "@utils/media/is-magnet-link";
|
||||||
|
import {
|
||||||
|
getUnixTimeLemmy,
|
||||||
|
getUnixTime,
|
||||||
|
unixTimeToLocalDateStr,
|
||||||
|
} from "@utils/helpers/get-unix-time";
|
||||||
|
|
||||||
const MAX_POST_TITLE_LENGTH = 200;
|
const MAX_POST_TITLE_LENGTH = 200;
|
||||||
|
|
||||||
|
@ -54,14 +63,23 @@ interface PostFormProps {
|
||||||
siteLanguages: number[];
|
siteLanguages: number[];
|
||||||
params?: PostFormParams;
|
params?: PostFormParams;
|
||||||
onCancel?(): void;
|
onCancel?(): void;
|
||||||
onCreate?(form: CreatePost): void;
|
onCreate?(form: CreatePost, bypassNavWarning: () => void): void;
|
||||||
onEdit?(form: EditPost): void;
|
onEdit?(form: EditPost, bypassNavWarning: () => void): void;
|
||||||
enableNsfw?: boolean;
|
enableNsfw?: boolean;
|
||||||
enableDownvotes?: boolean;
|
enableDownvotes?: boolean;
|
||||||
voteDisplayMode: LocalUserVoteDisplayMode;
|
voteDisplayMode: LocalUserVoteDisplayMode;
|
||||||
selectedCommunityChoice?: Choice;
|
selectedCommunityChoice?: Choice;
|
||||||
onSelectCommunity?: (choice: Choice) => void;
|
onSelectCommunity?: (choice: Choice) => void;
|
||||||
initialCommunities?: CommunityView[];
|
initialCommunities?: CommunityView[];
|
||||||
|
loading: boolean;
|
||||||
|
onTitleBlur?: (title: string) => void;
|
||||||
|
onUrlBlur?: (url: string) => void;
|
||||||
|
onBodyBlur?: (body: string) => void;
|
||||||
|
onLanguageChange?: (languageId?: number) => void;
|
||||||
|
onNsfwChange?: (nsfw: StringBoolean) => void;
|
||||||
|
onThumbnailUrlBlur?: (thumbnailUrl: string) => void;
|
||||||
|
onAltTextBlur?: (altText: string) => void;
|
||||||
|
onCopySuggestedTitle?: (url: string, title: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PostFormState {
|
interface PostFormState {
|
||||||
|
@ -75,8 +93,9 @@ interface PostFormState {
|
||||||
honeypot?: string;
|
honeypot?: string;
|
||||||
custom_thumbnail?: string;
|
custom_thumbnail?: string;
|
||||||
alt_text?: string;
|
alt_text?: string;
|
||||||
|
// Javascript treats this field as a string, that can't have timezone info.
|
||||||
|
scheduled_publish_time?: string;
|
||||||
};
|
};
|
||||||
loading: boolean;
|
|
||||||
suggestedPostsRes: RequestState<SearchResponse>;
|
suggestedPostsRes: RequestState<SearchResponse>;
|
||||||
metadataRes: RequestState<GetSiteMetadataResponse>;
|
metadataRes: RequestState<GetSiteMetadataResponse>;
|
||||||
imageLoading: boolean;
|
imageLoading: boolean;
|
||||||
|
@ -85,6 +104,7 @@ interface PostFormState {
|
||||||
communitySearchOptions: Choice[];
|
communitySearchOptions: Choice[];
|
||||||
previewMode: boolean;
|
previewMode: boolean;
|
||||||
submitted: boolean;
|
submitted: boolean;
|
||||||
|
bypassNavWarning: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePostSubmit(i: PostForm, event: any) {
|
function handlePostSubmit(i: PostForm, event: any) {
|
||||||
|
@ -93,13 +113,17 @@ function handlePostSubmit(i: PostForm, event: any) {
|
||||||
if ((i.state.form.url ?? "") === "") {
|
if ((i.state.form.url ?? "") === "") {
|
||||||
i.setState(s => ((s.form.url = undefined), s));
|
i.setState(s => ((s.form.url = undefined), s));
|
||||||
}
|
}
|
||||||
i.setState({ loading: true, submitted: true });
|
// This forces `props.loading` to become true, then false, to enable the
|
||||||
|
// submit button again.
|
||||||
|
i.setState({ submitted: true });
|
||||||
|
|
||||||
const pForm = i.state.form;
|
const pForm = i.state.form;
|
||||||
const pv = i.props.post_view;
|
const pv = i.props.post_view;
|
||||||
|
const scheduled_publish_time = getUnixTimeLemmy(pForm.scheduled_publish_time);
|
||||||
|
|
||||||
if (pv) {
|
if (pv) {
|
||||||
i.props.onEdit?.({
|
i.props.onEdit?.(
|
||||||
|
{
|
||||||
post_id: pv.post.id,
|
post_id: pv.post.id,
|
||||||
name: pForm.name,
|
name: pForm.name,
|
||||||
url: pForm.url,
|
url: pForm.url,
|
||||||
|
@ -108,9 +132,15 @@ function handlePostSubmit(i: PostForm, event: any) {
|
||||||
language_id: pForm.language_id,
|
language_id: pForm.language_id,
|
||||||
custom_thumbnail: pForm.custom_thumbnail,
|
custom_thumbnail: pForm.custom_thumbnail,
|
||||||
alt_text: pForm.alt_text,
|
alt_text: pForm.alt_text,
|
||||||
});
|
scheduled_publish_time,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
i.setState({ bypassNavWarning: true });
|
||||||
|
},
|
||||||
|
);
|
||||||
} else if (pForm.name && pForm.community_id) {
|
} else if (pForm.name && pForm.community_id) {
|
||||||
i.props.onCreate?.({
|
i.props.onCreate?.(
|
||||||
|
{
|
||||||
name: pForm.name,
|
name: pForm.name,
|
||||||
community_id: pForm.community_id,
|
community_id: pForm.community_id,
|
||||||
url: pForm.url,
|
url: pForm.url,
|
||||||
|
@ -120,21 +150,38 @@ function handlePostSubmit(i: PostForm, event: any) {
|
||||||
honeypot: pForm.honeypot,
|
honeypot: pForm.honeypot,
|
||||||
custom_thumbnail: pForm.custom_thumbnail,
|
custom_thumbnail: pForm.custom_thumbnail,
|
||||||
alt_text: pForm.alt_text,
|
alt_text: pForm.alt_text,
|
||||||
});
|
scheduled_publish_time,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
i.setState({ bypassNavWarning: true });
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function copySuggestedTitle(d: { i: PostForm; suggestedTitle?: string }) {
|
function copySuggestedTitle({
|
||||||
const sTitle = d.suggestedTitle;
|
i,
|
||||||
if (sTitle) {
|
suggestedTitle,
|
||||||
d.i.setState(
|
}: {
|
||||||
s => ((s.form.name = sTitle?.substring(0, MAX_POST_TITLE_LENGTH)), s),
|
i: PostForm;
|
||||||
|
suggestedTitle?: string;
|
||||||
|
}) {
|
||||||
|
if (suggestedTitle) {
|
||||||
|
i.setState(
|
||||||
|
s => (
|
||||||
|
(s.form.name = suggestedTitle?.substring(0, MAX_POST_TITLE_LENGTH)), s
|
||||||
|
),
|
||||||
);
|
);
|
||||||
d.i.setState({ suggestedPostsRes: EMPTY_REQUEST });
|
i.setState({ suggestedPostsRes: EMPTY_REQUEST });
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const textarea: any = document.getElementById("post-title");
|
if (i.postTitleRef.current) {
|
||||||
autosize.update(textarea);
|
autosize.update(i.postTitleRef.current);
|
||||||
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
|
i.updateUrl(() =>
|
||||||
|
i.props.onCopySuggestedTitle?.(i.state.form.url!, suggestedTitle),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +200,28 @@ function handlePostUrlChange(i: PostForm, event: any) {
|
||||||
i.fetchPageTitle();
|
i.fetchPageTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handlePostUrlBlur(i: PostForm, event: any) {
|
||||||
|
i.updateUrl(() => i.props.onUrlBlur?.(event.target.value));
|
||||||
|
}
|
||||||
|
|
||||||
function handlePostNsfwChange(i: PostForm, event: any) {
|
function handlePostNsfwChange(i: PostForm, event: any) {
|
||||||
i.setState(s => ((s.form.nsfw = event.target.checked), s));
|
i.setState(s => ((s.form.nsfw = event.target.checked), s));
|
||||||
|
|
||||||
|
i.updateUrl(() =>
|
||||||
|
i.props.onNsfwChange?.(event.target.checked ? "true" : "false"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePostScheduleChange(i: PostForm, event: any) {
|
||||||
|
const scheduled_publish_time = event.target.value;
|
||||||
|
|
||||||
|
i.setState(prev => ({
|
||||||
|
...prev,
|
||||||
|
form: {
|
||||||
|
...prev.form,
|
||||||
|
scheduled_publish_time,
|
||||||
|
},
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleHoneyPotChange(i: PostForm, event: any) {
|
function handleHoneyPotChange(i: PostForm, event: any) {
|
||||||
|
@ -165,10 +232,18 @@ function handleAltTextChange(i: PostForm, event: any) {
|
||||||
i.setState(s => ((s.form.alt_text = event.target.value), s));
|
i.setState(s => ((s.form.alt_text = event.target.value), s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleAltTextBlur(i: PostForm, event: any) {
|
||||||
|
i.updateUrl(() => i.props.onAltTextBlur?.(event.target.value));
|
||||||
|
}
|
||||||
|
|
||||||
function handleCustomThumbnailChange(i: PostForm, event: any) {
|
function handleCustomThumbnailChange(i: PostForm, event: any) {
|
||||||
i.setState(s => ((s.form.custom_thumbnail = event.target.value), s));
|
i.setState(s => ((s.form.custom_thumbnail = event.target.value), s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleCustomThumbnailBlur(i: PostForm, event: any) {
|
||||||
|
i.updateUrl(() => i.props.onThumbnailUrlBlur?.(event.target.value));
|
||||||
|
}
|
||||||
|
|
||||||
function handleCancel(i: PostForm) {
|
function handleCancel(i: PostForm) {
|
||||||
i.props.onCancel?.();
|
i.props.onCancel?.();
|
||||||
}
|
}
|
||||||
|
@ -192,8 +267,6 @@ function handleImageUpload(i: PostForm, event: any) {
|
||||||
i.setState({ imageLoading: true });
|
i.setState({ imageLoading: true });
|
||||||
|
|
||||||
HttpService.client.uploadImage({ image: file }).then(res => {
|
HttpService.client.uploadImage({ image: file }).then(res => {
|
||||||
console.log("pictrs upload:");
|
|
||||||
console.log(res);
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
if (res.data.msg === "ok") {
|
if (res.data.msg === "ok") {
|
||||||
i.state.form.url = res.data.url;
|
i.state.form.url = res.data.url;
|
||||||
|
@ -219,6 +292,10 @@ function handlePostNameChange(i: PostForm, event: any) {
|
||||||
i.fetchSimilarPosts();
|
i.fetchSimilarPosts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handlePostNameBlur(i: PostForm, event: any) {
|
||||||
|
i.updateUrl(() => i.props.onTitleBlur?.(event.target.value));
|
||||||
|
}
|
||||||
|
|
||||||
function handleImageDelete(i: PostForm) {
|
function handleImageDelete(i: PostForm) {
|
||||||
const { imageDeleteUrl } = i.state;
|
const { imageDeleteUrl } = i.state;
|
||||||
|
|
||||||
|
@ -240,27 +317,32 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
suggestedPostsRes: EMPTY_REQUEST,
|
suggestedPostsRes: EMPTY_REQUEST,
|
||||||
metadataRes: EMPTY_REQUEST,
|
metadataRes: EMPTY_REQUEST,
|
||||||
form: {},
|
form: {},
|
||||||
loading: false,
|
|
||||||
imageLoading: false,
|
imageLoading: false,
|
||||||
imageDeleteUrl: "",
|
imageDeleteUrl: "",
|
||||||
communitySearchLoading: false,
|
communitySearchLoading: false,
|
||||||
previewMode: false,
|
previewMode: false,
|
||||||
communitySearchOptions: [],
|
communitySearchOptions: [],
|
||||||
submitted: false,
|
submitted: false,
|
||||||
|
bypassNavWarning: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
postTitleRef = createRef<HTMLTextAreaElement>();
|
||||||
|
|
||||||
constructor(props: PostFormProps, context: any) {
|
constructor(props: PostFormProps, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.fetchSimilarPosts = debounce(this.fetchSimilarPosts.bind(this));
|
this.fetchSimilarPosts = debounce(this.fetchSimilarPosts.bind(this));
|
||||||
this.fetchPageTitle = debounce(this.fetchPageTitle.bind(this));
|
this.fetchPageTitle = debounce(this.fetchPageTitle.bind(this));
|
||||||
this.handlePostBodyChange = this.handlePostBodyChange.bind(this);
|
this.handlePostBodyChange = this.handlePostBodyChange.bind(this);
|
||||||
|
this.handlePostBodyBlur = this.handlePostBodyBlur.bind(this);
|
||||||
this.handleLanguageChange = this.handleLanguageChange.bind(this);
|
this.handleLanguageChange = this.handleLanguageChange.bind(this);
|
||||||
this.handleCommunitySelect = this.handleCommunitySelect.bind(this);
|
this.handleCommunitySelect = this.handleCommunitySelect.bind(this);
|
||||||
|
this.updateUrl = this.updateUrl.bind(this);
|
||||||
|
|
||||||
const { post_view, selectedCommunityChoice, params } = this.props;
|
const { post_view, selectedCommunityChoice, params } = this.props;
|
||||||
|
|
||||||
// Means its an edit
|
// Means its an edit
|
||||||
if (post_view) {
|
if (post_view) {
|
||||||
|
const unix = getUnixTime(post_view.post.scheduled_publish_time);
|
||||||
|
var scheduled_publish_time = unixTimeToLocalDateStr(unix);
|
||||||
this.state = {
|
this.state = {
|
||||||
...this.state,
|
...this.state,
|
||||||
form: {
|
form: {
|
||||||
|
@ -272,6 +354,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
language_id: post_view.post.language_id,
|
language_id: post_view.post.language_id,
|
||||||
custom_thumbnail: post_view.post.thumbnail_url,
|
custom_thumbnail: post_view.post.thumbnail_url,
|
||||||
alt_text: post_view.post.alt_text,
|
alt_text: post_view.post.alt_text,
|
||||||
|
scheduled_publish_time,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else if (selectedCommunityChoice) {
|
} else if (selectedCommunityChoice) {
|
||||||
|
@ -306,18 +389,26 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentWillMount() {
|
||||||
const textarea: any = document.getElementById("post-title");
|
if (this.state.form.url && isBrowser()) {
|
||||||
|
this.fetchPageTitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (textarea) {
|
componentDidMount() {
|
||||||
autosize(textarea);
|
if (this.postTitleRef.current) {
|
||||||
|
autosize(this.postTitleRef.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(
|
componentWillReceiveProps(
|
||||||
nextProps: Readonly<{ children?: InfernoNode } & PostFormProps>,
|
nextProps: Readonly<{ children?: InfernoNode } & PostFormProps>,
|
||||||
): void {
|
): void {
|
||||||
if (this.props !== nextProps) {
|
if (
|
||||||
|
this.props.selectedCommunityChoice?.value !==
|
||||||
|
nextProps.selectedCommunityChoice?.value &&
|
||||||
|
nextProps.selectedCommunityChoice
|
||||||
|
) {
|
||||||
this.setState(
|
this.setState(
|
||||||
s => (
|
s => (
|
||||||
(s.form.community_id = getIdFromString(
|
(s.form.community_id = getIdFromString(
|
||||||
|
@ -326,6 +417,33 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
s
|
s
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
this.setState({
|
||||||
|
communitySearchOptions: [nextProps.selectedCommunityChoice].concat(
|
||||||
|
(nextProps.initialCommunities?.map(communityToChoice) ?? []).filter(
|
||||||
|
option => option.value !== nextProps.selectedCommunityChoice?.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!this.props.initialCommunities?.length &&
|
||||||
|
nextProps.initialCommunities?.length
|
||||||
|
) {
|
||||||
|
this.setState({
|
||||||
|
communitySearchOptions:
|
||||||
|
nextProps.initialCommunities?.map(communityToChoice) ?? [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.props.loading && !nextProps.loading) {
|
||||||
|
this.setState({ submitted: false, bypassNavWarning: false });
|
||||||
|
}
|
||||||
|
if (this.props.params !== nextProps.params && nextProps.params) {
|
||||||
|
const params = nextProps.params;
|
||||||
|
for (const k in params) {
|
||||||
|
if (this.props.params?.[k] !== params[k]) {
|
||||||
|
this.setState(s => ({ form: { ...s.form, [k]: params[k] } }));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +462,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
this.state.form.name ||
|
this.state.form.name ||
|
||||||
this.state.form.url ||
|
this.state.form.url ||
|
||||||
this.state.form.body
|
this.state.form.body
|
||||||
) && !this.state.submitted
|
) && !this.state.bypassNavWarning
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
|
@ -356,6 +474,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
value={this.state.form.name}
|
value={this.state.form.name}
|
||||||
id="post-title"
|
id="post-title"
|
||||||
onInput={linkEvent(this, handlePostNameChange)}
|
onInput={linkEvent(this, handlePostNameChange)}
|
||||||
|
onBlur={linkEvent(this, handlePostNameBlur)}
|
||||||
className={`form-control ${
|
className={`form-control ${
|
||||||
!validTitle(this.state.form.name) && "is-invalid"
|
!validTitle(this.state.form.name) && "is-invalid"
|
||||||
}`}
|
}`}
|
||||||
|
@ -363,6 +482,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
rows={1}
|
rows={1}
|
||||||
minLength={3}
|
minLength={3}
|
||||||
maxLength={MAX_POST_TITLE_LENGTH}
|
maxLength={MAX_POST_TITLE_LENGTH}
|
||||||
|
ref={this.postTitleRef}
|
||||||
/>
|
/>
|
||||||
{!validTitle(this.state.form.name) && (
|
{!validTitle(this.state.form.name) && (
|
||||||
<div className="invalid-feedback">
|
<div className="invalid-feedback">
|
||||||
|
@ -385,6 +505,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
className="form-control mb-3"
|
className="form-control mb-3"
|
||||||
value={url}
|
value={url}
|
||||||
onInput={linkEvent(this, handlePostUrlChange)}
|
onInput={linkEvent(this, handlePostUrlChange)}
|
||||||
|
onBlur={linkEvent(this, handlePostUrlBlur)}
|
||||||
onPaste={linkEvent(this, handleImageUploadPaste)}
|
onPaste={linkEvent(this, handleImageUploadPaste)}
|
||||||
/>
|
/>
|
||||||
{this.renderSuggestedTitleCopy()}
|
{this.renderSuggestedTitleCopy()}
|
||||||
|
@ -500,6 +621,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
className="form-control mb-3"
|
className="form-control mb-3"
|
||||||
value={this.state.form.custom_thumbnail}
|
value={this.state.form.custom_thumbnail}
|
||||||
onInput={linkEvent(this, handleCustomThumbnailChange)}
|
onInput={linkEvent(this, handleCustomThumbnailChange)}
|
||||||
|
onBlur={linkEvent(this, handleCustomThumbnailBlur)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -514,6 +636,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
initialContent={this.state.form.body}
|
initialContent={this.state.form.body}
|
||||||
placeholder={I18NextService.i18n.t("optional")}
|
placeholder={I18NextService.i18n.t("optional")}
|
||||||
onContentChange={this.handlePostBodyChange}
|
onContentChange={this.handlePostBodyChange}
|
||||||
|
onContentBlur={this.handlePostBodyBlur}
|
||||||
allLanguages={this.props.allLanguages}
|
allLanguages={this.props.allLanguages}
|
||||||
siteLanguages={this.props.siteLanguages}
|
siteLanguages={this.props.siteLanguages}
|
||||||
hideNavigationWarnings
|
hideNavigationWarnings
|
||||||
|
@ -543,6 +666,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
id="post-alt-text"
|
id="post-alt-text"
|
||||||
value={this.state.form.alt_text}
|
value={this.state.form.alt_text}
|
||||||
onInput={linkEvent(this, handleAltTextChange)}
|
onInput={linkEvent(this, handleAltTextChange)}
|
||||||
|
onBlur={linkEvent(this, handleAltTextBlur)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -584,6 +708,23 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div className="mb-3 row">
|
||||||
|
<label className="col-sm-2 col-form-label" htmlFor="post-schedule">
|
||||||
|
{I18NextService.i18n.t("scheduled_publish_time")}
|
||||||
|
</label>
|
||||||
|
<div className="col-sm-10">
|
||||||
|
<input
|
||||||
|
type="datetime-local"
|
||||||
|
value={this.state.form.scheduled_publish_time}
|
||||||
|
min={unixTimeToLocalDateStr(Date.now())}
|
||||||
|
id="post-schedule"
|
||||||
|
className="form-control mb-3"
|
||||||
|
onInput={linkEvent(this, handlePostScheduleChange)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
autoComplete="false"
|
autoComplete="false"
|
||||||
|
@ -597,11 +738,15 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<button
|
<button
|
||||||
disabled={!this.state.form.community_id || this.state.loading}
|
disabled={
|
||||||
|
!this.state.form.community_id ||
|
||||||
|
this.props.loading ||
|
||||||
|
this.state.submitted
|
||||||
|
}
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary me-2"
|
className="btn btn-secondary me-2"
|
||||||
>
|
>
|
||||||
{this.state.loading ? (
|
{this.props.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : this.props.post_view ? (
|
) : this.props.post_view ? (
|
||||||
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
|
@ -705,12 +850,27 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
async fetchPageTitle() {
|
async fetchPageTitle() {
|
||||||
const url = this.state.form.url;
|
const url = this.state.form.url;
|
||||||
if (url && validURL(url)) {
|
if (url && validURL(url)) {
|
||||||
|
// If its a magnet link, fill in the download name
|
||||||
|
if (isMagnetLink(url)) {
|
||||||
|
const title = extractMagnetLinkDownloadName(url);
|
||||||
|
if (title) {
|
||||||
|
this.setState({
|
||||||
|
metadataRes: {
|
||||||
|
state: "success",
|
||||||
|
data: {
|
||||||
|
metadata: { title },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.setState({ metadataRes: LOADING_REQUEST });
|
this.setState({ metadataRes: LOADING_REQUEST });
|
||||||
this.setState({
|
this.setState({
|
||||||
metadataRes: await HttpService.client.getSiteMetadata({ url }),
|
metadataRes: await HttpService.client.getSiteMetadata({ url }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fetchSimilarPosts() {
|
async fetchSimilarPosts() {
|
||||||
const q = this.state.form.name;
|
const q = this.state.form.name;
|
||||||
|
@ -724,7 +884,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
listing_type: "All",
|
listing_type: "All",
|
||||||
community_id: this.state.form.community_id,
|
community_id: this.state.form.community_id,
|
||||||
page: 1,
|
page: 1,
|
||||||
limit: trendingFetchLimit,
|
limit: similarPostFetchLimit,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -734,8 +894,13 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
this.setState(s => ((s.form.body = val), s));
|
this.setState(s => ((s.form.body = val), s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlePostBodyBlur(val: string) {
|
||||||
|
this.updateUrl(() => this.props.onBodyBlur?.(val));
|
||||||
|
}
|
||||||
|
|
||||||
handleLanguageChange(val: number[]) {
|
handleLanguageChange(val: number[]) {
|
||||||
this.setState(s => ((s.form.language_id = val.at(0)), s));
|
this.setState(s => ((s.form.language_id = val.at(0)), s));
|
||||||
|
this.updateUrl(() => this.props.onLanguageChange?.(val.at(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommunitySearch = debounce(async (text: string) => {
|
handleCommunitySearch = debounce(async (text: string) => {
|
||||||
|
@ -762,8 +927,12 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
});
|
});
|
||||||
|
|
||||||
handleCommunitySelect(choice: Choice) {
|
handleCommunitySelect(choice: Choice) {
|
||||||
if (this.props.onSelectCommunity) {
|
this.updateUrl(() => this.props.onSelectCommunity?.(choice));
|
||||||
this.props.onSelectCommunity(choice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateUrl(update: () => void) {
|
||||||
|
this.setState({ bypassNavWarning: true });
|
||||||
|
update();
|
||||||
|
this.setState({ bypassNavWarning: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { myAuth, setIsoData } from "@utils/app";
|
import { myAuth, setIsoData } from "@utils/app";
|
||||||
import { canShare, share } from "@utils/browser";
|
import { canShare, share } from "@utils/browser";
|
||||||
import { getExternalHost, getHttpBase } from "@utils/env";
|
import { getExternalHost, getHttpBase } from "@utils/env";
|
||||||
import { futureDaysToUnixTime, hostname } from "@utils/helpers";
|
import { formatPastDate, futureDaysToUnixTime, hostname } from "@utils/helpers";
|
||||||
import { isImage, isVideo } from "@utils/media";
|
import { isImage, isVideo } from "@utils/media";
|
||||||
import { canAdmin, canMod } from "@utils/roles";
|
import { canAdmin, canMod } from "@utils/roles";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
|
import { T } from "inferno-i18next-dess";
|
||||||
import {
|
import {
|
||||||
AddAdmin,
|
AddAdmin,
|
||||||
AddModToCommunity,
|
AddModToCommunity,
|
||||||
|
@ -33,7 +34,7 @@ import {
|
||||||
SavePost,
|
SavePost,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { relTags } from "../../config";
|
import { relTags, torrentHelpUrl } from "../../config";
|
||||||
import { IsoDataOptionalSite, VoteContentType } from "../../interfaces";
|
import { IsoDataOptionalSite, VoteContentType } from "../../interfaces";
|
||||||
import { mdToHtml, mdToHtmlInline } from "../../markdown";
|
import { mdToHtml, mdToHtmlInline } from "../../markdown";
|
||||||
import { I18NextService, UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
|
@ -47,10 +48,14 @@ import { CommunityLink } from "../community/community-link";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
import { MetadataCard } from "./metadata-card";
|
import { MetadataCard } from "./metadata-card";
|
||||||
import { PostForm } from "./post-form";
|
import { PostForm } from "./post-form";
|
||||||
import { BanUpdateForm } from "../common/mod-action-form-modal";
|
import { BanUpdateForm } from "../common/modal/mod-action-form-modal";
|
||||||
import PostActionDropdown from "../common/content-actions/post-action-dropdown";
|
import PostActionDropdown from "../common/content-actions/post-action-dropdown";
|
||||||
import { CrossPostParams } from "@utils/types";
|
import { CrossPostParams } from "@utils/types";
|
||||||
import { RequestState } from "../../services/HttpService";
|
import { RequestState } from "../../services/HttpService";
|
||||||
|
import { toast } from "../../toast";
|
||||||
|
import isMagnetLink, {
|
||||||
|
extractMagnetLinkDownloadName,
|
||||||
|
} from "@utils/media/is-magnet-link";
|
||||||
|
|
||||||
type PostListingState = {
|
type PostListingState = {
|
||||||
showEdit: boolean;
|
showEdit: boolean;
|
||||||
|
@ -58,6 +63,7 @@ type PostListingState = {
|
||||||
viewSource: boolean;
|
viewSource: boolean;
|
||||||
showAdvanced: boolean;
|
showAdvanced: boolean;
|
||||||
showBody: boolean;
|
showBody: boolean;
|
||||||
|
loading: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface PostListingProps {
|
interface PostListingProps {
|
||||||
|
@ -107,6 +113,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
viewSource: false,
|
viewSource: false,
|
||||||
showAdvanced: false,
|
showAdvanced: false,
|
||||||
showBody: false,
|
showBody: false,
|
||||||
|
loading: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -134,17 +141,30 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this.handleHidePost = this.handleHidePost.bind(this);
|
this.handleHidePost = this.handleHidePost.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
unlisten = () => {};
|
||||||
|
|
||||||
|
componentWillMount(): void {
|
||||||
if (
|
if (
|
||||||
UserService.Instance.myUserInfo &&
|
UserService.Instance.myUserInfo &&
|
||||||
!this.isoData.showAdultConsentModal
|
!this.isoData.showAdultConsentModal
|
||||||
) {
|
) {
|
||||||
const { auto_expand, blur_nsfw } =
|
const blur_nsfw =
|
||||||
UserService.Instance.myUserInfo.local_user_view.local_user;
|
UserService.Instance.myUserInfo.local_user_view.local_user.blur_nsfw;
|
||||||
this.setState({
|
this.setState({
|
||||||
imageExpanded: auto_expand && !(blur_nsfw && this.postView.post.nsfw),
|
imageExpanded: !(blur_nsfw && this.postView.post.nsfw),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Leave edit mode on navigation
|
||||||
|
this.unlisten = this.context.router.history.listen(() => {
|
||||||
|
if (this.state.showEdit) {
|
||||||
|
this.setState({ showEdit: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
this.unlisten();
|
||||||
}
|
}
|
||||||
|
|
||||||
get postView(): PostView {
|
get postView(): PostView {
|
||||||
|
@ -160,9 +180,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<>
|
<>
|
||||||
{this.listing()}
|
{this.listing()}
|
||||||
{this.state.imageExpanded && !this.props.hideImage && this.img}
|
{this.state.imageExpanded && !this.props.hideImage && this.img}
|
||||||
|
{this.showBody &&
|
||||||
|
post.url &&
|
||||||
|
isMagnetLink(post.url) &&
|
||||||
|
this.torrentHelp()}
|
||||||
{this.showBody && post.url && post.embed_title && (
|
{this.showBody && post.url && post.embed_title && (
|
||||||
<MetadataCard post={post} />
|
<MetadataCard post={post} />
|
||||||
)}
|
)}
|
||||||
|
{this.showBody && this.videoBlock}
|
||||||
{this.showBody && this.body()}
|
{this.showBody && this.body()}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -176,6 +201,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
voteDisplayMode={this.props.voteDisplayMode}
|
voteDisplayMode={this.props.voteDisplayMode}
|
||||||
allLanguages={this.props.allLanguages}
|
allLanguages={this.props.allLanguages}
|
||||||
siteLanguages={this.props.siteLanguages}
|
siteLanguages={this.props.siteLanguages}
|
||||||
|
loading={this.state.loading}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -200,9 +226,54 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
torrentHelp() {
|
||||||
|
return (
|
||||||
|
<div className="alert alert-info small my-2" role="alert">
|
||||||
|
<Icon icon="info" classes="icon-inline me-2" />
|
||||||
|
<T parent="span" i18nKey="torrent_help">
|
||||||
|
#
|
||||||
|
<a className="alert-link" rel={relTags} href={torrentHelpUrl}>
|
||||||
|
#
|
||||||
|
</a>
|
||||||
|
</T>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get videoBlock() {
|
||||||
|
const post = this.postView.post;
|
||||||
|
const url = post.url;
|
||||||
|
|
||||||
|
// if direct video link or embedded video link
|
||||||
|
if (url && isVideo(url)) {
|
||||||
|
return (
|
||||||
|
<div className="ratio ratio-16x9 mt-3">
|
||||||
|
<video
|
||||||
|
onLoadStart={linkEvent(this, this.handleVideoLoadStart)}
|
||||||
|
onPlay={linkEvent(this, this.handleVideoLoadStart)}
|
||||||
|
onVolumeChange={linkEvent(this, this.handleVideoVolumeChange)}
|
||||||
|
controls
|
||||||
|
>
|
||||||
|
<source src={post.embed_video_url ?? url} type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (post.embed_video_url) {
|
||||||
|
return (
|
||||||
|
<div className="ratio ratio-16x9 mt-3">
|
||||||
|
<iframe
|
||||||
|
title="video embed"
|
||||||
|
src={post.embed_video_url}
|
||||||
|
sandbox="allow-same-origin allow-scripts"
|
||||||
|
allowFullScreen={true}
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get img() {
|
get img() {
|
||||||
const { post } = this.postView;
|
const { post } = this.postView;
|
||||||
const { url } = post;
|
|
||||||
|
|
||||||
if (this.isoData.showAdultConsentModal) {
|
if (this.isoData.showAdultConsentModal) {
|
||||||
return <></>;
|
return <></>;
|
||||||
|
@ -229,37 +300,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if direct video link
|
|
||||||
if (url && isVideo(url)) {
|
|
||||||
return (
|
|
||||||
<div className="embed-responsive ratio ratio-16x9 mt-3">
|
|
||||||
<video
|
|
||||||
onLoadStart={linkEvent(this, this.handleVideoLoadStart)}
|
|
||||||
onPlay={linkEvent(this, this.handleVideoLoadStart)}
|
|
||||||
onVolumeChange={linkEvent(this, this.handleVideoVolumeChange)}
|
|
||||||
controls
|
|
||||||
className="embed-responsive-item col-12"
|
|
||||||
>
|
|
||||||
<source src={url} type="video/mp4" />
|
|
||||||
</video>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if embedded video link
|
|
||||||
if (url && post.embed_video_url) {
|
|
||||||
return (
|
|
||||||
<div className="ratio ratio-16x9">
|
|
||||||
<iframe
|
|
||||||
allowFullScreen
|
|
||||||
className="post-metadata-iframe"
|
|
||||||
src={post.embed_video_url}
|
|
||||||
title={post.embed_title}
|
|
||||||
></iframe>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +350,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
} else if (!this.props.hideImage && url && thumbnail && this.imageSrc) {
|
} else if (
|
||||||
|
!this.props.hideImage &&
|
||||||
|
url &&
|
||||||
|
thumbnail &&
|
||||||
|
this.imageSrc &&
|
||||||
|
!isVideo(url)
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className="thumbnail rounded overflow-hidden d-inline-block position-relative p-0 border-0"
|
className="thumbnail rounded overflow-hidden d-inline-block position-relative p-0 border-0"
|
||||||
|
@ -330,7 +376,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
if ((!this.props.hideImage && isVideo(url)) || post.embed_video_url) {
|
if ((!this.props.hideImage && isVideo(url)) || post.embed_video_url) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className="text-body"
|
className={classNames(
|
||||||
|
"thumbnail rounded",
|
||||||
|
thumbnail
|
||||||
|
? "overflow-hidden d-inline-block position-relative p-0 border-0"
|
||||||
|
: "text-body bg-light d-flex justify-content-center",
|
||||||
|
)}
|
||||||
href={url}
|
href={url}
|
||||||
title={url}
|
title={url}
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
|
@ -339,9 +390,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
aria-label={I18NextService.i18n.t("expand_here")}
|
aria-label={I18NextService.i18n.t("expand_here")}
|
||||||
target={this.linkTarget}
|
target={this.linkTarget}
|
||||||
>
|
>
|
||||||
<div className="thumbnail rounded bg-light d-flex justify-content-center">
|
{thumbnail && this.imgThumb(thumbnail)}
|
||||||
<Icon icon="play" classes="d-flex align-items-center" />
|
<Icon
|
||||||
</div>
|
icon="video"
|
||||||
|
classes={
|
||||||
|
thumbnail
|
||||||
|
? "d-block text-white position-absolute end-0 top-0 mini-overlay text-opacity-75 text-opacity-100-hover"
|
||||||
|
: "d-flex align-items-center"
|
||||||
|
}
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -376,7 +433,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
|
||||||
createdLine() {
|
createdLine() {
|
||||||
const pv = this.postView;
|
const pv = this.postView;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="small mb-1 mb-md-0">
|
<div className="small mb-1 mb-md-0">
|
||||||
<PersonListing person={pv.creator} />
|
<PersonListing person={pv.creator} />
|
||||||
|
@ -402,6 +458,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
)}{" "}
|
)}{" "}
|
||||||
|
{pv.post.scheduled_publish_time && (
|
||||||
|
<span className="mx-1 badge text-bg-light">
|
||||||
|
{I18NextService.i18n.t("publish_in_time", {
|
||||||
|
time: formatPastDate(pv.post.scheduled_publish_time),
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
)}{" "}
|
||||||
· <MomentTime published={pv.post.published} updated={pv.post.updated} />
|
· <MomentTime published={pv.post.published} updated={pv.post.updated} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -522,6 +585,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
const post = this.postView.post;
|
const post = this.postView.post;
|
||||||
const url = post.url;
|
const url = post.url;
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
// If its a torrent link, extract the download name
|
||||||
|
const linkName = isMagnetLink(url)
|
||||||
|
? extractMagnetLinkDownloadName(url)
|
||||||
|
: !(hostname(url) === getExternalHost())
|
||||||
|
? hostname(url)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (linkName) {
|
||||||
return (
|
return (
|
||||||
<p className="small m-0">
|
<p className="small m-0">
|
||||||
{url && !(hostname(url) === getExternalHost()) && (
|
{url && !(hostname(url) === getExternalHost()) && (
|
||||||
|
@ -531,12 +603,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
title={url}
|
title={url}
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
>
|
>
|
||||||
{hostname(url)}
|
{linkName}
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
duplicatesLine() {
|
duplicatesLine() {
|
||||||
const dupes = this.props.crossPosts;
|
const dupes = this.props.crossPosts;
|
||||||
|
@ -701,19 +775,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mobileThumbnail() {
|
mobileThumbnail() {
|
||||||
const post = this.postView.post;
|
return (
|
||||||
return post.thumbnail_url || (post.url && isImage(post.url)) ? (
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className={`${this.state.imageExpanded ? "col-12" : "col-9"}`}>
|
<div className="col-9">{this.postTitleLine()}</div>
|
||||||
{this.postTitleLine()}
|
|
||||||
</div>
|
|
||||||
<div className="col-3 mobile-thumbnail-container">
|
<div className="col-3 mobile-thumbnail-container">
|
||||||
{/* Post thumbnail */}
|
{/* Post thumbnail */}
|
||||||
{!this.state.imageExpanded && this.thumbnail()}
|
{this.thumbnail()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
this.postTitleLine()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,9 +881,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The actual editing is done in the receive for post
|
// The actual editing is done in the receive for post
|
||||||
handleEditPost(form: EditPost) {
|
async handleEditPost(form: EditPost) {
|
||||||
this.setState({ showEdit: false });
|
this.setState({ loading: true });
|
||||||
return this.props.onPostEdit(form);
|
const res = await this.props.onPostEdit(form);
|
||||||
|
|
||||||
|
if (res.state === "success") {
|
||||||
|
toast(I18NextService.i18n.t("edited_post"));
|
||||||
|
this.setState({ loading: false, showEdit: false });
|
||||||
|
} else if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShare(i: PostListing) {
|
handleShare(i: PostListing) {
|
||||||
|
@ -855,7 +932,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get crossPostParams(): CrossPostParams {
|
get crossPostParams(): CrossPostParams {
|
||||||
const { name, url } = this.postView.post;
|
const { name, url, alt_text, nsfw, language_id } = this.postView.post;
|
||||||
const crossPostParams: CrossPostParams = { name };
|
const crossPostParams: CrossPostParams = { name };
|
||||||
|
|
||||||
if (url) {
|
if (url) {
|
||||||
|
@ -867,6 +944,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
crossPostParams.body = crossPostBody;
|
crossPostParams.body = crossPostBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (alt_text) {
|
||||||
|
crossPostParams.altText = alt_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsfw) {
|
||||||
|
crossPostParams.nsfw = nsfw ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (language_id !== undefined) {
|
||||||
|
crossPostParams.languageId = language_id;
|
||||||
|
}
|
||||||
|
|
||||||
return crossPostParams;
|
return crossPostParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,7 +1029,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
handleModBanFromCommunity({
|
handleModBanFromCommunity({
|
||||||
daysUntilExpires,
|
daysUntilExpires,
|
||||||
reason,
|
reason,
|
||||||
shouldRemove,
|
shouldRemoveOrRestoreData,
|
||||||
}: BanUpdateForm) {
|
}: BanUpdateForm) {
|
||||||
const {
|
const {
|
||||||
creator: { id: person_id },
|
creator: { id: person_id },
|
||||||
|
@ -951,7 +1040,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
|
||||||
// If its an unban, restore all their data
|
// If its an unban, restore all their data
|
||||||
if (ban === false) {
|
if (ban === false) {
|
||||||
shouldRemove = false;
|
shouldRemoveOrRestoreData = true;
|
||||||
}
|
}
|
||||||
const expires = futureDaysToUnixTime(daysUntilExpires);
|
const expires = futureDaysToUnixTime(daysUntilExpires);
|
||||||
|
|
||||||
|
@ -959,7 +1048,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
community_id,
|
community_id,
|
||||||
person_id,
|
person_id,
|
||||||
ban,
|
ban,
|
||||||
remove_data: shouldRemove,
|
remove_or_restore_data: shouldRemoveOrRestoreData,
|
||||||
reason,
|
reason,
|
||||||
expires,
|
expires,
|
||||||
});
|
});
|
||||||
|
@ -968,7 +1057,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
handleModBanFromSite({
|
handleModBanFromSite({
|
||||||
daysUntilExpires,
|
daysUntilExpires,
|
||||||
reason,
|
reason,
|
||||||
shouldRemove,
|
shouldRemoveOrRestoreData,
|
||||||
}: BanUpdateForm) {
|
}: BanUpdateForm) {
|
||||||
const {
|
const {
|
||||||
creator: { id: person_id, banned },
|
creator: { id: person_id, banned },
|
||||||
|
@ -977,14 +1066,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
|
||||||
// If its an unban, restore all their data
|
// If its an unban, restore all their data
|
||||||
if (ban === false) {
|
if (ban === false) {
|
||||||
shouldRemove = false;
|
shouldRemoveOrRestoreData = true;
|
||||||
}
|
}
|
||||||
const expires = futureDaysToUnixTime(daysUntilExpires);
|
const expires = futureDaysToUnixTime(daysUntilExpires);
|
||||||
|
|
||||||
return this.props.onBanPerson({
|
return this.props.onBanPerson({
|
||||||
person_id,
|
person_id,
|
||||||
ban,
|
ban,
|
||||||
remove_data: shouldRemove,
|
remove_or_restore_data: shouldRemoveOrRestoreData,
|
||||||
reason,
|
reason,
|
||||||
expires,
|
expires,
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,15 +18,17 @@ import { isBrowser } from "@utils/browser";
|
||||||
import {
|
import {
|
||||||
debounce,
|
debounce,
|
||||||
getApubName,
|
getApubName,
|
||||||
|
getQueryParams,
|
||||||
|
getQueryString,
|
||||||
randomStr,
|
randomStr,
|
||||||
resourcesSettled,
|
resourcesSettled,
|
||||||
|
bareRoutePush,
|
||||||
} from "@utils/helpers";
|
} from "@utils/helpers";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
import { isImage } from "@utils/media";
|
import { isImage } from "@utils/media";
|
||||||
import { RouteDataResponse } from "@utils/types";
|
import { QueryParams, RouteDataResponse } from "@utils/types";
|
||||||
import autosize from "autosize";
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Component, RefObject, createRef, linkEvent } from "inferno";
|
import { Component, createRef, linkEvent } from "inferno";
|
||||||
import {
|
import {
|
||||||
AddAdmin,
|
AddAdmin,
|
||||||
AddModToCommunity,
|
AddModToCommunity,
|
||||||
|
@ -103,6 +105,7 @@ import { PostListing } from "./post-listing";
|
||||||
import { getHttpBaseInternal } from "../../utils/env";
|
import { getHttpBaseInternal } from "../../utils/env";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
|
import { compareAsc, compareDesc } from "date-fns";
|
||||||
|
|
||||||
const commentsShownInterval = 15;
|
const commentsShownInterval = 15;
|
||||||
|
|
||||||
|
@ -112,48 +115,135 @@ type PostData = RouteDataResponse<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
interface PostState {
|
interface PostState {
|
||||||
postId?: number;
|
|
||||||
commentId?: number;
|
|
||||||
postRes: RequestState<GetPostResponse>;
|
postRes: RequestState<GetPostResponse>;
|
||||||
commentsRes: RequestState<GetCommentsResponse>;
|
commentsRes: RequestState<GetCommentsResponse>;
|
||||||
commentSort: CommentSortType;
|
|
||||||
commentViewType: CommentViewType;
|
|
||||||
scrolled?: boolean;
|
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
commentSectionRef?: RefObject<HTMLDivElement>;
|
|
||||||
showSidebarMobile: boolean;
|
showSidebarMobile: boolean;
|
||||||
maxCommentsShown: number;
|
maxCommentsShown: number;
|
||||||
finished: Map<CommentId, boolean | undefined>;
|
|
||||||
isIsomorphic: boolean;
|
isIsomorphic: boolean;
|
||||||
|
lastCreatedCommentId?: CommentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostPathProps =
|
function getCommentSortTypeFromQuery(
|
||||||
| { post_id: string; comment_id: never }
|
source: string | undefined,
|
||||||
| { post_id: never; comment_id: string };
|
fallback: CommentSortType,
|
||||||
type PostRouteProps = RouteComponentProps<PostPathProps> &
|
): CommentSortType {
|
||||||
Record<string, never>;
|
if (!source) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
switch (source) {
|
||||||
|
case "Hot":
|
||||||
|
case "Top":
|
||||||
|
case "New":
|
||||||
|
case "Old":
|
||||||
|
case "Controversial":
|
||||||
|
return source;
|
||||||
|
default:
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQueryStringFromCommentSortType(
|
||||||
|
sort: CommentSortType,
|
||||||
|
siteRes: GetSiteResponse,
|
||||||
|
): undefined | string {
|
||||||
|
const myUserInfo = siteRes.my_user ?? UserService.Instance.myUserInfo;
|
||||||
|
const local_user = myUserInfo?.local_user_view.local_user;
|
||||||
|
const local_site = siteRes.site_view.local_site;
|
||||||
|
const defaultSort =
|
||||||
|
local_user?.default_comment_sort_type ??
|
||||||
|
local_site.default_comment_sort_type;
|
||||||
|
if (sort === defaultSort) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultCommentView: CommentViewType = CommentViewType.Tree;
|
||||||
|
|
||||||
|
function getCommentViewTypeFromQuery(source?: string): CommentViewType {
|
||||||
|
switch (source) {
|
||||||
|
case "Tree":
|
||||||
|
return CommentViewType.Tree;
|
||||||
|
case "Flat":
|
||||||
|
return CommentViewType.Flat;
|
||||||
|
default:
|
||||||
|
return defaultCommentView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQueryStringFromCommentView(
|
||||||
|
view: CommentViewType,
|
||||||
|
): string | undefined {
|
||||||
|
if (view === defaultCommentView) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
switch (view) {
|
||||||
|
case CommentViewType.Tree:
|
||||||
|
return "Tree";
|
||||||
|
case CommentViewType.Flat:
|
||||||
|
return "Flat";
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PostProps {
|
||||||
|
sort: CommentSortType;
|
||||||
|
view: CommentViewType;
|
||||||
|
scrollToComments: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Fallbacks = {
|
||||||
|
sort: CommentSortType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getPostQueryParams(
|
||||||
|
source: string | undefined,
|
||||||
|
siteRes: GetSiteResponse,
|
||||||
|
): PostProps {
|
||||||
|
const myUserInfo = siteRes.my_user ?? UserService.Instance.myUserInfo;
|
||||||
|
const local_user = myUserInfo?.local_user_view.local_user;
|
||||||
|
const local_site = siteRes.site_view.local_site;
|
||||||
|
|
||||||
|
return getQueryParams<PostProps, Fallbacks>(
|
||||||
|
{
|
||||||
|
scrollToComments: (s?: string) => !!s,
|
||||||
|
sort: getCommentSortTypeFromQuery,
|
||||||
|
view: getCommentViewTypeFromQuery,
|
||||||
|
},
|
||||||
|
source,
|
||||||
|
{
|
||||||
|
sort:
|
||||||
|
local_user?.default_comment_sort_type ??
|
||||||
|
local_site.default_comment_sort_type,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type PostPathProps = { post_id?: string; comment_id?: string };
|
||||||
|
type PostRouteProps = RouteComponentProps<PostPathProps> & PostProps;
|
||||||
|
type PartialPostRouteProps = Partial<
|
||||||
|
PostProps & { match: { params: PostPathProps } }
|
||||||
|
>;
|
||||||
export type PostFetchConfig = IRoutePropsWithFetch<
|
export type PostFetchConfig = IRoutePropsWithFetch<
|
||||||
PostData,
|
PostData,
|
||||||
PostPathProps,
|
PostPathProps,
|
||||||
Record<string, never>
|
PostProps
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@scrollMixin
|
@scrollMixin
|
||||||
export class Post extends Component<PostRouteProps, PostState> {
|
export class Post extends Component<PostRouteProps, PostState> {
|
||||||
private isoData = setIsoData<PostData>(this.context);
|
private isoData = setIsoData<PostData>(this.context);
|
||||||
private commentScrollDebounced: () => void;
|
private commentScrollDebounced: () => void;
|
||||||
|
private shouldScrollToComments: boolean = false;
|
||||||
|
private commentSectionRef = createRef<HTMLDivElement>();
|
||||||
state: PostState = {
|
state: PostState = {
|
||||||
postRes: EMPTY_REQUEST,
|
postRes: EMPTY_REQUEST,
|
||||||
commentsRes: EMPTY_REQUEST,
|
commentsRes: EMPTY_REQUEST,
|
||||||
postId: getIdFromProps(this.props),
|
|
||||||
commentId: getCommentIdFromProps(this.props),
|
|
||||||
commentSort: "Hot",
|
|
||||||
commentViewType: CommentViewType.Tree,
|
|
||||||
scrolled: false,
|
|
||||||
siteRes: this.isoData.site_res,
|
siteRes: this.isoData.site_res,
|
||||||
showSidebarMobile: false,
|
showSidebarMobile: false,
|
||||||
maxCommentsShown: commentsShownInterval,
|
maxCommentsShown: commentsShownInterval,
|
||||||
finished: new Map(),
|
|
||||||
isIsomorphic: false,
|
isIsomorphic: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,6 +260,8 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
this.handleFollow = this.handleFollow.bind(this);
|
this.handleFollow = this.handleFollow.bind(this);
|
||||||
this.handleModRemoveCommunity = this.handleModRemoveCommunity.bind(this);
|
this.handleModRemoveCommunity = this.handleModRemoveCommunity.bind(this);
|
||||||
this.handleCreateComment = this.handleCreateComment.bind(this);
|
this.handleCreateComment = this.handleCreateComment.bind(this);
|
||||||
|
this.handleCreateToplevelComment =
|
||||||
|
this.handleCreateToplevelComment.bind(this);
|
||||||
this.handleEditComment = this.handleEditComment.bind(this);
|
this.handleEditComment = this.handleEditComment.bind(this);
|
||||||
this.handleSaveComment = this.handleSaveComment.bind(this);
|
this.handleSaveComment = this.handleSaveComment.bind(this);
|
||||||
this.handleBlockCommunity = this.handleBlockCommunity.bind(this);
|
this.handleBlockCommunity = this.handleBlockCommunity.bind(this);
|
||||||
|
@ -201,8 +293,6 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
this.handleScrollIntoCommentsClick =
|
this.handleScrollIntoCommentsClick =
|
||||||
this.handleScrollIntoCommentsClick.bind(this);
|
this.handleScrollIntoCommentsClick.bind(this);
|
||||||
|
|
||||||
this.state = { ...this.state, commentSectionRef: createRef() };
|
|
||||||
|
|
||||||
// Only fetch the data if coming from another route
|
// Only fetch the data if coming from another route
|
||||||
if (FirstLoadService.isFirstLoad) {
|
if (FirstLoadService.isFirstLoad) {
|
||||||
const { commentsRes, postRes } = this.isoData.routeData;
|
const { commentsRes, postRes } = this.isoData.routeData;
|
||||||
|
@ -213,71 +303,104 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
commentsRes,
|
commentsRes,
|
||||||
isIsomorphic: true,
|
isIsomorphic: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isBrowser()) {
|
|
||||||
if (this.checkScrollIntoCommentsParam) {
|
|
||||||
this.scrollIntoCommentSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchPost() {
|
fetchPostToken?: symbol;
|
||||||
this.setState({
|
async fetchPost(props: PostRouteProps) {
|
||||||
postRes: LOADING_REQUEST,
|
const token = (this.fetchPostToken = Symbol());
|
||||||
commentsRes: LOADING_REQUEST,
|
this.setState({ postRes: LOADING_REQUEST });
|
||||||
|
const postRes = await HttpService.client.getPost({
|
||||||
|
id: getIdFromProps(props),
|
||||||
|
comment_id: getCommentIdFromProps(props),
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchPostToken) {
|
||||||
|
this.setState({ postRes });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const [postRes, commentsRes] = await Promise.all([
|
fetchCommentsToken?: symbol;
|
||||||
await HttpService.client.getPost({
|
async fetchComments(props: PostRouteProps) {
|
||||||
id: this.state.postId,
|
const token = (this.fetchCommentsToken = Symbol());
|
||||||
comment_id: this.state.commentId,
|
const { sort } = props;
|
||||||
}),
|
this.setState({ commentsRes: LOADING_REQUEST });
|
||||||
HttpService.client.getComments({
|
const commentsRes = await HttpService.client.getComments({
|
||||||
post_id: this.state.postId,
|
post_id: getIdFromProps(props),
|
||||||
parent_id: this.state.commentId,
|
parent_id: getCommentIdFromProps(props),
|
||||||
max_depth: commentTreeMaxDepth,
|
max_depth: commentTreeMaxDepth,
|
||||||
sort: this.state.commentSort,
|
sort,
|
||||||
type_: "All",
|
type_: "All",
|
||||||
saved_only: false,
|
saved_only: false,
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
postRes,
|
|
||||||
commentsRes,
|
|
||||||
});
|
});
|
||||||
|
if (token === this.fetchCommentsToken) {
|
||||||
|
this.setState({ commentsRes });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.checkScrollIntoCommentsParam) {
|
updateUrl(props: PartialPostRouteProps, replace = false) {
|
||||||
this.scrollIntoCommentSection();
|
const {
|
||||||
|
view,
|
||||||
|
sort,
|
||||||
|
match: {
|
||||||
|
params: { comment_id, post_id },
|
||||||
|
},
|
||||||
|
} = {
|
||||||
|
...this.props,
|
||||||
|
...props,
|
||||||
|
};
|
||||||
|
|
||||||
|
const query: QueryParams<PostProps> = {
|
||||||
|
sort: getQueryStringFromCommentSortType(sort, this.state.siteRes),
|
||||||
|
view: getQueryStringFromCommentView(view),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Not inheriting old scrollToComments
|
||||||
|
if (props.scrollToComments) {
|
||||||
|
query.scrollToComments = true.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
let pathname: string | undefined;
|
||||||
|
if (comment_id && post_id) {
|
||||||
|
pathname = `/post/${post_id}/${comment_id}`;
|
||||||
|
} else if (comment_id) {
|
||||||
|
pathname = `/comment/${comment_id}`;
|
||||||
|
} else {
|
||||||
|
pathname = `/post/${post_id}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const location = { pathname, search: getQueryString(query) };
|
||||||
|
if (replace || this.props.location.pathname === pathname) {
|
||||||
|
this.props.history.replace(location);
|
||||||
|
} else {
|
||||||
|
this.props.history.push(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async fetchInitialData({
|
static async fetchInitialData({
|
||||||
headers,
|
headers,
|
||||||
match,
|
match,
|
||||||
}: InitialFetchRequest<PostPathProps>): Promise<PostData> {
|
query: { sort },
|
||||||
|
}: InitialFetchRequest<PostPathProps, PostProps>): Promise<PostData> {
|
||||||
const client = wrapClient(
|
const client = wrapClient(
|
||||||
new LemmyHttp(getHttpBaseInternal(), { headers }),
|
new LemmyHttp(getHttpBaseInternal(), { headers }),
|
||||||
);
|
);
|
||||||
const postId = getIdFromProps({ match });
|
const postId = getIdFromProps({ match });
|
||||||
const commentId = getCommentIdFromProps({ match });
|
const commentId = getCommentIdFromProps({ match });
|
||||||
|
|
||||||
const postForm: GetPost = {};
|
const postForm: GetPost = {
|
||||||
|
id: postId,
|
||||||
|
comment_id: commentId,
|
||||||
|
};
|
||||||
|
|
||||||
const commentsForm: GetComments = {
|
const commentsForm: GetComments = {
|
||||||
|
post_id: postId,
|
||||||
|
parent_id: commentId,
|
||||||
max_depth: commentTreeMaxDepth,
|
max_depth: commentTreeMaxDepth,
|
||||||
sort: "Hot",
|
sort,
|
||||||
type_: "All",
|
type_: "All",
|
||||||
saved_only: false,
|
saved_only: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
postForm.id = postId;
|
|
||||||
postForm.comment_id = commentId;
|
|
||||||
|
|
||||||
commentsForm.post_id = postId;
|
|
||||||
commentsForm.parent_id = commentId;
|
|
||||||
|
|
||||||
const [postRes, commentsRes] = await Promise.all([
|
const [postRes, commentsRes] = await Promise.all([
|
||||||
client.getPost(postForm),
|
client.getPost(postForm),
|
||||||
client.getComments(commentsForm),
|
client.getComments(commentsForm),
|
||||||
|
@ -293,15 +416,79 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
document.removeEventListener("scroll", this.commentScrollDebounced);
|
document.removeEventListener("scroll", this.commentScrollDebounced);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
|
if (isBrowser()) {
|
||||||
|
this.shouldScrollToComments = this.props.scrollToComments;
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic) {
|
||||||
await this.fetchPost();
|
await Promise.all([
|
||||||
|
this.fetchPost(this.props),
|
||||||
|
this.fetchComments(this.props),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
autosize(document.querySelectorAll("textarea"));
|
componentDidMount() {
|
||||||
|
|
||||||
this.commentScrollDebounced = debounce(this.trackCommentsBoxScrolling, 100);
|
this.commentScrollDebounced = debounce(this.trackCommentsBoxScrolling, 100);
|
||||||
document.addEventListener("scroll", this.commentScrollDebounced);
|
document.addEventListener("scroll", this.commentScrollDebounced);
|
||||||
|
|
||||||
|
if (this.state.isIsomorphic) {
|
||||||
|
this.maybeScrollToComments();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps: PostRouteProps): void {
|
||||||
|
const { post_id: nextPost, comment_id: nextComment } =
|
||||||
|
nextProps.match.params;
|
||||||
|
const { post_id: prevPost, comment_id: prevComment } =
|
||||||
|
this.props.match.params;
|
||||||
|
|
||||||
|
const newOrder =
|
||||||
|
this.props.sort !== nextProps.sort || this.props.view !== nextProps.view;
|
||||||
|
|
||||||
|
// For comment links restore sort type from current props.
|
||||||
|
if (
|
||||||
|
nextPost === prevPost &&
|
||||||
|
nextComment &&
|
||||||
|
newOrder &&
|
||||||
|
!nextProps.location.search &&
|
||||||
|
nextProps.history.action === "PUSH"
|
||||||
|
) {
|
||||||
|
this.updateUrl({ match: nextProps.match }, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const needPost =
|
||||||
|
prevPost !== nextPost ||
|
||||||
|
(bareRoutePush(this.props, nextProps) && !nextComment);
|
||||||
|
const needComments =
|
||||||
|
needPost ||
|
||||||
|
prevComment !== nextComment ||
|
||||||
|
nextProps.sort !== this.props.sort;
|
||||||
|
|
||||||
|
if (needPost) {
|
||||||
|
this.fetchPost(nextProps);
|
||||||
|
}
|
||||||
|
if (needComments) {
|
||||||
|
this.fetchComments(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
nextProps.scrollToComments &&
|
||||||
|
this.props.scrollToComments !== nextProps.scrollToComments
|
||||||
|
) {
|
||||||
|
this.shouldScrollToComments = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(): void {
|
||||||
|
if (
|
||||||
|
this.commentSectionRef.current &&
|
||||||
|
this.state.postRes.state === "success" &&
|
||||||
|
this.state.commentsRes.state === "success"
|
||||||
|
) {
|
||||||
|
this.maybeScrollToComments();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleScrollIntoCommentsClick(e: MouseEvent) {
|
handleScrollIntoCommentsClick(e: MouseEvent) {
|
||||||
|
@ -309,16 +496,18 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
get checkScrollIntoCommentsParam() {
|
maybeScrollToComments() {
|
||||||
return (
|
if (this.shouldScrollToComments) {
|
||||||
Boolean(
|
this.shouldScrollToComments = false;
|
||||||
new URLSearchParams(this.props.location.search).get("scrollToComments"),
|
if (this.props.history.action !== "POP" || this.state.isIsomorphic) {
|
||||||
) && this.props.history.action !== "POP"
|
this.scrollIntoCommentSection();
|
||||||
);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollIntoCommentSection() {
|
scrollIntoCommentSection() {
|
||||||
this.state.commentSectionRef?.current?.scrollIntoView();
|
// This doesn't work when in a background tab in firefox.
|
||||||
|
this.commentSectionRef.current?.scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
isBottom(el: Element): boolean {
|
isBottom(el: Element): boolean {
|
||||||
|
@ -413,20 +602,25 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
onHidePost={this.handleHidePost}
|
onHidePost={this.handleHidePost}
|
||||||
onScrollIntoCommentsClick={this.handleScrollIntoCommentsClick}
|
onScrollIntoCommentsClick={this.handleScrollIntoCommentsClick}
|
||||||
/>
|
/>
|
||||||
<div ref={this.state.commentSectionRef} className="mb-2" />
|
<div ref={this.commentSectionRef} className="mb-2" />
|
||||||
|
|
||||||
{/* Only show the top level comment form if its not a context view */}
|
{/* Only show the top level comment form if its not a context view */}
|
||||||
{!(
|
{!(
|
||||||
this.state.commentId || res.post_view.banned_from_community
|
getCommentIdFromProps(this.props) ||
|
||||||
|
res.post_view.banned_from_community
|
||||||
) && (
|
) && (
|
||||||
<CommentForm
|
<CommentForm
|
||||||
|
key={
|
||||||
|
this.context.router.history.location.key +
|
||||||
|
this.state.lastCreatedCommentId
|
||||||
|
// reset on new location, otherwise <Prompt /> stops working
|
||||||
|
}
|
||||||
node={res.post_view.post.id}
|
node={res.post_view.post.id}
|
||||||
disabled={res.post_view.post.locked}
|
disabled={res.post_view.post.locked}
|
||||||
allLanguages={siteRes.all_languages}
|
allLanguages={siteRes.all_languages}
|
||||||
siteLanguages={siteRes.discussion_languages}
|
siteLanguages={siteRes.discussion_languages}
|
||||||
containerClass="post-comment-container"
|
containerClass="post-comment-container"
|
||||||
onUpsertComment={this.handleCreateComment}
|
onUpsertComment={this.handleCreateToplevelComment}
|
||||||
finished={this.state.finished.get(0)}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="d-block d-md-none">
|
<div className="d-block d-md-none">
|
||||||
|
@ -447,10 +641,8 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
{this.state.showSidebarMobile && this.sidebar()}
|
{this.state.showSidebarMobile && this.sidebar()}
|
||||||
</div>
|
</div>
|
||||||
{this.sortRadios()}
|
{this.sortRadios()}
|
||||||
{this.state.commentViewType === CommentViewType.Tree &&
|
{this.props.view === CommentViewType.Tree && this.commentsTree()}
|
||||||
this.commentsTree()}
|
{this.props.view === CommentViewType.Flat && this.commentsFlat()}
|
||||||
{this.state.commentViewType === CommentViewType.Flat &&
|
|
||||||
this.commentsFlat()}
|
|
||||||
</main>
|
</main>
|
||||||
<aside className="d-none d-md-block col-md-4 col-lg-3">
|
<aside className="d-none d-md-block col-md-4 col-lg-3">
|
||||||
{this.sidebar()}
|
{this.sidebar()}
|
||||||
|
@ -482,13 +674,13 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
value={"Hot"}
|
value={"Hot"}
|
||||||
checked={this.state.commentSort === "Hot"}
|
checked={this.props.sort === "Hot"}
|
||||||
onChange={linkEvent(this, this.handleCommentSortChange)}
|
onChange={linkEvent(this, this.handleCommentSortChange)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`${radioId}-hot`}
|
htmlFor={`${radioId}-hot`}
|
||||||
className={classNames("btn btn-outline-secondary pointer", {
|
className={classNames("btn btn-outline-secondary pointer", {
|
||||||
active: this.state.commentSort === "Hot",
|
active: this.props.sort === "Hot",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("hot")}
|
{I18NextService.i18n.t("hot")}
|
||||||
|
@ -498,13 +690,13 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
value={"Top"}
|
value={"Top"}
|
||||||
checked={this.state.commentSort === "Top"}
|
checked={this.props.sort === "Top"}
|
||||||
onChange={linkEvent(this, this.handleCommentSortChange)}
|
onChange={linkEvent(this, this.handleCommentSortChange)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`${radioId}-top`}
|
htmlFor={`${radioId}-top`}
|
||||||
className={classNames("btn btn-outline-secondary pointer", {
|
className={classNames("btn btn-outline-secondary pointer", {
|
||||||
active: this.state.commentSort === "Top",
|
active: this.props.sort === "Top",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("top")}
|
{I18NextService.i18n.t("top")}
|
||||||
|
@ -514,13 +706,13 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
value={"Controversial"}
|
value={"Controversial"}
|
||||||
checked={this.state.commentSort === "Controversial"}
|
checked={this.props.sort === "Controversial"}
|
||||||
onChange={linkEvent(this, this.handleCommentSortChange)}
|
onChange={linkEvent(this, this.handleCommentSortChange)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`${radioId}-controversial`}
|
htmlFor={`${radioId}-controversial`}
|
||||||
className={classNames("btn btn-outline-secondary pointer", {
|
className={classNames("btn btn-outline-secondary pointer", {
|
||||||
active: this.state.commentSort === "Controversial",
|
active: this.props.sort === "Controversial",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("controversial")}
|
{I18NextService.i18n.t("controversial")}
|
||||||
|
@ -530,13 +722,13 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
value={"New"}
|
value={"New"}
|
||||||
checked={this.state.commentSort === "New"}
|
checked={this.props.sort === "New"}
|
||||||
onChange={linkEvent(this, this.handleCommentSortChange)}
|
onChange={linkEvent(this, this.handleCommentSortChange)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`${radioId}-new`}
|
htmlFor={`${radioId}-new`}
|
||||||
className={classNames("btn btn-outline-secondary pointer", {
|
className={classNames("btn btn-outline-secondary pointer", {
|
||||||
active: this.state.commentSort === "New",
|
active: this.props.sort === "New",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("new")}
|
{I18NextService.i18n.t("new")}
|
||||||
|
@ -546,13 +738,13 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
value={"Old"}
|
value={"Old"}
|
||||||
checked={this.state.commentSort === "Old"}
|
checked={this.props.sort === "Old"}
|
||||||
onChange={linkEvent(this, this.handleCommentSortChange)}
|
onChange={linkEvent(this, this.handleCommentSortChange)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`${radioId}-old`}
|
htmlFor={`${radioId}-old`}
|
||||||
className={classNames("btn btn-outline-secondary pointer", {
|
className={classNames("btn btn-outline-secondary pointer", {
|
||||||
active: this.state.commentSort === "Old",
|
active: this.props.sort === "Old",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("old")}
|
{I18NextService.i18n.t("old")}
|
||||||
|
@ -564,13 +756,13 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
value={CommentViewType.Flat}
|
value={CommentViewType.Flat}
|
||||||
checked={this.state.commentViewType === CommentViewType.Flat}
|
checked={this.props.view === CommentViewType.Flat}
|
||||||
onChange={linkEvent(this, this.handleCommentViewTypeChange)}
|
onChange={linkEvent(this, this.handleCommentViewTypeChange)}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`${radioId}-chat`}
|
htmlFor={`${radioId}-chat`}
|
||||||
className={classNames("btn btn-outline-secondary pointer", {
|
className={classNames("btn btn-outline-secondary pointer", {
|
||||||
active: this.state.commentViewType === CommentViewType.Flat,
|
active: this.props.view === CommentViewType.Flat,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("chat")}
|
{I18NextService.i18n.t("chat")}
|
||||||
|
@ -581,6 +773,14 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
commentsFlat() {
|
commentsFlat() {
|
||||||
|
if (this.state.commentsRes.state === "loading") {
|
||||||
|
return (
|
||||||
|
<div className="text-center">
|
||||||
|
<Spinner large />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// These are already sorted by new
|
// These are already sorted by new
|
||||||
const commentsRes = this.state.commentsRes;
|
const commentsRes = this.state.commentsRes;
|
||||||
const postRes = this.state.postRes;
|
const postRes = this.state.postRes;
|
||||||
|
@ -590,8 +790,8 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={commentsToFlatNodes(commentsRes.data.comments)}
|
nodes={this.sortedFlatNodes()}
|
||||||
viewType={this.state.commentViewType}
|
viewType={this.props.view}
|
||||||
maxCommentsShown={this.state.maxCommentsShown}
|
maxCommentsShown={this.state.maxCommentsShown}
|
||||||
isTopLevel
|
isTopLevel
|
||||||
locked={postRes.data.post_view.post.locked}
|
locked={postRes.data.post_view.post.locked}
|
||||||
|
@ -600,7 +800,6 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
enableDownvotes={enableDownvotes(siteRes)}
|
enableDownvotes={enableDownvotes(siteRes)}
|
||||||
voteDisplayMode={voteDisplayMode(siteRes)}
|
voteDisplayMode={voteDisplayMode(siteRes)}
|
||||||
showContext
|
showContext
|
||||||
finished={this.state.finished}
|
|
||||||
allLanguages={siteRes.all_languages}
|
allLanguages={siteRes.all_languages}
|
||||||
siteLanguages={siteRes.discussion_languages}
|
siteLanguages={siteRes.discussion_languages}
|
||||||
onSaveComment={this.handleSaveComment}
|
onSaveComment={this.handleSaveComment}
|
||||||
|
@ -652,7 +851,29 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sortedFlatNodes(): CommentNodeI[] {
|
||||||
|
if (this.state.commentsRes.state !== "success") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const nodeToDate = (node: CommentNodeI) =>
|
||||||
|
node.comment_view.comment.published;
|
||||||
|
const nodes = commentsToFlatNodes(this.state.commentsRes.data.comments);
|
||||||
|
if (this.props.sort === "New") {
|
||||||
|
return nodes.sort((a, b) => compareDesc(nodeToDate(a), nodeToDate(b)));
|
||||||
|
} else {
|
||||||
|
return nodes.sort((a, b) => compareAsc(nodeToDate(a), nodeToDate(b)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
commentsTree() {
|
commentsTree() {
|
||||||
|
if (this.state.commentsRes.state === "loading") {
|
||||||
|
return (
|
||||||
|
<div className="text-center">
|
||||||
|
<Spinner large />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const res = this.state.postRes;
|
const res = this.state.postRes;
|
||||||
const firstComment = this.commentTree().at(0)?.comment_view.comment;
|
const firstComment = this.commentTree().at(0)?.comment_view.comment;
|
||||||
const depth = getDepthFromComment(firstComment);
|
const depth = getDepthFromComment(firstComment);
|
||||||
|
@ -662,11 +883,11 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
return (
|
return (
|
||||||
res.state === "success" && (
|
res.state === "success" && (
|
||||||
<div>
|
<div>
|
||||||
{!!this.state.commentId && (
|
{!!getCommentIdFromProps(this.props) && (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="ps-0 d-block btn btn-link text-muted"
|
className="ps-0 d-block btn btn-link text-muted"
|
||||||
onClick={linkEvent(this, this.handleViewPost)}
|
onClick={linkEvent(this, this.handleViewAllComments)}
|
||||||
>
|
>
|
||||||
{I18NextService.i18n.t("view_all_comments")} ➔
|
{I18NextService.i18n.t("view_all_comments")} ➔
|
||||||
</button>
|
</button>
|
||||||
|
@ -682,14 +903,13 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
)}
|
)}
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={this.commentTree()}
|
nodes={this.commentTree()}
|
||||||
viewType={this.state.commentViewType}
|
viewType={this.props.view}
|
||||||
maxCommentsShown={this.state.maxCommentsShown}
|
maxCommentsShown={this.state.maxCommentsShown}
|
||||||
locked={res.data.post_view.post.locked}
|
locked={res.data.post_view.post.locked}
|
||||||
moderators={res.data.moderators}
|
moderators={res.data.moderators}
|
||||||
admins={siteRes.admins}
|
admins={siteRes.admins}
|
||||||
enableDownvotes={enableDownvotes(siteRes)}
|
enableDownvotes={enableDownvotes(siteRes)}
|
||||||
voteDisplayMode={voteDisplayMode(siteRes)}
|
voteDisplayMode={voteDisplayMode(siteRes)}
|
||||||
finished={this.state.finished}
|
|
||||||
allLanguages={siteRes.all_languages}
|
allLanguages={siteRes.all_languages}
|
||||||
siteLanguages={siteRes.discussion_languages}
|
siteLanguages={siteRes.discussion_languages}
|
||||||
onSaveComment={this.handleSaveComment}
|
onSaveComment={this.handleSaveComment}
|
||||||
|
@ -719,50 +939,69 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
|
|
||||||
commentTree(): CommentNodeI[] {
|
commentTree(): CommentNodeI[] {
|
||||||
if (this.state.commentsRes.state === "success") {
|
if (this.state.commentsRes.state === "success") {
|
||||||
return buildCommentsTree(
|
const comments = this.state.commentsRes.data.comments;
|
||||||
this.state.commentsRes.data.comments,
|
if (comments.length) {
|
||||||
!!this.state.commentId,
|
return buildCommentsTree(comments, !!getCommentIdFromProps(this.props));
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
async handleCommentSortChange(i: Post, event: any) {
|
async handleCommentSortChange(i: Post, event: any) {
|
||||||
i.setState({
|
const sort = event.target.value as CommentSortType;
|
||||||
commentSort: event.target.value as CommentSortType,
|
const flattenable = sort === "New" || sort === "Old";
|
||||||
commentViewType: CommentViewType.Tree,
|
if (flattenable || i.props.view !== CommentViewType.Flat) {
|
||||||
commentsRes: LOADING_REQUEST,
|
i.updateUrl({ sort });
|
||||||
postRes: LOADING_REQUEST,
|
} else {
|
||||||
});
|
i.updateUrl({ sort, view: CommentViewType.Tree });
|
||||||
await i.fetchPost();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommentViewTypeChange(i: Post, event: any) {
|
handleCommentViewTypeChange(i: Post, event: any) {
|
||||||
i.setState({
|
const flattenable = i.props.sort === "New" || i.props.sort === "Old";
|
||||||
commentViewType: Number(event.target.value),
|
const view: CommentViewType = Number(event.target.value);
|
||||||
commentSort: "New",
|
if (flattenable || view !== CommentViewType.Flat) {
|
||||||
});
|
i.updateUrl({ view });
|
||||||
|
} else {
|
||||||
|
i.updateUrl({ view, sort: "New" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShowSidebarMobile(i: Post) {
|
handleShowSidebarMobile(i: Post) {
|
||||||
i.setState({ showSidebarMobile: !i.state.showSidebarMobile });
|
i.setState({ showSidebarMobile: !i.state.showSidebarMobile });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleViewPost(i: Post) {
|
handleViewAllComments(i: Post) {
|
||||||
if (i.state.postRes.state === "success") {
|
const id =
|
||||||
const id = i.state.postRes.data.post_view.post.id;
|
getIdFromProps(i.props) ||
|
||||||
i.context.router.history.push(`/post/${id}`);
|
(i.state.postRes.state === "success" &&
|
||||||
|
i.state.postRes.data.post_view.post.id);
|
||||||
|
if (id) {
|
||||||
|
i.updateUrl({
|
||||||
|
match: { params: { post_id: id.toString() } },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleViewContext(i: Post) {
|
handleViewContext(i: Post) {
|
||||||
if (i.state.commentsRes.state === "success") {
|
if (i.state.commentsRes.state === "success") {
|
||||||
const parentId = getCommentParentId(
|
const commentId = getCommentIdFromProps(i.props);
|
||||||
i.state.commentsRes.data.comments.at(0)?.comment,
|
const commentView = i.state.commentsRes.data.comments.find(
|
||||||
|
c => c.comment.id === commentId,
|
||||||
);
|
);
|
||||||
if (parentId) {
|
|
||||||
i.context.router.history.push(`/comment/${parentId}`);
|
const parentId = getCommentParentId(commentView?.comment);
|
||||||
|
const postId = commentView?.post.id;
|
||||||
|
|
||||||
|
if (parentId && postId) {
|
||||||
|
i.updateUrl({
|
||||||
|
match: {
|
||||||
|
params: {
|
||||||
|
post_id: postId.toString(),
|
||||||
|
comment_id: parentId.toString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -848,6 +1087,14 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleCreateToplevelComment(form: CreateComment) {
|
||||||
|
const res = await this.handleCreateComment(form);
|
||||||
|
if (res.state === "success") {
|
||||||
|
this.setState({ lastCreatedCommentId: res.data.comment_view.comment.id });
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
async handleCreateComment(form: CreateComment) {
|
async handleCreateComment(form: CreateComment) {
|
||||||
const createCommentRes = await HttpService.client.createComment(form);
|
const createCommentRes = await HttpService.client.createComment(form);
|
||||||
this.createAndUpdateComments(createCommentRes);
|
this.createAndUpdateComments(createCommentRes);
|
||||||
|
@ -1165,12 +1412,12 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
);
|
);
|
||||||
|
|
||||||
comments.splice(foundCommentParentIndex + 1, 0, newComment);
|
comments.splice(foundCommentParentIndex + 1, 0, newComment);
|
||||||
|
|
||||||
// Set finished for the parent
|
|
||||||
s.finished.set(newCommentParentId ?? 0, true);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findAndUpdateCommentEdit(res: RequestState<CommentResponse>) {
|
findAndUpdateCommentEdit(res: RequestState<CommentResponse>) {
|
||||||
|
@ -1180,13 +1427,14 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
res.data.comment_view,
|
res.data.comment_view,
|
||||||
s.commentsRes.data.comments,
|
s.commentsRes.data.comments,
|
||||||
);
|
);
|
||||||
s.finished.set(res.data.comment_view.comment.id, true);
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to set finished on a comment vote, save, etc
|
|
||||||
findAndUpdateComment(res: RequestState<CommentResponse>) {
|
findAndUpdateComment(res: RequestState<CommentResponse>) {
|
||||||
this.setState(s => {
|
this.setState(s => {
|
||||||
if (s.commentsRes.state === "success" && res.state === "success") {
|
if (s.commentsRes.state === "success" && res.state === "success") {
|
||||||
|
@ -1197,6 +1445,9 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findAndUpdateCommentReply(res: RequestState<CommentReplyResponse>) {
|
findAndUpdateCommentReply(res: RequestState<CommentReplyResponse>) {
|
||||||
|
@ -1209,6 +1460,9 @@ export class Post extends Component<PostRouteProps, PostState> {
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateModerators(res: RequestState<AddModToCommunityResponse>) {
|
updateModerators(res: RequestState<AddModToCommunityResponse>) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../../routes";
|
import { IRoutePropsWithFetch } from "../../routes";
|
||||||
import { resourcesSettled } from "@utils/helpers";
|
import { resourcesSettled } from "@utils/helpers";
|
||||||
import { scrollMixin } from "../mixins/scroll-mixin";
|
import { scrollMixin } from "../mixins/scroll-mixin";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
type CreatePrivateMessageData = RouteDataResponse<{
|
type CreatePrivateMessageData = RouteDataResponse<{
|
||||||
recipientDetailsResponse: GetPersonDetailsResponse;
|
recipientDetailsResponse: GetPersonDetailsResponse;
|
||||||
|
@ -79,8 +80,8 @@ export class CreatePrivateMessage extends Component<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
await this.fetchPersonDetails();
|
await this.fetchPersonDetails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,14 +168,22 @@ export class CreatePrivateMessage extends Component<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handlePrivateMessageCreate(form: CreatePrivateMessageI) {
|
async handlePrivateMessageCreate(
|
||||||
|
form: CreatePrivateMessageI,
|
||||||
|
bypassNavWarning: () => void,
|
||||||
|
): Promise<boolean> {
|
||||||
const res = await HttpService.client.createPrivateMessage(form);
|
const res = await HttpService.client.createPrivateMessage(form);
|
||||||
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
toast(I18NextService.i18n.t("message_sent"));
|
toast(I18NextService.i18n.t("message_sent"));
|
||||||
|
|
||||||
|
bypassNavWarning();
|
||||||
// Navigate to the front
|
// Navigate to the front
|
||||||
this.context.router.history.push("/");
|
this.context.router.history.push("/");
|
||||||
|
} else if (res.state === "failed") {
|
||||||
|
toast(I18NextService.i18n.t(res.err.message), "danger");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res.state !== "failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { capitalizeFirstLetter } from "@utils/helpers";
|
import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import { Component, InfernoNode } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
import { Prompt } from "inferno-router";
|
import { Prompt } from "inferno-router";
|
||||||
import {
|
import {
|
||||||
|
@ -19,8 +19,14 @@ interface PrivateMessageFormProps {
|
||||||
privateMessageView?: PrivateMessageView; // If a pm is given, that means this is an edit
|
privateMessageView?: PrivateMessageView; // If a pm is given, that means this is an edit
|
||||||
replyType?: boolean;
|
replyType?: boolean;
|
||||||
onCancel?(): any;
|
onCancel?(): any;
|
||||||
onCreate?(form: CreatePrivateMessage): void;
|
onCreate?(
|
||||||
onEdit?(form: EditPrivateMessage): void;
|
form: CreatePrivateMessage,
|
||||||
|
bypassNavWarning: () => void,
|
||||||
|
): Promise<boolean>;
|
||||||
|
onEdit?(
|
||||||
|
form: EditPrivateMessage,
|
||||||
|
bypassNavWarning: () => void,
|
||||||
|
): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PrivateMessageFormState {
|
interface PrivateMessageFormState {
|
||||||
|
@ -28,6 +34,7 @@ interface PrivateMessageFormState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
previewMode: boolean;
|
previewMode: boolean;
|
||||||
submitted: boolean;
|
submitted: boolean;
|
||||||
|
bypassNavWarning?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PrivateMessageForm extends Component<
|
export class PrivateMessageForm extends Component<
|
||||||
|
@ -51,21 +58,15 @@ export class PrivateMessageForm extends Component<
|
||||||
this.handlePrivateMessageSubmit.bind(this);
|
this.handlePrivateMessageSubmit.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(
|
|
||||||
nextProps: Readonly<{ children?: InfernoNode } & PrivateMessageFormProps>,
|
|
||||||
): void {
|
|
||||||
if (this.props !== nextProps) {
|
|
||||||
this.setState({ loading: false, content: undefined, previewMode: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<form className="private-message-form">
|
<form className="private-message-form">
|
||||||
<Prompt
|
<Prompt
|
||||||
message={I18NextService.i18n.t("block_leaving")}
|
message={I18NextService.i18n.t("block_leaving")}
|
||||||
when={
|
when={
|
||||||
!this.state.loading && !!this.state.content && !this.state.submitted
|
!this.state.bypassNavWarning &&
|
||||||
|
((!!this.state.content && !this.state.submitted) ||
|
||||||
|
this.state.loading)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{!this.props.privateMessageView && (
|
{!this.props.privateMessageView && (
|
||||||
|
@ -140,21 +141,34 @@ export class PrivateMessageForm extends Component<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePrivateMessageSubmit() {
|
async handlePrivateMessageSubmit(): Promise<boolean> {
|
||||||
this.setState({ loading: true, submitted: true });
|
this.setState({ loading: true, submitted: true });
|
||||||
const pm = this.props.privateMessageView;
|
const pm = this.props.privateMessageView;
|
||||||
const content = this.state.content ?? "";
|
const content = this.state.content ?? "";
|
||||||
|
let success: boolean | undefined;
|
||||||
if (pm) {
|
if (pm) {
|
||||||
this.props.onEdit?.({
|
success = await this.props.onEdit?.(
|
||||||
|
{
|
||||||
private_message_id: pm.private_message.id,
|
private_message_id: pm.private_message.id,
|
||||||
content,
|
content,
|
||||||
});
|
},
|
||||||
|
() => {
|
||||||
|
this.setState({ bypassNavWarning: true });
|
||||||
|
},
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.props.onCreate?.({
|
success = await this.props.onCreate?.(
|
||||||
|
{
|
||||||
content,
|
content,
|
||||||
recipient_id: this.props.recipient.id,
|
recipient_id: this.props.recipient.id,
|
||||||
});
|
},
|
||||||
|
() => {
|
||||||
|
this.setState({ bypassNavWarning: true });
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
this.setState({ loading: false, submitted: success ?? true });
|
||||||
|
return success ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleContentChange(val: string) {
|
handleContentChange(val: string) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import {
|
import {
|
||||||
CreatePrivateMessage,
|
CreatePrivateMessage,
|
||||||
CreatePrivateMessageReport,
|
CreatePrivateMessageReport,
|
||||||
|
@ -14,7 +14,7 @@ import { Icon, Spinner } from "../common/icon";
|
||||||
import { MomentTime } from "../common/moment-time";
|
import { MomentTime } from "../common/moment-time";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
import { PrivateMessageForm } from "./private-message-form";
|
import { PrivateMessageForm } from "./private-message-form";
|
||||||
import ModActionFormModal from "../common/mod-action-form-modal";
|
import ModActionFormModal from "../common/modal/mod-action-form-modal";
|
||||||
import { tippyMixin } from "../mixins/tippy-mixin";
|
import { tippyMixin } from "../mixins/tippy-mixin";
|
||||||
|
|
||||||
interface PrivateMessageState {
|
interface PrivateMessageState {
|
||||||
|
@ -32,8 +32,8 @@ interface PrivateMessageProps {
|
||||||
onDelete(form: DeletePrivateMessage): void;
|
onDelete(form: DeletePrivateMessage): void;
|
||||||
onMarkRead(form: MarkPrivateMessageAsRead): void;
|
onMarkRead(form: MarkPrivateMessageAsRead): void;
|
||||||
onReport(form: CreatePrivateMessageReport): void;
|
onReport(form: CreatePrivateMessageReport): void;
|
||||||
onCreate(form: CreatePrivateMessage): void;
|
onCreate(form: CreatePrivateMessage): Promise<boolean>;
|
||||||
onEdit(form: EditPrivateMessage): void;
|
onEdit(form: EditPrivateMessage): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@tippyMixin
|
@tippyMixin
|
||||||
|
@ -56,6 +56,8 @@ export class PrivateMessage extends Component<
|
||||||
this.handleReplyCancel = this.handleReplyCancel.bind(this);
|
this.handleReplyCancel = this.handleReplyCancel.bind(this);
|
||||||
this.handleReportSubmit = this.handleReportSubmit.bind(this);
|
this.handleReportSubmit = this.handleReportSubmit.bind(this);
|
||||||
this.hideReportDialog = this.hideReportDialog.bind(this);
|
this.hideReportDialog = this.hideReportDialog.bind(this);
|
||||||
|
this.handleCreate = this.handleCreate.bind(this);
|
||||||
|
this.handleEdit = this.handleEdit.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get mine(): boolean {
|
get mine(): boolean {
|
||||||
|
@ -65,22 +67,6 @@ export class PrivateMessage extends Component<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(
|
|
||||||
nextProps: Readonly<{ children?: InfernoNode } & PrivateMessageProps>,
|
|
||||||
): void {
|
|
||||||
if (this.props !== nextProps) {
|
|
||||||
this.setState({
|
|
||||||
showReply: false,
|
|
||||||
showEdit: false,
|
|
||||||
collapsed: false,
|
|
||||||
viewSource: false,
|
|
||||||
showReportDialog: false,
|
|
||||||
deleteLoading: false,
|
|
||||||
readLoading: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const message_view = this.props.private_message_view;
|
const message_view = this.props.private_message_view;
|
||||||
const otherPerson: Person = this.mine
|
const otherPerson: Person = this.mine
|
||||||
|
@ -126,7 +112,7 @@ export class PrivateMessage extends Component<
|
||||||
<PrivateMessageForm
|
<PrivateMessageForm
|
||||||
recipient={otherPerson}
|
recipient={otherPerson}
|
||||||
privateMessageView={message_view}
|
privateMessageView={message_view}
|
||||||
onEdit={this.props.onEdit}
|
onEdit={this.handleEdit}
|
||||||
onCancel={this.handleReplyCancel}
|
onCancel={this.handleReplyCancel}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -265,7 +251,7 @@ export class PrivateMessage extends Component<
|
||||||
<PrivateMessageForm
|
<PrivateMessageForm
|
||||||
replyType={true}
|
replyType={true}
|
||||||
recipient={otherPerson}
|
recipient={otherPerson}
|
||||||
onCreate={this.props.onCreate}
|
onCreate={this.handleCreate}
|
||||||
onCancel={this.handleReplyCancel}
|
onCancel={this.handleReplyCancel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -304,7 +290,6 @@ export class PrivateMessage extends Component<
|
||||||
|
|
||||||
handleEditClick(i: PrivateMessage) {
|
handleEditClick(i: PrivateMessage) {
|
||||||
i.setState({ showEdit: true });
|
i.setState({ showEdit: true });
|
||||||
i.setState(i.state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteClick(i: PrivateMessage) {
|
handleDeleteClick(i: PrivateMessage) {
|
||||||
|
@ -319,6 +304,22 @@ export class PrivateMessage extends Component<
|
||||||
this.setState({ showReply: false, showEdit: false });
|
this.setState({ showReply: false, showEdit: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleCreate(form: CreatePrivateMessage): Promise<boolean> {
|
||||||
|
const success = await this.props.onCreate(form);
|
||||||
|
if (success) {
|
||||||
|
this.setState({ showReply: false });
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleEdit(form: EditPrivateMessage): Promise<boolean> {
|
||||||
|
const success = await this.props.onEdit(form);
|
||||||
|
if (success) {
|
||||||
|
this.setState({ showEdit: false });
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
handleMarkRead(i: PrivateMessage) {
|
handleMarkRead(i: PrivateMessage) {
|
||||||
i.setState({ readLoading: true });
|
i.setState({ readLoading: true });
|
||||||
i.props.onMarkRead({
|
i.props.onMarkRead({
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { CommunityLink } from "./community/community-link";
|
||||||
import { getHttpBaseInternal } from "../utils/env";
|
import { getHttpBaseInternal } from "../utils/env";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../routes";
|
import { IRoutePropsWithFetch } from "../routes";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
interface RemoteFetchProps {
|
interface RemoteFetchProps {
|
||||||
uri?: string;
|
uri?: string;
|
||||||
|
@ -128,8 +129,8 @@ export class RemoteFetch extends Component<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentWillMount() {
|
||||||
if (!this.state.isIsomorphic) {
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
const { uri } = this.props;
|
const { uri } = this.props;
|
||||||
|
|
||||||
if (uri) {
|
if (uri) {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
enableNsfw,
|
enableNsfw,
|
||||||
fetchCommunities,
|
fetchCommunities,
|
||||||
fetchUsers,
|
fetchUsers,
|
||||||
getUpdatedSearchId,
|
|
||||||
myAuth,
|
myAuth,
|
||||||
personToChoice,
|
personToChoice,
|
||||||
setIsoData,
|
setIsoData,
|
||||||
|
@ -19,6 +18,7 @@ import {
|
||||||
dedupByProperty,
|
dedupByProperty,
|
||||||
getIdFromString,
|
getIdFromString,
|
||||||
getPageFromString,
|
getPageFromString,
|
||||||
|
getBoolFromString,
|
||||||
getQueryParams,
|
getQueryParams,
|
||||||
getQueryString,
|
getQueryString,
|
||||||
numToSI,
|
numToSI,
|
||||||
|
@ -46,7 +46,7 @@ import {
|
||||||
Search as SearchForm,
|
Search as SearchForm,
|
||||||
SearchResponse,
|
SearchResponse,
|
||||||
SearchType,
|
SearchType,
|
||||||
SortType,
|
PostSortType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit } from "../config";
|
import { fetchLimit } from "../config";
|
||||||
import { CommentViewType, InitialFetchRequest } from "../interfaces";
|
import { CommentViewType, InitialFetchRequest } from "../interfaces";
|
||||||
|
@ -71,12 +71,14 @@ import { PostListing } from "./post/post-listing";
|
||||||
import { getHttpBaseInternal } from "../utils/env";
|
import { getHttpBaseInternal } from "../utils/env";
|
||||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||||
import { IRoutePropsWithFetch } from "../routes";
|
import { IRoutePropsWithFetch } from "../routes";
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
interface SearchProps {
|
interface SearchProps {
|
||||||
q?: string;
|
q?: string;
|
||||||
type: SearchType;
|
type: SearchType;
|
||||||
sort: SortType;
|
sort: PostSortType;
|
||||||
listingType: ListingType;
|
listingType: ListingType;
|
||||||
|
titleOnly?: boolean;
|
||||||
communityId?: number;
|
communityId?: number;
|
||||||
creatorId?: number;
|
creatorId?: number;
|
||||||
page: number;
|
page: number;
|
||||||
|
@ -96,7 +98,6 @@ interface SearchState {
|
||||||
searchRes: RequestState<SearchResponse>;
|
searchRes: RequestState<SearchResponse>;
|
||||||
resolveObjectRes: RequestState<ResolveObjectResponse>;
|
resolveObjectRes: RequestState<ResolveObjectResponse>;
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
searchText?: string;
|
|
||||||
communitySearchOptions: Choice[];
|
communitySearchOptions: Choice[];
|
||||||
creatorSearchOptions: Choice[];
|
creatorSearchOptions: Choice[];
|
||||||
searchCreatorLoading: boolean;
|
searchCreatorLoading: boolean;
|
||||||
|
@ -123,6 +124,7 @@ export function getSearchQueryParams(source?: string): SearchProps {
|
||||||
type: getSearchTypeFromQuery,
|
type: getSearchTypeFromQuery,
|
||||||
sort: getSortTypeFromQuery,
|
sort: getSortTypeFromQuery,
|
||||||
listingType: getListingTypeFromQuery,
|
listingType: getListingTypeFromQuery,
|
||||||
|
titleOnly: getBoolFromString,
|
||||||
communityId: getIdFromString,
|
communityId: getIdFromString,
|
||||||
creatorId: getIdFromString,
|
creatorId: getIdFromString,
|
||||||
page: getPageFromString,
|
page: getPageFromString,
|
||||||
|
@ -137,8 +139,8 @@ function getSearchTypeFromQuery(type_?: string): SearchType {
|
||||||
return type_ ? (type_ as SearchType) : defaultSearchType;
|
return type_ ? (type_ as SearchType) : defaultSearchType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSortTypeFromQuery(sort?: string): SortType {
|
function getSortTypeFromQuery(sort?: string): PostSortType {
|
||||||
return sort ? (sort as SortType) : defaultSortType;
|
return sort ? (sort as PostSortType) : defaultSortType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getListingTypeFromQuery(listingType?: string): ListingType {
|
function getListingTypeFromQuery(listingType?: string): ListingType {
|
||||||
|
@ -284,10 +286,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
this.handleCommunityFilterChange =
|
this.handleCommunityFilterChange =
|
||||||
this.handleCommunityFilterChange.bind(this);
|
this.handleCommunityFilterChange.bind(this);
|
||||||
this.handleCreatorFilterChange = this.handleCreatorFilterChange.bind(this);
|
this.handleCreatorFilterChange = this.handleCreatorFilterChange.bind(this);
|
||||||
|
this.handleTitleOnlyChange = this.handleTitleOnlyChange.bind(this);
|
||||||
const { q } = this.props;
|
|
||||||
|
|
||||||
this.state.searchText = q;
|
|
||||||
|
|
||||||
// Only fetch the data if coming from another route
|
// Only fetch the data if coming from another route
|
||||||
if (FirstLoadService.isFirstLoad) {
|
if (FirstLoadService.isFirstLoad) {
|
||||||
|
@ -329,81 +328,142 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
componentWillMount() {
|
||||||
|
if (!this.state.isIsomorphic && isBrowser()) {
|
||||||
|
this.fetchAll(this.props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.props.history.action !== "POP" || this.state.isIsomorphic) {
|
||||||
|
this.searchInput.current?.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps: SearchRouteProps) {
|
||||||
|
if (nextProps.communityId !== this.props.communityId) {
|
||||||
|
this.fetchSelectedCommunity(nextProps);
|
||||||
|
}
|
||||||
|
if (nextProps.creatorId !== this.props.creatorId) {
|
||||||
|
this.fetchSelectedCreator(nextProps);
|
||||||
|
}
|
||||||
|
this.search(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: SearchRouteProps) {
|
||||||
|
if (this.props.location.key !== prevProps.location.key) {
|
||||||
if (this.props.history.action !== "POP") {
|
if (this.props.history.action !== "POP") {
|
||||||
this.searchInput.current?.select();
|
this.searchInput.current?.select();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isIsomorphic) {
|
fetchDefaultCommunitiesToken?: symbol;
|
||||||
|
async fetchDefaultCommunities({
|
||||||
|
communityId,
|
||||||
|
}: Pick<SearchRouteProps, "communityId">) {
|
||||||
|
const token = (this.fetchDefaultCommunitiesToken = Symbol());
|
||||||
this.setState({
|
this.setState({
|
||||||
searchCommunitiesLoading: true,
|
searchCommunitiesLoading: true,
|
||||||
searchCreatorLoading: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const promises = [
|
const res = await HttpService.client.listCommunities({
|
||||||
HttpService.client
|
|
||||||
.listCommunities({
|
|
||||||
type_: defaultListingType,
|
type_: defaultListingType,
|
||||||
sort: defaultSortType,
|
sort: defaultSortType,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
})
|
});
|
||||||
.then(res => {
|
|
||||||
|
if (token !== this.fetchDefaultCommunitiesToken) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
|
const retainSelected: false | undefined | Choice =
|
||||||
|
!res.data.communities.some(cv => cv.community.id === communityId) &&
|
||||||
|
this.state.communitySearchOptions.find(
|
||||||
|
choice => choice.value === communityId?.toString(),
|
||||||
|
);
|
||||||
|
const choices = res.data.communities.map(communityToChoice);
|
||||||
this.setState({
|
this.setState({
|
||||||
communitySearchOptions:
|
communitySearchOptions: retainSelected
|
||||||
res.data.communities.map(communityToChoice),
|
? [retainSelected, ...choices]
|
||||||
|
: choices,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
const { communityId, creatorId } = this.props;
|
this.setState({
|
||||||
|
searchCommunitiesLoading: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (communityId) {
|
fetchSelectedCommunityToken?: symbol;
|
||||||
promises.push(
|
async fetchSelectedCommunity({
|
||||||
HttpService.client.getCommunity({ id: communityId }).then(res => {
|
communityId,
|
||||||
if (res.state === "success") {
|
}: Pick<SearchRouteProps, "communityId">) {
|
||||||
|
const token = (this.fetchSelectedCommunityToken = Symbol());
|
||||||
|
const needsSelectedCommunity = () => {
|
||||||
|
return !this.state.communitySearchOptions.some(
|
||||||
|
choice => choice.value === communityId?.toString(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
if (communityId && needsSelectedCommunity()) {
|
||||||
|
const res = await HttpService.client.getCommunity({ id: communityId });
|
||||||
|
if (
|
||||||
|
res.state === "success" &&
|
||||||
|
needsSelectedCommunity() &&
|
||||||
|
token === this.fetchSelectedCommunityToken
|
||||||
|
) {
|
||||||
this.setState(prev => {
|
this.setState(prev => {
|
||||||
prev.communitySearchOptions.unshift(
|
prev.communitySearchOptions.unshift(
|
||||||
communityToChoice(res.data.community_view),
|
communityToChoice(res.data.community_view),
|
||||||
);
|
);
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creatorId) {
|
fetchSelectedCreatorToken?: symbol;
|
||||||
promises.push(
|
async fetchSelectedCreator({
|
||||||
HttpService.client
|
creatorId,
|
||||||
.getPersonDetails({
|
}: Pick<SearchRouteProps, "creatorId">) {
|
||||||
|
const token = (this.fetchSelectedCreatorToken = Symbol());
|
||||||
|
const needsSelectedCreator = () => {
|
||||||
|
return !this.state.creatorSearchOptions.some(
|
||||||
|
choice => choice.value === creatorId?.toString(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!creatorId || !needsSelectedCreator()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ searchCreatorLoading: true });
|
||||||
|
|
||||||
|
const res = await HttpService.client.getPersonDetails({
|
||||||
person_id: creatorId,
|
person_id: creatorId,
|
||||||
})
|
});
|
||||||
.then(res => {
|
|
||||||
if (res.state === "success") {
|
if (token !== this.fetchSelectedCreatorToken) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.state === "success" && needsSelectedCreator()) {
|
||||||
this.setState(prev => {
|
this.setState(prev => {
|
||||||
prev.creatorSearchOptions.push(
|
prev.creatorSearchOptions.push(personToChoice(res.data.person_view));
|
||||||
personToChoice(res.data.person_view),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
|
||||||
);
|
this.setState({ searchCreatorLoading: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.searchText) {
|
async fetchAll(props: SearchRouteProps) {
|
||||||
promises.push(this.search());
|
await Promise.all([
|
||||||
}
|
this.fetchDefaultCommunities(props),
|
||||||
|
this.fetchSelectedCommunity(props),
|
||||||
await Promise.all(promises);
|
this.fetchSelectedCreator(props),
|
||||||
|
this.search(props),
|
||||||
this.setState({
|
]);
|
||||||
searchCommunitiesLoading: false,
|
|
||||||
searchCreatorLoading: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async fetchInitialData({
|
static async fetchInitialData({
|
||||||
|
@ -413,6 +473,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
type: searchType,
|
type: searchType,
|
||||||
sort,
|
sort,
|
||||||
listingType: listing_type,
|
listingType: listing_type,
|
||||||
|
titleOnly: title_only,
|
||||||
communityId: community_id,
|
communityId: community_id,
|
||||||
creatorId: creator_id,
|
creatorId: creator_id,
|
||||||
page,
|
page,
|
||||||
|
@ -458,6 +519,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
type_: searchType,
|
type_: searchType,
|
||||||
sort,
|
sort,
|
||||||
listing_type,
|
listing_type,
|
||||||
|
title_only,
|
||||||
page,
|
page,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
};
|
};
|
||||||
|
@ -533,7 +595,6 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
case "Comments":
|
case "Comments":
|
||||||
return this.comments;
|
return this.comments;
|
||||||
case "Posts":
|
case "Posts":
|
||||||
case "Url":
|
|
||||||
return this.posts;
|
return this.posts;
|
||||||
case "Communities":
|
case "Communities":
|
||||||
return this.communities;
|
return this.communities;
|
||||||
|
@ -551,13 +612,15 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
onSubmit={linkEvent(this, this.handleSearchSubmit)}
|
onSubmit={linkEvent(this, this.handleSearchSubmit)}
|
||||||
>
|
>
|
||||||
<div className="col-auto flex-grow-1 flex-sm-grow-0">
|
<div className="col-auto flex-grow-1 flex-sm-grow-0">
|
||||||
|
{/* key is necessary for defaultValue to update when props.q changes,
|
||||||
|
e.g. back button. */}
|
||||||
<input
|
<input
|
||||||
|
key={this.context.router.history.location.key}
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control me-2 mb-2 col-sm-8"
|
className="form-control me-2 mb-2 col-sm-8"
|
||||||
value={this.state.searchText}
|
defaultValue={this.props.q ?? ""}
|
||||||
placeholder={`${I18NextService.i18n.t("search")}...`}
|
placeholder={`${I18NextService.i18n.t("search")}...`}
|
||||||
aria-label={I18NextService.i18n.t("search")}
|
aria-label={I18NextService.i18n.t("search")}
|
||||||
onInput={linkEvent(this, this.handleQChange)}
|
|
||||||
required
|
required
|
||||||
minLength={1}
|
minLength={1}
|
||||||
ref={this.searchInput}
|
ref={this.searchInput}
|
||||||
|
@ -577,7 +640,8 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get selects() {
|
get selects() {
|
||||||
const { type, listingType, sort, communityId, creatorId } = this.props;
|
const { type, listingType, titleOnly, sort, communityId, creatorId } =
|
||||||
|
this.props;
|
||||||
const {
|
const {
|
||||||
communitySearchOptions,
|
communitySearchOptions,
|
||||||
creatorSearchOptions,
|
creatorSearchOptions,
|
||||||
|
@ -615,6 +679,20 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
onChange={this.handleListingTypeChange}
|
onChange={this.handleListingTypeChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{(type === "All" || type === "Posts") && (
|
||||||
|
<div className="col">
|
||||||
|
<input
|
||||||
|
className="btn-check"
|
||||||
|
id="title-only"
|
||||||
|
type="checkbox"
|
||||||
|
checked={titleOnly}
|
||||||
|
onChange={this.handleTitleOnlyChange}
|
||||||
|
/>
|
||||||
|
<label className="btn btn-outline-secondary" htmlFor="title-only">
|
||||||
|
{I18NextService.i18n.t("post_title_only")}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<SortSelect
|
<SortSelect
|
||||||
sort={sort}
|
sort={sort}
|
||||||
|
@ -766,7 +844,6 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
allLanguages={siteRes.all_languages}
|
allLanguages={siteRes.all_languages}
|
||||||
siteLanguages={siteRes.discussion_languages}
|
siteLanguages={siteRes.discussion_languages}
|
||||||
// All of these are unused, since its viewonly
|
// All of these are unused, since its viewonly
|
||||||
finished={new Map()}
|
|
||||||
onSaveComment={async () => {}}
|
onSaveComment={async () => {}}
|
||||||
onBlockPerson={async () => {}}
|
onBlockPerson={async () => {}}
|
||||||
onDeleteComment={async () => {}}
|
onDeleteComment={async () => {}}
|
||||||
|
@ -828,7 +905,6 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
allLanguages={siteRes.all_languages}
|
allLanguages={siteRes.all_languages}
|
||||||
siteLanguages={siteRes.discussion_languages}
|
siteLanguages={siteRes.discussion_languages}
|
||||||
// All of these are unused, since its viewonly
|
// All of these are unused, since its viewonly
|
||||||
finished={new Map()}
|
|
||||||
onSaveComment={async () => {}}
|
onSaveComment={async () => {}}
|
||||||
onBlockPerson={async () => {}}
|
onBlockPerson={async () => {}}
|
||||||
onDeleteComment={async () => {}}
|
onDeleteComment={async () => {}}
|
||||||
|
@ -984,35 +1060,50 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
return resObjCount + searchCount;
|
return resObjCount + searchCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
async search() {
|
searchToken?: symbol;
|
||||||
const { searchText: q } = this.state;
|
async search(props: SearchRouteProps) {
|
||||||
const { communityId, creatorId, type, sort, listingType, page } =
|
const token = (this.searchToken = Symbol());
|
||||||
this.props;
|
const {
|
||||||
|
q,
|
||||||
|
communityId,
|
||||||
|
creatorId,
|
||||||
|
type,
|
||||||
|
sort,
|
||||||
|
listingType,
|
||||||
|
titleOnly,
|
||||||
|
page,
|
||||||
|
} = props;
|
||||||
|
|
||||||
if (q) {
|
if (q) {
|
||||||
this.setState({ searchRes: LOADING_REQUEST });
|
this.setState({ searchRes: LOADING_REQUEST });
|
||||||
this.setState({
|
const searchRes = await HttpService.client.search({
|
||||||
searchRes: await HttpService.client.search({
|
|
||||||
q,
|
q,
|
||||||
community_id: communityId ?? undefined,
|
community_id: communityId ?? undefined,
|
||||||
creator_id: creatorId ?? undefined,
|
creator_id: creatorId ?? undefined,
|
||||||
type_: type,
|
type_: type,
|
||||||
sort,
|
sort,
|
||||||
listing_type: listingType,
|
listing_type: listingType,
|
||||||
|
title_only: titleOnly,
|
||||||
page,
|
page,
|
||||||
limit: fetchLimit,
|
limit: fetchLimit,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token !== this.searchToken) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({ searchRes });
|
||||||
|
|
||||||
if (myAuth()) {
|
if (myAuth()) {
|
||||||
this.setState({ resolveObjectRes: LOADING_REQUEST });
|
this.setState({ resolveObjectRes: LOADING_REQUEST });
|
||||||
this.setState({
|
const resolveObjectRes = await HttpService.client.resolveObject({
|
||||||
resolveObjectRes: await HttpService.client.resolveObject({
|
|
||||||
q,
|
q,
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
if (token === this.searchToken) {
|
||||||
|
this.setState({ resolveObjectRes });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.setState({ searchRes: EMPTY_REQUEST });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCreatorSearch = debounce(async (text: string) => {
|
handleCreatorSearch = debounce(async (text: string) => {
|
||||||
|
@ -1053,8 +1144,17 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
handleSortChange(sort: SortType) {
|
getQ(): string | undefined {
|
||||||
this.updateUrl({ sort, page: 1 });
|
return this.searchInput.current?.value ?? this.props.q;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSortChange(sort: PostSortType) {
|
||||||
|
this.updateUrl({ sort, page: 1, q: this.getQ() });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTitleOnlyChange(event: any) {
|
||||||
|
const titleOnly = event.target.checked;
|
||||||
|
this.updateUrl({ titleOnly, q: this.getQ() });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTypeChange(i: Search, event: any) {
|
handleTypeChange(i: Search, event: any) {
|
||||||
|
@ -1063,6 +1163,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
i.updateUrl({
|
i.updateUrl({
|
||||||
type,
|
type,
|
||||||
page: 1,
|
page: 1,
|
||||||
|
q: i.getQ(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,20 +1175,23 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
this.updateUrl({
|
this.updateUrl({
|
||||||
listingType,
|
listingType,
|
||||||
page: 1,
|
page: 1,
|
||||||
|
q: this.getQ(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommunityFilterChange({ value }: Choice) {
|
handleCommunityFilterChange({ value }: Choice) {
|
||||||
this.updateUrl({
|
this.updateUrl({
|
||||||
communityId: getIdFromString(value) ?? 0,
|
communityId: getIdFromString(value),
|
||||||
page: 1,
|
page: 1,
|
||||||
|
q: this.getQ(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCreatorFilterChange({ value }: Choice) {
|
handleCreatorFilterChange({ value }: Choice) {
|
||||||
this.updateUrl({
|
this.updateUrl({
|
||||||
creatorId: getIdFromString(value) ?? 0,
|
creatorId: getIdFromString(value),
|
||||||
page: 1,
|
page: 1,
|
||||||
|
q: this.getQ(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,44 +1199,35 @@ export class Search extends Component<SearchRouteProps, SearchState> {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
i.updateUrl({
|
i.updateUrl({
|
||||||
q: i.state.searchText,
|
q: i.getQ(),
|
||||||
page: 1,
|
page: 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleQChange(i: Search, event: any) {
|
async updateUrl(props: Partial<SearchProps>) {
|
||||||
i.setState({ searchText: event.target.value });
|
const {
|
||||||
}
|
|
||||||
|
|
||||||
async updateUrl({
|
|
||||||
q,
|
q,
|
||||||
type,
|
type,
|
||||||
listingType,
|
listingType,
|
||||||
|
titleOnly,
|
||||||
sort,
|
sort,
|
||||||
communityId,
|
communityId,
|
||||||
creatorId,
|
creatorId,
|
||||||
page,
|
page,
|
||||||
}: Partial<SearchProps>) {
|
} = {
|
||||||
const {
|
...this.props,
|
||||||
q: urlQ,
|
...props,
|
||||||
type: urlType,
|
};
|
||||||
listingType: urlListingType,
|
|
||||||
communityId: urlCommunityId,
|
|
||||||
sort: urlSort,
|
|
||||||
creatorId: urlCreatorId,
|
|
||||||
page: urlPage,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const query = q ?? this.state.searchText ?? urlQ;
|
|
||||||
|
|
||||||
const queryParams: QueryParams<SearchProps> = {
|
const queryParams: QueryParams<SearchProps> = {
|
||||||
q: query,
|
q,
|
||||||
type: type ?? urlType,
|
type: type,
|
||||||
listingType: listingType ?? urlListingType,
|
listingType: listingType,
|
||||||
communityId: getUpdatedSearchId(communityId, urlCommunityId),
|
titleOnly: titleOnly?.toString(),
|
||||||
creatorId: getUpdatedSearchId(creatorId, urlCreatorId),
|
communityId: communityId?.toString(),
|
||||||
page: (page ?? urlPage).toString(),
|
creatorId: creatorId?.toString(),
|
||||||
sort: sort ?? urlSort,
|
page: page?.toString(),
|
||||||
|
sort: sort,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.history.push(`/search${getQueryString(queryParams)}`);
|
this.props.history.push(`/search${getQueryString(queryParams)}`);
|
||||||
|
|
|
@ -9,6 +9,7 @@ export const donateLemmyUrl = `${joinLemmyUrl}/donate`;
|
||||||
export const docsUrl = `${joinLemmyUrl}/docs/en/index.html`;
|
export const docsUrl = `${joinLemmyUrl}/docs/en/index.html`;
|
||||||
export const helpGuideUrl = `${joinLemmyUrl}/docs/en/users/01-getting-started.html`; // TODO find a way to redirect to the non-en folder
|
export const helpGuideUrl = `${joinLemmyUrl}/docs/en/users/01-getting-started.html`; // TODO find a way to redirect to the non-en folder
|
||||||
export const markdownHelpUrl = `${joinLemmyUrl}/docs/en/users/02-media.html`;
|
export const markdownHelpUrl = `${joinLemmyUrl}/docs/en/users/02-media.html`;
|
||||||
|
export const torrentHelpUrl = `${markdownHelpUrl}#torrents`;
|
||||||
export const sortingHelpUrl = `${joinLemmyUrl}/docs/en/users/03-votes-and-ranking.html`;
|
export const sortingHelpUrl = `${joinLemmyUrl}/docs/en/users/03-votes-and-ranking.html`;
|
||||||
export const archiveTodayUrl = "https://archive.today";
|
export const archiveTodayUrl = "https://archive.today";
|
||||||
export const ghostArchiveUrl = "https://ghostarchive.org";
|
export const ghostArchiveUrl = "https://ghostarchive.org";
|
||||||
|
@ -16,7 +17,6 @@ export const webArchiveUrl = "https://web.archive.org";
|
||||||
export const elementUrl = "https://element.io";
|
export const elementUrl = "https://element.io";
|
||||||
|
|
||||||
export const postRefetchSeconds: number = 60 * 1000;
|
export const postRefetchSeconds: number = 60 * 1000;
|
||||||
export const trendingFetchLimit = 6;
|
|
||||||
export const mentionDropdownFetchLimit = 10;
|
export const mentionDropdownFetchLimit = 10;
|
||||||
export const commentTreeMaxDepth = 8;
|
export const commentTreeMaxDepth = 8;
|
||||||
export const postMarkdownFieldCharacterLimit = 50000;
|
export const postMarkdownFieldCharacterLimit = 50000;
|
||||||
|
@ -25,6 +25,7 @@ export const maxUploadImages = 20;
|
||||||
export const concurrentImageUpload = 4;
|
export const concurrentImageUpload = 4;
|
||||||
export const updateUnreadCountsInterval = 30000;
|
export const updateUnreadCountsInterval = 30000;
|
||||||
export const fetchLimit = 20;
|
export const fetchLimit = 20;
|
||||||
|
export const similarPostFetchLimit = 6;
|
||||||
export const relTags = "noopener nofollow";
|
export const relTags = "noopener nofollow";
|
||||||
export const emDash = "\u2014";
|
export const emDash = "\u2014";
|
||||||
export const authCookieName = "jwt";
|
export const authCookieName = "jwt";
|
||||||
|
@ -49,3 +50,6 @@ export const instanceLinkRegex = new RegExp(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const testHost = "0.0.0.0:8536";
|
export const testHost = "0.0.0.0:8536";
|
||||||
|
|
||||||
|
export const validActorRegexPattern =
|
||||||
|
"^\\w+|[\\p{Script=Arabic}\\d_]+|[\\p{Script=Cyrillic}\\d_]+$";
|
||||||
|
|
|
@ -46,6 +46,11 @@ export interface PostFormParams {
|
||||||
name?: string;
|
name?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
body?: string;
|
body?: string;
|
||||||
|
nsfw?: boolean;
|
||||||
|
language_id?: number;
|
||||||
|
community_id?: number;
|
||||||
|
custom_thumbnail?: string;
|
||||||
|
alt_text?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CommentViewType {
|
export enum CommentViewType {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { communitySearch, personSearch } from "@utils/app";
|
import { communitySearch, personSearch } from "@utils/app";
|
||||||
import { isBrowser } from "@utils/browser";
|
|
||||||
import { debounce, groupBy } from "@utils/helpers";
|
import { debounce, groupBy } from "@utils/helpers";
|
||||||
import { CommunityTribute, PersonTribute } from "@utils/types";
|
import { CommunityTribute, PersonTribute } from "@utils/types";
|
||||||
import { Picker } from "emoji-mart";
|
import { Picker } from "emoji-mart";
|
||||||
|
@ -15,12 +14,13 @@ import markdown_it_ruby from "markdown-it-ruby";
|
||||||
import markdown_it_sub from "markdown-it-sub";
|
import markdown_it_sub from "markdown-it-sub";
|
||||||
import markdown_it_sup from "markdown-it-sup";
|
import markdown_it_sup from "markdown-it-sup";
|
||||||
import markdown_it_highlightjs from "markdown-it-highlightjs/core";
|
import markdown_it_highlightjs from "markdown-it-highlightjs/core";
|
||||||
import Renderer from "markdown-it/lib/renderer";
|
import { Renderer, Token } from "markdown-it";
|
||||||
import Token from "markdown-it/lib/token";
|
|
||||||
import { instanceLinkRegex, relTags } from "./config";
|
import { instanceLinkRegex, relTags } from "./config";
|
||||||
import { lazyHighlightjs } from "./lazy-highlightjs";
|
import { lazyHighlightjs } from "./lazy-highlightjs";
|
||||||
|
import { HttpService } from "./services";
|
||||||
|
import { WrappedLemmyHttp } from "./services/HttpService";
|
||||||
|
|
||||||
export let Tribute: any;
|
let Tribute: any;
|
||||||
|
|
||||||
export let md: MarkdownIt = new MarkdownIt();
|
export let md: MarkdownIt = new MarkdownIt();
|
||||||
|
|
||||||
|
@ -34,17 +34,13 @@ export const mdLimited: MarkdownIt = new MarkdownIt("zero").enable([
|
||||||
"strikethrough",
|
"strikethrough",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const customEmojis: EmojiMartCategory[] = [];
|
let customEmojis: EmojiMartCategory[] = [];
|
||||||
|
|
||||||
export let customEmojisLookup: Map<string, CustomEmojiView> = new Map<
|
export let customEmojisLookup: Map<string, CustomEmojiView> = new Map<
|
||||||
string,
|
string,
|
||||||
CustomEmojiView
|
CustomEmojiView
|
||||||
>();
|
>();
|
||||||
|
|
||||||
if (isBrowser()) {
|
|
||||||
Tribute = require("tributejs");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mdToHtml(text: string, rerender: () => void) {
|
export function mdToHtml(text: string, rerender: () => void) {
|
||||||
return { __html: lazyHighlightjs.render(md, text, rerender) };
|
return { __html: lazyHighlightjs.render(md, text, rerender) };
|
||||||
}
|
}
|
||||||
|
@ -210,14 +206,17 @@ export function setupMarkdown() {
|
||||||
) {
|
) {
|
||||||
//Provide custom renderer for our emojis to allow us to add a css class and force size dimensions on them.
|
//Provide custom renderer for our emojis to allow us to add a css class and force size dimensions on them.
|
||||||
const item = tokens[idx] as any;
|
const item = tokens[idx] as any;
|
||||||
let title = item.attrs.length >= 3 ? item.attrs[2][1] : "";
|
const url = item.attrs.length > 0 ? item.attrs[0][1] : "";
|
||||||
|
const altText = item.attrs.length > 1 ? item.attrs[1][1] : "";
|
||||||
|
const title = item.attrs.length > 2 ? item.attrs[2][1] : "";
|
||||||
const splitTitle = title.split(/ (.*)/, 2);
|
const splitTitle = title.split(/ (.*)/, 2);
|
||||||
const isEmoji = splitTitle[0] === "emoji";
|
const isEmoji = splitTitle[0] === "emoji";
|
||||||
|
let shortcode: string | undefined;
|
||||||
if (isEmoji) {
|
if (isEmoji) {
|
||||||
title = splitTitle[1];
|
shortcode = splitTitle[1];
|
||||||
}
|
}
|
||||||
const customEmoji = customEmojisLookup.get(title);
|
// customEmojisLookup is empty in SSR, CSR rerenders markdown anyway
|
||||||
const isLocalEmoji = customEmoji !== undefined;
|
const isLocalEmoji = shortcode && customEmojisLookup.has(shortcode);
|
||||||
if (!isLocalEmoji) {
|
if (!isLocalEmoji) {
|
||||||
const imgElement =
|
const imgElement =
|
||||||
defaultImageRenderer?.(tokens, idx, options, env, self) ?? "";
|
defaultImageRenderer?.(tokens, idx, options, env, self) ?? "";
|
||||||
|
@ -228,10 +227,8 @@ export function setupMarkdown() {
|
||||||
} else return "";
|
} else return "";
|
||||||
}
|
}
|
||||||
return `<img class="icon icon-emoji" src="${
|
return `<img class="icon icon-emoji" src="${
|
||||||
customEmoji!.custom_emoji.image_url
|
url
|
||||||
}" title="${customEmoji!.custom_emoji.shortcode}" alt="${
|
}" title="${shortcode}" alt="${altText}"/>`;
|
||||||
customEmoji!.custom_emoji.alt_text
|
|
||||||
}"/>`;
|
|
||||||
};
|
};
|
||||||
md.renderer.rules.table_open = function () {
|
md.renderer.rules.table_open = function () {
|
||||||
return '<table class="table">';
|
return '<table class="table">';
|
||||||
|
@ -253,11 +250,14 @@ export function setupMarkdown() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupEmojiDataModel(custom_emoji_views: CustomEmojiView[]) {
|
export function emojiMartCategories(
|
||||||
|
custom_emoji_views: CustomEmojiView[],
|
||||||
|
): EmojiMartCategory[] {
|
||||||
const groupedEmojis = groupBy(
|
const groupedEmojis = groupBy(
|
||||||
custom_emoji_views,
|
custom_emoji_views,
|
||||||
x => x.custom_emoji.category,
|
x => x.custom_emoji.category,
|
||||||
);
|
);
|
||||||
|
const customEmojis: EmojiMartCategory[] = [];
|
||||||
for (const [category, emojis] of Object.entries(groupedEmojis)) {
|
for (const [category, emojis] of Object.entries(groupedEmojis)) {
|
||||||
customEmojis.push({
|
customEmojis.push({
|
||||||
id: category,
|
id: category,
|
||||||
|
@ -270,63 +270,24 @@ export function setupEmojiDataModel(custom_emoji_views: CustomEmojiView[]) {
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return customEmojis;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setupEmojiDataModel(
|
||||||
|
client: WrappedLemmyHttp = HttpService.client,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const emojisRes = await client.listCustomEmojis({
|
||||||
|
ignore_page_limits: true,
|
||||||
|
});
|
||||||
|
if (emojisRes.state !== "success") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const custom_emoji_views = emojisRes.data.custom_emojis;
|
||||||
|
customEmojis = emojiMartCategories(custom_emoji_views);
|
||||||
customEmojisLookup = new Map(
|
customEmojisLookup = new Map(
|
||||||
custom_emoji_views.map(view => [view.custom_emoji.shortcode, view]),
|
custom_emoji_views.map(view => [view.custom_emoji.shortcode, view]),
|
||||||
);
|
);
|
||||||
}
|
return true;
|
||||||
|
|
||||||
export function updateEmojiDataModel(custom_emoji_view: CustomEmojiView) {
|
|
||||||
const emoji: EmojiMartCustomEmoji = {
|
|
||||||
id: custom_emoji_view.custom_emoji.shortcode,
|
|
||||||
name: custom_emoji_view.custom_emoji.shortcode,
|
|
||||||
keywords: custom_emoji_view.keywords.map(x => x.keyword),
|
|
||||||
skins: [{ src: custom_emoji_view.custom_emoji.image_url }],
|
|
||||||
};
|
|
||||||
const categoryIndex = customEmojis.findIndex(
|
|
||||||
x => x.id === custom_emoji_view.custom_emoji.category,
|
|
||||||
);
|
|
||||||
if (categoryIndex === -1) {
|
|
||||||
customEmojis.push({
|
|
||||||
id: custom_emoji_view.custom_emoji.category,
|
|
||||||
name: custom_emoji_view.custom_emoji.category,
|
|
||||||
emojis: [emoji],
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const emojiIndex = customEmojis[categoryIndex].emojis.findIndex(
|
|
||||||
x => x.id === custom_emoji_view.custom_emoji.shortcode,
|
|
||||||
);
|
|
||||||
if (emojiIndex === -1) {
|
|
||||||
customEmojis[categoryIndex].emojis.push(emoji);
|
|
||||||
} else {
|
|
||||||
customEmojis[categoryIndex].emojis[emojiIndex] = emoji;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customEmojisLookup.set(
|
|
||||||
custom_emoji_view.custom_emoji.shortcode,
|
|
||||||
custom_emoji_view,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeFromEmojiDataModel(id: number) {
|
|
||||||
let view: CustomEmojiView | undefined;
|
|
||||||
for (const item of customEmojisLookup.values()) {
|
|
||||||
if (item.custom_emoji.id === id) {
|
|
||||||
view = item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!view) return;
|
|
||||||
const categoryIndex = customEmojis.findIndex(
|
|
||||||
x => x.id === view?.custom_emoji.category,
|
|
||||||
);
|
|
||||||
const emojiIndex = customEmojis[categoryIndex].emojis.findIndex(
|
|
||||||
x => x.id === view?.custom_emoji.shortcode,
|
|
||||||
);
|
|
||||||
customEmojis[categoryIndex].emojis = customEmojis[
|
|
||||||
categoryIndex
|
|
||||||
].emojis.splice(emojiIndex, 1);
|
|
||||||
|
|
||||||
customEmojisLookup.delete(view?.custom_emoji.shortcode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEmojiMart(
|
export function getEmojiMart(
|
||||||
|
@ -334,14 +295,20 @@ export function getEmojiMart(
|
||||||
customPickerOptions: any = {},
|
customPickerOptions: any = {},
|
||||||
) {
|
) {
|
||||||
const pickerOptions = {
|
const pickerOptions = {
|
||||||
...customPickerOptions,
|
|
||||||
onEmojiSelect: onEmojiSelect,
|
onEmojiSelect: onEmojiSelect,
|
||||||
custom: customEmojis,
|
custom: customEmojis,
|
||||||
|
...customPickerOptions,
|
||||||
};
|
};
|
||||||
return new Picker(pickerOptions);
|
return new Picker(pickerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupTribute() {
|
export async function setupTribute() {
|
||||||
|
// eslint-disable-next-line eqeqeq
|
||||||
|
if (Tribute == null) {
|
||||||
|
console.debug("Tribute is null, importing...");
|
||||||
|
Tribute = (await import("tributejs")).default;
|
||||||
|
}
|
||||||
|
|
||||||
return new Tribute({
|
return new Tribute({
|
||||||
noMatchTemplate: function () {
|
noMatchTemplate: function () {
|
||||||
return "";
|
return "";
|
||||||
|
@ -415,7 +382,7 @@ export function setupTribute() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EmojiMartCategory {
|
export interface EmojiMartCategory {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
emojis: EmojiMartCustomEmoji[];
|
emojis: EmojiMartCustomEmoji[];
|
||||||
|
|
|
@ -28,7 +28,11 @@ import {
|
||||||
} from "./components/home/login";
|
} from "./components/home/login";
|
||||||
import { LoginReset } from "./components/home/login-reset";
|
import { LoginReset } from "./components/home/login-reset";
|
||||||
import { Setup } from "./components/home/setup";
|
import { Setup } from "./components/home/setup";
|
||||||
import { Signup } from "./components/home/signup";
|
import {
|
||||||
|
Signup,
|
||||||
|
SignupFetchConfig,
|
||||||
|
getSignupQueryParams,
|
||||||
|
} from "./components/home/signup";
|
||||||
import {
|
import {
|
||||||
Modlog,
|
Modlog,
|
||||||
ModlogFetchConfig,
|
ModlogFetchConfig,
|
||||||
|
@ -53,7 +57,11 @@ import {
|
||||||
CreatePost,
|
CreatePost,
|
||||||
getCreatePostQueryParams,
|
getCreatePostQueryParams,
|
||||||
} from "./components/post/create-post";
|
} from "./components/post/create-post";
|
||||||
import { Post, PostFetchConfig } from "./components/post/post";
|
import {
|
||||||
|
Post,
|
||||||
|
PostFetchConfig,
|
||||||
|
getPostQueryParams,
|
||||||
|
} from "./components/post/post";
|
||||||
import {
|
import {
|
||||||
CreatePrivateMessage,
|
CreatePrivateMessage,
|
||||||
CreatePrivateMessageFetchConfig,
|
CreatePrivateMessageFetchConfig,
|
||||||
|
@ -71,6 +79,11 @@ import {
|
||||||
import { InitialFetchRequest, RouteData } from "./interfaces";
|
import { InitialFetchRequest, RouteData } from "./interfaces";
|
||||||
import { GetSiteResponse } from "lemmy-js-client";
|
import { GetSiteResponse } from "lemmy-js-client";
|
||||||
import { Inferno } from "inferno";
|
import { Inferno } from "inferno";
|
||||||
|
import {
|
||||||
|
OAuthCallback,
|
||||||
|
OAuthCallbackConfig,
|
||||||
|
getOAuthCallbackQueryParams,
|
||||||
|
} from "./components/home/oauth/oauth-callback";
|
||||||
|
|
||||||
export interface IRoutePropsWithFetch<
|
export interface IRoutePropsWithFetch<
|
||||||
DataT extends RouteData,
|
DataT extends RouteData,
|
||||||
|
@ -87,6 +100,7 @@ export interface IRoutePropsWithFetch<
|
||||||
component: Inferno.ComponentClass<
|
component: Inferno.ComponentClass<
|
||||||
RouteComponentProps<PathPropsT> & QueryPropsT
|
RouteComponentProps<PathPropsT> & QueryPropsT
|
||||||
>;
|
>;
|
||||||
|
mountedSameRouteNavKey?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
||||||
|
@ -96,6 +110,7 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
||||||
fetchInitialData: Home.fetchInitialData,
|
fetchInitialData: Home.fetchInitialData,
|
||||||
exact: true,
|
exact: true,
|
||||||
getQueryParams: getHomeQueryParams,
|
getQueryParams: getHomeQueryParams,
|
||||||
|
mountedSameRouteNavKey: "home",
|
||||||
} as HomeFetchConfig,
|
} as HomeFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/login`,
|
path: `/login`,
|
||||||
|
@ -108,13 +123,15 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/signup`,
|
path: `/signup`,
|
||||||
|
getQueryParams: getSignupQueryParams,
|
||||||
component: Signup,
|
component: Signup,
|
||||||
},
|
} as SignupFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/create_post`,
|
path: `/create_post`,
|
||||||
component: CreatePost,
|
component: CreatePost,
|
||||||
fetchInitialData: CreatePost.fetchInitialData,
|
fetchInitialData: CreatePost.fetchInitialData,
|
||||||
getQueryParams: getCreatePostQueryParams,
|
getQueryParams: getCreatePostQueryParams,
|
||||||
|
mountedSameRouteNavKey: "create_post",
|
||||||
} as CreatePostFetchConfig,
|
} as CreatePostFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/create_community`,
|
path: `/create_community`,
|
||||||
|
@ -130,28 +147,38 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
||||||
component: Communities,
|
component: Communities,
|
||||||
fetchInitialData: Communities.fetchInitialData,
|
fetchInitialData: Communities.fetchInitialData,
|
||||||
getQueryParams: getCommunitiesQueryParams,
|
getQueryParams: getCommunitiesQueryParams,
|
||||||
|
mountedSameRouteNavKey: "communities",
|
||||||
} as CommunitiesFetchConfig,
|
} as CommunitiesFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/post/:post_id`,
|
// "/comment/:post_id?/:comment_id" would be preferable as direct comment
|
||||||
|
// link, but it looks like a Route can't match multiple paths and a
|
||||||
|
// component can't stay mounted across routes.
|
||||||
|
path: `/post/:post_id/:comment_id?`,
|
||||||
component: Post,
|
component: Post,
|
||||||
fetchInitialData: Post.fetchInitialData,
|
fetchInitialData: Post.fetchInitialData,
|
||||||
|
getQueryParams: getPostQueryParams,
|
||||||
|
mountedSameRouteNavKey: "post",
|
||||||
} as PostFetchConfig,
|
} as PostFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/comment/:comment_id`,
|
path: `/comment/:comment_id`,
|
||||||
component: Post,
|
component: Post,
|
||||||
fetchInitialData: Post.fetchInitialData,
|
fetchInitialData: Post.fetchInitialData,
|
||||||
|
getQueryParams: getPostQueryParams,
|
||||||
|
mountedSameRouteNavKey: "post",
|
||||||
} as PostFetchConfig,
|
} as PostFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/c/:name`,
|
path: `/c/:name`,
|
||||||
component: Community,
|
component: Community,
|
||||||
fetchInitialData: Community.fetchInitialData,
|
fetchInitialData: Community.fetchInitialData,
|
||||||
getQueryParams: getCommunityQueryParams,
|
getQueryParams: getCommunityQueryParams,
|
||||||
|
mountedSameRouteNavKey: "community",
|
||||||
} as CommunityFetchConfig,
|
} as CommunityFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/u/:username`,
|
path: `/u/:username`,
|
||||||
component: Profile,
|
component: Profile,
|
||||||
fetchInitialData: Profile.fetchInitialData,
|
fetchInitialData: Profile.fetchInitialData,
|
||||||
getQueryParams: getProfileQueryParams,
|
getQueryParams: getProfileQueryParams,
|
||||||
|
mountedSameRouteNavKey: "profile",
|
||||||
} as ProfileFetchConfig,
|
} as ProfileFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/inbox`,
|
path: `/inbox`,
|
||||||
|
@ -164,16 +191,11 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
||||||
fetchInitialData: Settings.fetchInitialData,
|
fetchInitialData: Settings.fetchInitialData,
|
||||||
} as SettingsFetchConfig,
|
} as SettingsFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/modlog/:communityId`,
|
path: `/modlog/:communityId?`,
|
||||||
component: Modlog,
|
|
||||||
fetchInitialData: Modlog.fetchInitialData,
|
|
||||||
getQueryParams: getModlogQueryParams,
|
|
||||||
} as ModlogFetchConfig,
|
|
||||||
{
|
|
||||||
path: `/modlog`,
|
|
||||||
component: Modlog,
|
component: Modlog,
|
||||||
fetchInitialData: Modlog.fetchInitialData,
|
fetchInitialData: Modlog.fetchInitialData,
|
||||||
getQueryParams: getModlogQueryParams,
|
getQueryParams: getModlogQueryParams,
|
||||||
|
mountedSameRouteNavKey: "modlog",
|
||||||
} as ModlogFetchConfig,
|
} as ModlogFetchConfig,
|
||||||
{ path: `/setup`, component: Setup },
|
{ path: `/setup`, component: Setup },
|
||||||
{
|
{
|
||||||
|
@ -196,6 +218,7 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
||||||
component: Search,
|
component: Search,
|
||||||
fetchInitialData: Search.fetchInitialData,
|
fetchInitialData: Search.fetchInitialData,
|
||||||
getQueryParams: getSearchQueryParams,
|
getQueryParams: getSearchQueryParams,
|
||||||
|
mountedSameRouteNavKey: "search",
|
||||||
} as SearchFetchConfig,
|
} as SearchFetchConfig,
|
||||||
{
|
{
|
||||||
path: `/password_change/:token`,
|
path: `/password_change/:token`,
|
||||||
|
@ -205,6 +228,11 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
|
||||||
path: `/verify_email/:token`,
|
path: `/verify_email/:token`,
|
||||||
component: VerifyEmail,
|
component: VerifyEmail,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: `/oauth/callback`,
|
||||||
|
getQueryParams: getOAuthCallbackQueryParams,
|
||||||
|
component: OAuthCallback,
|
||||||
|
} as OAuthCallbackConfig,
|
||||||
{
|
{
|
||||||
path: `/instances`,
|
path: `/instances`,
|
||||||
component: Instances,
|
component: Instances,
|
||||||
|
|
|
@ -35,6 +35,7 @@ export const languages: TranslationDesc[] = [
|
||||||
{ resource: "ja", code: "ja", name: "日本語" },
|
{ resource: "ja", code: "ja", name: "日本語" },
|
||||||
{ resource: "ko", code: "ko", name: "한국어" },
|
{ resource: "ko", code: "ko", name: "한국어" },
|
||||||
{ resource: "nl", code: "nl", name: "Nederlands" },
|
{ resource: "nl", code: "nl", name: "Nederlands" },
|
||||||
|
{ resource: "nn", code: "nn", name: "nynorsk" },
|
||||||
{ resource: "oc", code: "oc", name: "Occitan" },
|
{ resource: "oc", code: "oc", name: "Occitan" },
|
||||||
{ resource: "pl", code: "pl", name: "Polski" },
|
{ resource: "pl", code: "pl", name: "Polski" },
|
||||||
{ resource: "pt", code: "pt", name: "Português" },
|
{ resource: "pt", code: "pt", name: "Português" },
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue