Merge remote-tracking branch 'origin/main' into renovate/prettier-3.x-lockfile

This commit is contained in:
Dessalines 2024-12-07 16:09:21 -05:00
commit ab16a4391b
97 changed files with 21647 additions and 4883 deletions

View file

@ -3,7 +3,7 @@ variables:
steps:
fetch_git_submodules:
image: node:20-alpine
image: node:22-alpine
commands:
- apk add git
- git submodule init
@ -12,7 +12,7 @@ steps:
- event: [pull_request, tag]
install:
image: node:20-alpine
image: node:22-alpine
commands:
- *install_pnpm
- pnpm i
@ -20,7 +20,7 @@ steps:
- event: pull_request
lint:
image: node:20-alpine
image: node:22-alpine
commands:
- *install_pnpm
- pnpm lint
@ -28,7 +28,7 @@ steps:
- event: pull_request
build_dev:
image: node:20-alpine
image: node:22-alpine
commands:
- *install_pnpm
- pnpm prebuild:dev
@ -38,10 +38,13 @@ steps:
publish_release_docker:
image: woodpeckerci/plugin-docker-buildx
secrets: [docker_username, docker_password]
settings:
repo: dessalines/lemmy-ui
dockerfile: Dockerfile
username:
from_secret: docker_username
password:
from_secret: docker_password
platforms: linux/amd64, linux/arm64
tag: ${CI_COMMIT_TAG}
when:
@ -49,10 +52,13 @@ steps:
nightly_build:
image: woodpeckerci/plugin-docker-buildx
secrets: [docker_username, docker_password]
settings:
repo: dessalines/lemmy-ui
dockerfile: Dockerfile
username:
from_secret: docker_username
password:
from_secret: docker_password
platforms: linux/amd64, linux/arm64
tag: dev
when:

3342
CHANGELOG.md Normal file

File diff suppressed because it is too large Load diff

View file

@ -14,18 +14,19 @@ body = """
{%- if version %} in {{ version }}{%- endif -%}
{% for commit in commits %}
{% if commit.github.pr_title -%}
{%- set commit_message = commit.github.pr_title -%}
{% if commit.remote.pr_title -%}
{%- set commit_message = commit.remote.pr_title -%}
{%- else -%}
{%- set commit_message = commit.message -%}
{%- endif -%}
* {{ commit_message | split(pat="\n") | first | trim }}\
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif -%}
{% if commit.github.pr_number %} in \
[#{{ commit.github.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.github.pr_number }}) \
{% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%}
{% if commit.remote.pr_number %} in \
[#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \
{%- endif %}
{%- endfor -%}
{%- if github -%}
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
{% raw %}\n{% endraw -%}
## New Contributors
@ -36,6 +37,7 @@ body = """
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
{%- endif %}
{%- endfor -%}
{%- endif -%}
{% if version %}
{% if previous.version %}
@ -51,7 +53,7 @@ body = """
"""
# remove the leading and trailing whitespace from the template
trim = true
# changelog footer
# template for the changelog footer
footer = """
<!-- generated by git-cliff -->
"""
@ -70,16 +72,12 @@ commit_preprocessors = [
# remove issue numbers from commits
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
commit_parsers = [
{ 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_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
topo_order = false
# sort the commits inside sections by oldest/newest order

View file

@ -1,4 +1,4 @@
FROM node:20-alpine as builder
FROM node:22-alpine as builder
RUN apk update && apk add curl python3 build-base gcc wget git --no-cache
RUN corepack enable pnpm
@ -30,7 +30,7 @@ RUN echo "export const BUILD_DATE_ISO8601 = '$(date -u +"%Y-%m-%dT%H:%M:%SZ")';"
RUN pnpm i --prefer-offline
RUN pnpm build:dev
FROM node:20-alpine as runner
FROM node:22-alpine as runner
COPY --from=builder /usr/src/app/dist /app/dist
COPY --from=builder /usr/src/app/node_modules /app/node_modules

6
generate_changelog.sh Executable file
View 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 ee2cffac809ad466644f061ad79ac577b6c2e4fd
Subproject commit 2bde7acef9807d28cb13b6584fc63d7b8a457005

View file

@ -1,7 +1,7 @@
{
"name": "lemmy-ui",
"description": "An isomorphic UI for lemmy",
"version": "0.19.5",
"version": "0.19.6-beta.14",
"author": "Dessalines <tyhou13@gmx.com>",
"license": "AGPL-3.0",
"scripts": {
@ -26,12 +26,12 @@
},
"dependencies": {
"@babel/plugin-proposal-decorators": "^7.24.7",
"@babel/plugin-transform-class-properties": "^7.24.7",
"@babel/plugin-transform-runtime": "^7.24.7",
"@babel/plugin-transform-typescript": "^7.24.7",
"@babel/preset-env": "^7.24.7",
"@babel/plugin-transform-class-properties": "^7.25.4",
"@babel/plugin-transform-runtime": "^7.25.4",
"@babel/plugin-transform-typescript": "^7.25.2",
"@babel/preset-env": "^7.25.4",
"@babel/preset-typescript": "^7.24.7",
"@babel/runtime": "^7.24.7",
"@babel/runtime": "^7.25.4",
"@emoji-mart/data": "^1.2.1",
"autosize": "^6.0.1",
"babel-loader": "^9.1.3",
@ -40,18 +40,18 @@
"check-password-strength": "^2.0.10",
"classnames": "^2.5.1",
"clean-webpack-plugin": "^4.0.0",
"cookie": "^0.6.0",
"cookie": "^1.0.0",
"cookie-parser": "^1.4.6",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2",
"date-fns": "^3.6.0",
"date-fns": "^4.0.0",
"emoji-mart": "^5.6.0",
"emoji-short-name": "^2.0.0",
"express": "~4.19.2",
"highlight.js": "^11.9.0",
"express": "~4.21.0",
"highlight.js": "^11.10.0",
"history": "^5.3.0",
"html-to-text": "^9.0.5",
"i18next": "^23.11.5",
"i18next": "^23.14.0",
"inferno": "^8.2.3",
"inferno-create-element": "^8.2.3",
"inferno-helmet": "^5.2.1",
@ -60,78 +60,78 @@
"inferno-router": "^8.2.3",
"inferno-server": "^8.2.3",
"jwt-decode": "^4.0.0",
"lemmy-js-client": "0.19.4",
"lemmy-js-client": "0.20.0-alpha.17",
"lodash.isequal": "^4.5.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-emoji": "^3.0.0",
"markdown-it-footnote": "^4.0.0",
"markdown-it-highlightjs": "^4.1.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-sup": "^2.0.0",
"mini-css-extract-plugin": "^2.9.0",
"qreator": "^9.2.0",
"mini-css-extract-plugin": "^2.9.1",
"qreator": "^9.3.0",
"register-service-worker": "^1.7.2",
"run-node-webpack-plugin": "^1.3.0",
"rxjs": "^7.8.1",
"sanitize-html": "^2.13.0",
"sass": "^1.77.4",
"sass-loader": "^14.2.1",
"sass": "^1.77.8",
"sass-loader": "^16.0.1",
"serialize-javascript": "^6.0.2",
"service-worker-webpack": "^1.0.0",
"sharp": "0.33.4",
"sharp": "0.33.5",
"tippy.js": "^6.3.7",
"toastify-js": "^1.12.0",
"tributejs": "^5.1.3",
"webpack": "^5.91.0",
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4",
"webpack-node-externals": "^3.0.0"
},
"devDependencies": {
"@babel/core": "^7.24.7",
"@eslint/js": "^9.4.0",
"@babel/core": "^7.25.2",
"@eslint/js": "^9.9.1",
"@types/autosize": "^4.0.3",
"@types/bootstrap": "^5.2.10",
"@types/cookie": "^0.6.0",
"@types/cookie": "^1.0.0",
"@types/cookie-parser": "^1.4.7",
"@types/express": "^4.17.21",
"@types/html-to-text": "^9.0.4",
"@types/lodash.isequal": "^4.5.8",
"@types/markdown-it": "^14.1.1",
"@types/markdown-it": "^14.1.2",
"@types/markdown-it-container": "^2.0.10",
"@types/node": "^20.14.2",
"@types/path-browserify": "^1.0.2",
"@types/sanitize-html": "^2.11.0",
"@types/node": "^22.5.0",
"@types/path-browserify": "^1.0.3",
"@types/sanitize-html": "^2.13.0",
"@types/serialize-javascript": "^5.0.4",
"@types/toastify-js": "^1.12.3",
"@typescript-eslint/eslint-plugin": "^7.12.0",
"@typescript-eslint/parser": "^7.12.0",
"eslint": "^9.4.0",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"@typescript-eslint/parser": "^8.3.0",
"eslint": "^9.9.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-inferno": "^7.34.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "^5.1.3",
"globals": "^15.3.0",
"husky": "^9.0.11",
"eslint-plugin-jsx-a11y": "^6.9.0",
"eslint-plugin-prettier": "^5.2.1",
"globals": "^15.9.0",
"husky": "^9.1.5",
"import-sort-style-module": "^6.0.0",
"lint-staged": "^15.2.5",
"prettier": "^3.3.1",
"lint-staged": "^15.2.9",
"prettier": "^3.4.1",
"prettier-plugin-import-sort": "^0.0.7",
"prettier-plugin-organize-imports": "^4.0.0",
"prettier-plugin-packagejson": "^2.5.0",
"qs": "^6.12.1",
"rimraf": "^6.0.0",
"prettier-plugin-packagejson": "^2.5.2",
"qs": "^6.13.0",
"rimraf": "^6.0.1",
"sortpack": "^2.4.0",
"style-loader": "^4.0.0",
"terser": "^5.31.0",
"typescript": "^5.4.5",
"typescript-eslint": "^7.12.0",
"terser": "^5.31.6",
"typescript": "^5.5.4",
"typescript-eslint": "^8.3.0",
"typescript-language-server": "^4.3.3",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-dev-server": "5.0.4"
"webpack-dev-server": "5.1.0"
},
"lint-staged": {
"*.{css, scss}": [
@ -145,7 +145,7 @@
"sortpack"
]
},
"packageManager": "pnpm@9.5.0",
"packageManager": "pnpm@9.15.0+sha512.76e2379760a4328ec4415815bcd6628dee727af3779aaa4c914e3944156c4299921a89f976381ee107d41f12cfa4b66681ca9c718f0668fa0831ed4c6d8ba56c",
"engineStrict": true,
"importSort": {
".js, .jsx, .ts, .tsx": {

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,7 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"automerge": true
"schedule": ["every weekend"],
"automerge": true,
"ignoreDeps": ["lemmy-js-client"]
}

View file

@ -461,3 +461,15 @@ br.big {
.totp-link {
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%;
}

View file

@ -85,28 +85,28 @@ hr.my-3 {
--bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 48, 48, 48;
--bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: #004b38;
--bs-secondary-text-emphasis: #45484c;
--bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: #5c1e18;
--bs-primary-text-emphasis: rgb(0, 75.2, 56);
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6);
--bs-success-text-emphasis: rgb(0, 75.2, 56);
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
--bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: #ccf2e8;
--bs-secondary-bg-subtle: #eff0f2;
--bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: #fcfcfd;
--bs-primary-bg-subtle: rgb(204, 241.6, 232);
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8);
--bs-success-bg-subtle: rgb(204, 241.6, 232);
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #99e4d1;
--bs-secondary-border-subtle: #dee1e5;
--bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: #f5b7b1;
--bs-primary-border-subtle: rgb(153, 228.2, 209);
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6);
--bs-success-border-subtle: rgb(153, 228.2, 209);
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
--bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
@ -137,7 +137,7 @@ hr.my-3 {
--bs-link-color: #00bc8c;
--bs-link-color-rgb: 0, 188, 140;
--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-code-color: #d63384;
--bs-highlight-color: #dee2e6;
@ -182,44 +182,44 @@ hr.my-3 {
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: #66d7ba;
--bs-secondary-text-emphasis: #ced3d7;
--bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: #f1948a;
--bs-primary-text-emphasis: rgb(102, 214.8, 186);
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4);
--bs-success-text-emphasis: rgb(102, 214.8, 186);
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #00261c;
--bs-secondary-bg-subtle: #232426;
--bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: #2e0f0c;
--bs-primary-bg-subtle: rgb(0, 37.6, 28);
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8);
--bs-success-bg-subtle: rgb(0, 37.6, 28);
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
--bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: #007154;
--bs-secondary-border-subtle: #686d71;
--bs-success-border-subtle: #007154;
--bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: #8b2e24;
--bs-primary-border-subtle: rgb(0, 112.8, 84);
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4);
--bs-success-border-subtle: rgb(0, 112.8, 84);
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
--bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030;
--bs-heading-color: inherit;
--bs-link-color: #66d7ba;
--bs-link-hover-color: #85dfc8;
--bs-link-color: rgb(102, 214.8, 186);
--bs-link-hover-color: rgb(132.6, 222.84, 199.8);
--bs-link-color-rgb: 102, 215, 186;
--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-bg: #333;
--bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: #f1948a;
--bs-form-valid-color: rgb(102, 214.8, 186);
--bs-form-valid-border-color: rgb(102, 214.8, 186);
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
}
*,
@ -1951,13 +1951,13 @@ progress {
.table-primary {
--bs-table-color: #000;
--bs-table-bg: #ccf2e8;
--bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: #c2e6dc;
--bs-table-bg: rgb(204, 241.6, 232);
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
--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-hover-bg: #bde0d7;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1965,13 +1965,13 @@ progress {
.table-secondary {
--bs-table-color: #000;
--bs-table-bg: #eff0f2;
--bs-table-border-color: #bfc0c2;
--bs-table-striped-bg: #e3e4e6;
--bs-table-bg: rgb(238.6, 240.2, 241.8);
--bs-table-border-color: rgb(190.88, 192.16, 193.44);
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71);
--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-hover-bg: #dddee0;
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1979,13 +1979,13 @@ progress {
.table-success {
--bs-table-color: #000;
--bs-table-bg: #ccf2e8;
--bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: #c2e6dc;
--bs-table-bg: rgb(204, 241.6, 232);
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
--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-hover-bg: #bde0d7;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1993,13 +1993,13 @@ progress {
.table-info {
--bs-table-color: #000;
--bs-table-bg: #d6eaf8;
--bs-table-border-color: #abbbc6;
--bs-table-striped-bg: #cbdeec;
--bs-table-bg: rgb(214.4, 234.4, 247.8);
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
--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-hover-bg: #c6d8e5;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2007,13 +2007,13 @@ progress {
.table-warning {
--bs-table-color: #000;
--bs-table-bg: #fdebd0;
--bs-table-border-color: #cabca6;
--bs-table-striped-bg: #f0dfc6;
--bs-table-bg: rgb(252.6, 235.2, 207.6);
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
--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-hover-bg: #ead9c0;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2021,13 +2021,13 @@ progress {
.table-danger {
--bs-table-color: #000;
--bs-table-bg: #fadbd8;
--bs-table-border-color: #c8afad;
--bs-table-striped-bg: #eed0cd;
--bs-table-bg: rgb(250.2, 219.2, 216);
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
--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-hover-bg: #e7cbc8;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2036,12 +2036,12 @@ progress {
.table-light {
--bs-table-color: #fff;
--bs-table-bg: #303030;
--bs-table-border-color: #595959;
--bs-table-striped-bg: #3a3a3a;
--bs-table-border-color: rgb(89.4, 89.4, 89.4);
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35);
--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-hover-bg: #404040;
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2050,12 +2050,12 @@ progress {
.table-dark {
--bs-table-color: #000;
--bs-table-bg: #dee2e6;
--bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: #d3d7db;
--bs-table-border-color: rgb(177.6, 180.8, 184);
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
--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-hover-bg: #cdd1d5;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2155,7 +2155,7 @@ progress {
.form-control:focus {
color: #fff;
background-color: #444;
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
}
@ -2173,7 +2173,7 @@ progress {
opacity: 1;
}
.form-control:disabled {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
opacity: 1;
}
.form-control::file-selector-button {
@ -2300,7 +2300,7 @@ textarea.form-control-lg {
}
}
.form-select:focus {
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
}
@ -2309,7 +2309,7 @@ textarea.form-control-lg {
background-image: none;
}
.form-select:disabled {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
}
.form-select:-moz-focusring {
color: transparent;
@ -2384,7 +2384,7 @@ textarea.form-control-lg {
filter: brightness(90%);
}
.form-check-input:focus {
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2501,7 +2501,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #b3ebdd;
background-color: rgb(178.5, 234.9, 220.5);
}
.form-range::-webkit-slider-runnable-track {
width: 100%;
@ -2527,7 +2527,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #b3ebdd;
background-color: rgb(178.5, 234.9, 220.5);
}
.form-range::-moz-range-track {
width: 100%;
@ -2634,7 +2634,7 @@ textarea.form-control-lg {
}
.form-floating > :disabled ~ label::after,
.form-floating > .form-control:disabled ~ label::after {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
}
.input-group {
@ -2991,12 +2991,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: #1ac398;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
--bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: #1ac398;
--bs-btn-active-bg: rgb(51, 201.4, 163);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c;
@ -3008,12 +3008,12 @@ textarea.form-control-lg {
--bs-btn-bg: #adb5bd;
--bs-btn-border-color: #adb5bd;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #b9c0c7;
--bs-btn-hover-border-color: #b5bcc4;
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9);
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6);
--bs-btn-focus-shadow-rgb: 147, 154, 161;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #bdc4ca;
--bs-btn-active-border-color: #b5bcc4;
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #adb5bd;
@ -3025,12 +3025,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: #1ac398;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
--bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: #1ac398;
--bs-btn-active-bg: rgb(51, 201.4, 163);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c;
@ -3042,12 +3042,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #2c81ba;
--bs-btn-hover-border-color: #2a7aaf;
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15);
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2);
--bs-btn-focus-shadow-rgb: 82, 167, 224;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #2a7aaf;
--bs-btn-active-border-color: #2772a4;
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #3498db;
@ -3059,12 +3059,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: #f4a62a;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
--bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: #f4a62a;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12;
@ -3076,12 +3076,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: #b93d30;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
--bs-btn-focus-shadow-rgb: 235, 103, 89;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: #ad392d;
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #e74c3c;
@ -3093,11 +3093,11 @@ textarea.form-control-lg {
--bs-btn-bg: #303030;
--bs-btn-border-color: #303030;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #292929;
--bs-btn-hover-border-color: #262626;
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8);
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4);
--bs-btn-focus-shadow-rgb: 79, 79, 79;
--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-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff;
@ -3110,12 +3110,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: #e1e5e9;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
--bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6;
@ -4506,7 +4506,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%23004b38' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4624,8 +4624,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {
@ -4670,16 +4670,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius);
--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-focus-color: var(--bs-link-hover-color);
--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-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-disabled-color: #fff;
--bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
--bs-pagination-disabled-border-color: transparent;
display: flex;
padding-left: 0;

View file

@ -45,28 +45,28 @@
--bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 17, 17, 17;
--bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: #004b38;
--bs-secondary-text-emphasis: #292929;
--bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: #5c1e18;
--bs-primary-text-emphasis: rgb(0, 75.2, 56);
--bs-secondary-text-emphasis: rgb(40.8, 40.8, 40.8);
--bs-success-text-emphasis: rgb(0, 75.2, 56);
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
--bs-light-text-emphasis: #333;
--bs-dark-text-emphasis: #333;
--bs-primary-bg-subtle: #ccf2e8;
--bs-secondary-bg-subtle: #e0e0e0;
--bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: #f6f6f7;
--bs-primary-bg-subtle: rgb(204, 241.6, 232);
--bs-secondary-bg-subtle: rgb(224.4, 224.4, 224.4);
--bs-success-bg-subtle: rgb(204, 241.6, 232);
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
--bs-light-bg-subtle: rgb(245.5, 246, 246.5);
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #99e4d1;
--bs-secondary-border-subtle: #c2c2c2;
--bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: #f5b7b1;
--bs-primary-border-subtle: rgb(153, 228.2, 209);
--bs-secondary-border-subtle: rgb(193.8, 193.8, 193.8);
--bs-success-border-subtle: rgb(153, 228.2, 209);
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
--bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 243, 243, 243;
@ -97,7 +97,7 @@
--bs-link-color: #00bc8c;
--bs-link-color-rgb: 0, 188, 140;
--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-code-color: #d63384;
--bs-highlight-color: #ebebeb;
@ -140,46 +140,46 @@
--bs-secondary-bg-rgb: 32, 32, 32;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--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-primary-text-emphasis: #66d7ba;
--bs-secondary-text-emphasis: #a3a3a3;
--bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: #f1948a;
--bs-primary-text-emphasis: rgb(102, 214.8, 186);
--bs-secondary-text-emphasis: rgb(163.2, 163.2, 163.2);
--bs-success-text-emphasis: rgb(102, 214.8, 186);
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #00261c;
--bs-secondary-bg-subtle: #141414;
--bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: #2e0f0c;
--bs-primary-bg-subtle: rgb(0, 37.6, 28);
--bs-secondary-bg-subtle: rgb(20.4, 20.4, 20.4);
--bs-success-bg-subtle: rgb(0, 37.6, 28);
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
--bs-light-bg-subtle: #202020;
--bs-dark-bg-subtle: #101010;
--bs-primary-border-subtle: #007154;
--bs-secondary-border-subtle: #3d3d3d;
--bs-success-border-subtle: #007154;
--bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: #8b2e24;
--bs-primary-border-subtle: rgb(0, 112.8, 84);
--bs-secondary-border-subtle: rgb(61.2, 61.2, 61.2);
--bs-success-border-subtle: rgb(0, 112.8, 84);
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
--bs-light-border-subtle: #333;
--bs-dark-border-subtle: #202020;
--bs-heading-color: inherit;
--bs-link-color: #66d7ba;
--bs-link-hover-color: #85dfc8;
--bs-link-color: rgb(102, 214.8, 186);
--bs-link-hover-color: rgb(132.6, 222.84, 199.8);
--bs-link-color-rgb: 102, 215, 186;
--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-bg: #111;
--bs-border-color: #333;
--bs-border-color-translucent: rgba(243, 243, 243, 0.15);
--bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: #f1948a;
--bs-form-valid-color: rgb(102, 214.8, 186);
--bs-form-valid-border-color: rgb(102, 214.8, 186);
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
}
*,
@ -1935,13 +1935,13 @@ progress {
.table-primary {
--bs-table-color: #000;
--bs-table-bg: #ccf2e8;
--bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: #c2e6dc;
--bs-table-bg: rgb(204, 241.6, 232);
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
--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-hover-bg: #bde0d7;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary {
--bs-table-color: #000;
--bs-table-bg: #e0e0e0;
--bs-table-border-color: #b3b3b3;
--bs-table-striped-bg: #d5d5d5;
--bs-table-bg: rgb(224.4, 224.4, 224.4);
--bs-table-border-color: rgb(179.52, 179.52, 179.52);
--bs-table-striped-bg: rgb(213.18, 213.18, 213.18);
--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-hover-bg: #cfcfcf;
--bs-table-hover-bg: rgb(207.57, 207.57, 207.57);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success {
--bs-table-color: #000;
--bs-table-bg: #ccf2e8;
--bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: #c2e6dc;
--bs-table-bg: rgb(204, 241.6, 232);
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
--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-hover-bg: #bde0d7;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info {
--bs-table-color: #000;
--bs-table-bg: #d6eaf8;
--bs-table-border-color: #abbbc6;
--bs-table-striped-bg: #cbdeec;
--bs-table-bg: rgb(214.4, 234.4, 247.8);
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
--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-hover-bg: #c6d8e5;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning {
--bs-table-color: #000;
--bs-table-bg: #fdebd0;
--bs-table-border-color: #cabca6;
--bs-table-striped-bg: #f0dfc6;
--bs-table-bg: rgb(252.6, 235.2, 207.6);
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
--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-hover-bg: #ead9c0;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2005,13 +2005,13 @@ progress {
.table-danger {
--bs-table-color: #000;
--bs-table-bg: #fadbd8;
--bs-table-border-color: #c8afad;
--bs-table-striped-bg: #eed0cd;
--bs-table-bg: rgb(250.2, 219.2, 216);
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
--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-hover-bg: #e7cbc8;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2020,12 +2020,12 @@ progress {
.table-light {
--bs-table-color: #f3f3f3;
--bs-table-bg: #111;
--bs-table-border-color: #3e3e3e;
--bs-table-striped-bg: #1c1c1c;
--bs-table-border-color: rgb(62.2, 62.2, 62.2);
--bs-table-striped-bg: rgb(28.3, 28.3, 28.3);
--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-hover-bg: #222222;
--bs-table-hover-bg: rgb(33.95, 33.95, 33.95);
--bs-table-hover-color: #f3f3f3;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark {
--bs-table-color: #000;
--bs-table-bg: #dee2e6;
--bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: #d3d7db;
--bs-table-border-color: rgb(177.6, 180.8, 184);
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
--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-hover-bg: #cdd1d5;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2139,7 +2139,7 @@ progress {
.form-control:focus {
color: #f3f3f3;
background-color: #111;
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
}
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
}
}
.form-select:focus {
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
}
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
filter: brightness(90%);
}
.form-check-input:focus {
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #b3ebdd;
background-color: rgb(178.5, 234.9, 220.5);
}
.form-range::-webkit-slider-runnable-track {
width: 100%;
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #b3ebdd;
background-color: rgb(178.5, 234.9, 220.5);
}
.form-range::-moz-range-track {
width: 100%;
@ -2975,12 +2975,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: #1ac398;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
--bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: #1ac398;
--bs-btn-active-bg: rgb(51, 201.4, 163);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c;
@ -2992,12 +2992,12 @@ textarea.form-control-lg {
--bs-btn-bg: #666;
--bs-btn-border-color: #666;
--bs-btn-hover-color: #f3f3f3;
--bs-btn-hover-bg: #575757;
--bs-btn-hover-border-color: #525252;
--bs-btn-hover-bg: rgb(86.7, 86.7, 86.7);
--bs-btn-hover-border-color: rgb(81.6, 81.6, 81.6);
--bs-btn-focus-shadow-rgb: 123, 123, 123;
--bs-btn-active-color: #f3f3f3;
--bs-btn-active-bg: #525252;
--bs-btn-active-border-color: #4d4d4d;
--bs-btn-active-bg: rgb(81.6, 81.6, 81.6);
--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-disabled-color: #f3f3f3;
--bs-btn-disabled-bg: #666;
@ -3009,12 +3009,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: #1ac398;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
--bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: #1ac398;
--bs-btn-active-bg: rgb(51, 201.4, 163);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c;
@ -3026,12 +3026,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #52a7e0;
--bs-btn-hover-border-color: #48a2df;
--bs-btn-hover-bg: rgb(82.45, 167.45, 224.4);
--bs-btn-hover-border-color: rgb(72.3, 162.3, 222.6);
--bs-btn-focus-shadow-rgb: 44, 129, 186;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #5dade2;
--bs-btn-active-border-color: #48a2df;
--bs-btn-active-bg: rgb(92.6, 172.6, 226.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #3498db;
@ -3043,12 +3043,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: #f4a62a;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
--bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: #f4a62a;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12;
@ -3060,12 +3060,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #f3f3f3;
--bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: #b93d30;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
--bs-btn-focus-shadow-rgb: 233, 101, 87;
--bs-btn-active-color: #f3f3f3;
--bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: #ad392d;
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
--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-disabled-color: #f3f3f3;
--bs-btn-disabled-bg: #e74c3c;
@ -3077,12 +3077,12 @@ textarea.form-control-lg {
--bs-btn-bg: #111;
--bs-btn-border-color: #111;
--bs-btn-hover-color: #f3f3f3;
--bs-btn-hover-bg: #0e0e0e;
--bs-btn-hover-border-color: #0e0e0e;
--bs-btn-hover-bg: rgb(14.45, 14.45, 14.45);
--bs-btn-hover-border-color: rgb(13.6, 13.6, 13.6);
--bs-btn-focus-shadow-rgb: 51, 51, 51;
--bs-btn-active-color: #f3f3f3;
--bs-btn-active-bg: #0e0e0e;
--bs-btn-active-border-color: #0d0d0d;
--bs-btn-active-bg: rgb(13.6, 13.6, 13.6);
--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-disabled-color: #f3f3f3;
--bs-btn-disabled-bg: #111;
@ -3094,12 +3094,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: #e1e5e9;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
--bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6;
@ -4494,7 +4494,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%23004b38' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4612,8 +4612,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {
@ -4658,16 +4658,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius);
--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-focus-color: var(--bs-link-hover-color);
--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-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-disabled-color: #f3f3f3;
--bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
--bs-pagination-disabled-border-color: transparent;
display: flex;
padding-left: 0;

View file

@ -45,28 +45,28 @@
--bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 48, 48, 48;
--bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: #162433;
--bs-secondary-text-emphasis: #45484c;
--bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: #5c1e18;
--bs-primary-text-emphasis: rgb(22, 36, 50.8);
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6);
--bs-success-text-emphasis: rgb(0, 75.2, 56);
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
--bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: #d7dee5;
--bs-secondary-bg-subtle: #eff0f2;
--bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: #fcfcfd;
--bs-primary-bg-subtle: rgb(215, 222, 229.4);
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8);
--bs-success-bg-subtle: rgb(204, 241.6, 232);
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #afbdcc;
--bs-secondary-border-subtle: #dee1e5;
--bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: #f5b7b1;
--bs-primary-border-subtle: rgb(175, 189, 203.8);
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6);
--bs-success-border-subtle: rgb(153, 228.2, 209);
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
--bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #e74c3c;
--bs-link-color-rgb: 231, 76, 60;
--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-code-color: #d63384;
--bs-highlight-color: #dee2e6;
@ -142,44 +142,44 @@
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: #879cb2;
--bs-secondary-text-emphasis: #ced3d7;
--bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: #f1948a;
--bs-primary-text-emphasis: rgb(135, 156, 178.2);
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4);
--bs-success-text-emphasis: rgb(102, 214.8, 186);
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #0b1219;
--bs-secondary-bg-subtle: #232426;
--bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: #2e0f0c;
--bs-primary-bg-subtle: rgb(11, 18, 25.4);
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8);
--bs-success-bg-subtle: rgb(0, 37.6, 28);
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
--bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: #21364c;
--bs-secondary-border-subtle: #686d71;
--bs-success-border-subtle: #007154;
--bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: #8b2e24;
--bs-primary-border-subtle: rgb(33, 54, 76.2);
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4);
--bs-success-border-subtle: rgb(0, 112.8, 84);
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
--bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030;
--bs-heading-color: inherit;
--bs-link-color: #879cb2;
--bs-link-hover-color: #9fb0c1;
--bs-link-color: rgb(135, 156, 178.2);
--bs-link-hover-color: rgb(159, 175.8, 193.56);
--bs-link-color-rgb: 135, 156, 178;
--bs-link-hover-color-rgb: 159, 176, 193;
--bs-code-color: #e685b5;
--bs-link-hover-color-rgb: 159, 176, 194;
--bs-code-color: rgb(230.4, 132.6, 181.2);
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #333;
--bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: #f1948a;
--bs-form-valid-color: rgb(102, 214.8, 186);
--bs-form-valid-border-color: rgb(102, 214.8, 186);
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
}
*,
@ -1935,13 +1935,13 @@ progress {
.table-primary {
--bs-table-color: #000;
--bs-table-bg: #d7dee5;
--bs-table-border-color: #acb2b7;
--bs-table-striped-bg: #ccd3da;
--bs-table-bg: rgb(215, 222, 229.4);
--bs-table-border-color: rgb(172, 177.6, 183.52);
--bs-table-striped-bg: rgb(204.25, 210.9, 217.93);
--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-hover-bg: #c7cdd4;
--bs-table-hover-bg: rgb(198.875, 205.35, 212.195);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary {
--bs-table-color: #000;
--bs-table-bg: #eff0f2;
--bs-table-border-color: #bfc0c2;
--bs-table-striped-bg: #e3e4e6;
--bs-table-bg: rgb(238.6, 240.2, 241.8);
--bs-table-border-color: rgb(190.88, 192.16, 193.44);
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71);
--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-hover-bg: #dddee0;
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success {
--bs-table-color: #000;
--bs-table-bg: #ccf2e8;
--bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: #c2e6dc;
--bs-table-bg: rgb(204, 241.6, 232);
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
--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-hover-bg: #bde0d7;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info {
--bs-table-color: #000;
--bs-table-bg: #d6eaf8;
--bs-table-border-color: #abbbc6;
--bs-table-striped-bg: #cbdeec;
--bs-table-bg: rgb(214.4, 234.4, 247.8);
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
--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-hover-bg: #c6d8e5;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning {
--bs-table-color: #000;
--bs-table-bg: #fdebd0;
--bs-table-border-color: #cabca6;
--bs-table-striped-bg: #f0dfc6;
--bs-table-bg: rgb(252.6, 235.2, 207.6);
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
--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-hover-bg: #ead9c0;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2005,13 +2005,13 @@ progress {
.table-danger {
--bs-table-color: #000;
--bs-table-bg: #fadbd8;
--bs-table-border-color: #c8afad;
--bs-table-striped-bg: #eed0cd;
--bs-table-bg: rgb(250.2, 219.2, 216);
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
--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-hover-bg: #e7cbc8;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2020,12 +2020,12 @@ progress {
.table-light {
--bs-table-color: #fff;
--bs-table-bg: #303030;
--bs-table-border-color: #595959;
--bs-table-striped-bg: #3a3a3a;
--bs-table-border-color: rgb(89.4, 89.4, 89.4);
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35);
--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-hover-bg: #404040;
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark {
--bs-table-color: #000;
--bs-table-bg: #dee2e6;
--bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: #d3d7db;
--bs-table-border-color: rgb(177.6, 180.8, 184);
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
--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-hover-bg: #cdd1d5;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2139,7 +2139,7 @@ progress {
.form-control:focus {
color: #fff;
background-color: #444;
border-color: #9badbf;
border-color: rgb(155, 172.5, 191);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
}
@ -2157,7 +2157,7 @@ progress {
opacity: 1;
}
.form-control:disabled {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
opacity: 1;
}
.form-control::file-selector-button {
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
}
}
.form-select:focus {
border-color: #9badbf;
border-color: rgb(155, 172.5, 191);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
}
@ -2293,7 +2293,7 @@ textarea.form-control-lg {
background-image: none;
}
.form-select:disabled {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
}
.form-select:-moz-focusring {
color: transparent;
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
filter: brightness(90%);
}
.form-check-input:focus {
border-color: #9badbf;
border-color: rgb(155, 172.5, 191);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #c3ced9;
background-color: rgb(195, 205.5, 216.6);
}
.form-range::-webkit-slider-runnable-track {
width: 100%;
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #c3ced9;
background-color: rgb(195, 205.5, 216.6);
}
.form-range::-moz-range-track {
width: 100%;
@ -2618,7 +2618,7 @@ textarea.form-control-lg {
}
.form-floating > :disabled ~ label::after,
.form-floating > .form-control:disabled ~ label::after {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
}
.input-group {
@ -2975,12 +2975,12 @@ textarea.form-control-lg {
--bs-btn-bg: #375a7f;
--bs-btn-border-color: #375a7f;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #2f4d6c;
--bs-btn-hover-border-color: #2c4866;
--bs-btn-hover-bg: rgb(46.75, 76.5, 107.95);
--bs-btn-hover-border-color: rgb(44, 72, 101.6);
--bs-btn-focus-shadow-rgb: 85, 115, 146;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #2c4866;
--bs-btn-active-border-color: #29445f;
--bs-btn-active-bg: rgb(44, 72, 101.6);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #375a7f;
@ -2992,12 +2992,12 @@ textarea.form-control-lg {
--bs-btn-bg: #adb5bd;
--bs-btn-border-color: #adb5bd;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #b9c0c7;
--bs-btn-hover-border-color: #b5bcc4;
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9);
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6);
--bs-btn-focus-shadow-rgb: 147, 154, 161;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #bdc4ca;
--bs-btn-active-border-color: #b5bcc4;
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #adb5bd;
@ -3009,12 +3009,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: #1ac398;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
--bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: #1ac398;
--bs-btn-active-bg: rgb(51, 201.4, 163);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c;
@ -3026,12 +3026,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #2c81ba;
--bs-btn-hover-border-color: #2a7aaf;
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15);
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2);
--bs-btn-focus-shadow-rgb: 82, 167, 224;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #2a7aaf;
--bs-btn-active-border-color: #2772a4;
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #3498db;
@ -3043,12 +3043,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: #f4a62a;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
--bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: #f4a62a;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12;
@ -3060,12 +3060,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: #b93d30;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
--bs-btn-focus-shadow-rgb: 235, 103, 89;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: #ad392d;
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #e74c3c;
@ -3077,11 +3077,11 @@ textarea.form-control-lg {
--bs-btn-bg: #303030;
--bs-btn-border-color: #303030;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #292929;
--bs-btn-hover-border-color: #262626;
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8);
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4);
--bs-btn-focus-shadow-rgb: 79, 79, 79;
--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-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff;
@ -3094,12 +3094,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: #e1e5e9;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
--bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6;
@ -4494,7 +4494,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%23162433' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4612,8 +4612,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {
@ -4658,16 +4658,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius);
--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-focus-color: var(--bs-link-hover-color);
--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-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-disabled-color: #fff;
--bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
--bs-pagination-disabled-border-color: transparent;
display: flex;
padding-left: 0;

View file

@ -45,28 +45,28 @@
--bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 48, 48, 48;
--bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: #004b38;
--bs-secondary-text-emphasis: #45484c;
--bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: #5c1e18;
--bs-primary-text-emphasis: rgb(0, 75.2, 56);
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6);
--bs-success-text-emphasis: rgb(0, 75.2, 56);
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6);
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2);
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24);
--bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: #ccf2e8;
--bs-secondary-bg-subtle: #eff0f2;
--bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: #fcfcfd;
--bs-primary-bg-subtle: rgb(204, 241.6, 232);
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8);
--bs-success-bg-subtle: rgb(204, 241.6, 232);
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8);
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6);
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216);
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #99e4d1;
--bs-secondary-border-subtle: #dee1e5;
--bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: #f5b7b1;
--bs-primary-border-subtle: rgb(153, 228.2, 209);
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6);
--bs-success-border-subtle: rgb(153, 228.2, 209);
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6);
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2);
--bs-danger-border-subtle: rgb(245.4, 183.4, 177);
--bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #00bc8c;
--bs-link-color-rgb: 0, 188, 140;
--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-code-color: #d63384;
--bs-highlight-color: #dee2e6;
@ -142,44 +142,44 @@
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: #66d7ba;
--bs-secondary-text-emphasis: #ced3d7;
--bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: #f1948a;
--bs-primary-text-emphasis: rgb(102, 214.8, 186);
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4);
--bs-success-text-emphasis: rgb(102, 214.8, 186);
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4);
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8);
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138);
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #00261c;
--bs-secondary-bg-subtle: #232426;
--bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: #2e0f0c;
--bs-primary-bg-subtle: rgb(0, 37.6, 28);
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8);
--bs-success-bg-subtle: rgb(0, 37.6, 28);
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8);
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6);
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12);
--bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: #007154;
--bs-secondary-border-subtle: #686d71;
--bs-success-border-subtle: #007154;
--bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: #8b2e24;
--bs-primary-border-subtle: rgb(0, 112.8, 84);
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4);
--bs-success-border-subtle: rgb(0, 112.8, 84);
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4);
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8);
--bs-danger-border-subtle: rgb(138.6, 45.6, 36);
--bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030;
--bs-heading-color: inherit;
--bs-link-color: #66d7ba;
--bs-link-hover-color: #85dfc8;
--bs-link-color: rgb(102, 214.8, 186);
--bs-link-hover-color: rgb(132.6, 222.84, 199.8);
--bs-link-color-rgb: 102, 215, 186;
--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-bg: #333;
--bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: #f1948a;
--bs-form-valid-color: rgb(102, 214.8, 186);
--bs-form-valid-border-color: rgb(102, 214.8, 186);
--bs-form-invalid-color: rgb(240.6, 147.6, 138);
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138);
}
*,
@ -1935,13 +1935,13 @@ progress {
.table-primary {
--bs-table-color: #000;
--bs-table-bg: #ccf2e8;
--bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: #c2e6dc;
--bs-table-bg: rgb(204, 241.6, 232);
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
--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-hover-bg: #bde0d7;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary {
--bs-table-color: #000;
--bs-table-bg: #eff0f2;
--bs-table-border-color: #bfc0c2;
--bs-table-striped-bg: #e3e4e6;
--bs-table-bg: rgb(238.6, 240.2, 241.8);
--bs-table-border-color: rgb(190.88, 192.16, 193.44);
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71);
--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-hover-bg: #dddee0;
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success {
--bs-table-color: #000;
--bs-table-bg: #ccf2e8;
--bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: #c2e6dc;
--bs-table-bg: rgb(204, 241.6, 232);
--bs-table-border-color: rgb(163.2, 193.28, 185.6);
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4);
--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-hover-bg: #bde0d7;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info {
--bs-table-color: #000;
--bs-table-bg: #d6eaf8;
--bs-table-border-color: #abbbc6;
--bs-table-striped-bg: #cbdeec;
--bs-table-bg: rgb(214.4, 234.4, 247.8);
--bs-table-border-color: rgb(171.52, 187.52, 198.24);
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41);
--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-hover-bg: #c6d8e5;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning {
--bs-table-color: #000;
--bs-table-bg: #fdebd0;
--bs-table-border-color: #cabca6;
--bs-table-striped-bg: #f0dfc6;
--bs-table-bg: rgb(252.6, 235.2, 207.6);
--bs-table-border-color: rgb(202.08, 188.16, 166.08);
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22);
--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-hover-bg: #ead9c0;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2005,13 +2005,13 @@ progress {
.table-danger {
--bs-table-color: #000;
--bs-table-bg: #fadbd8;
--bs-table-border-color: #c8afad;
--bs-table-striped-bg: #eed0cd;
--bs-table-bg: rgb(250.2, 219.2, 216);
--bs-table-border-color: rgb(200.16, 175.36, 172.8);
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2);
--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-hover-bg: #e7cbc8;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2020,12 +2020,12 @@ progress {
.table-light {
--bs-table-color: #fff;
--bs-table-bg: #303030;
--bs-table-border-color: #595959;
--bs-table-striped-bg: #3a3a3a;
--bs-table-border-color: rgb(89.4, 89.4, 89.4);
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35);
--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-hover-bg: #404040;
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark {
--bs-table-color: #000;
--bs-table-bg: #dee2e6;
--bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: #d3d7db;
--bs-table-border-color: rgb(177.6, 180.8, 184);
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5);
--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-hover-bg: #cdd1d5;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2139,7 +2139,7 @@ progress {
.form-control:focus {
color: #fff;
background-color: #444;
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
}
@ -2157,7 +2157,7 @@ progress {
opacity: 1;
}
.form-control:disabled {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
opacity: 1;
}
.form-control::file-selector-button {
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
}
}
.form-select:focus {
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
}
@ -2293,7 +2293,7 @@ textarea.form-control-lg {
background-image: none;
}
.form-select:disabled {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
}
.form-select:-moz-focusring {
color: transparent;
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
filter: brightness(90%);
}
.form-check-input:focus {
border-color: #80dec6;
border-color: rgb(127.5, 221.5, 197.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #b3ebdd;
background-color: rgb(178.5, 234.9, 220.5);
}
.form-range::-webkit-slider-runnable-track {
width: 100%;
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #b3ebdd;
background-color: rgb(178.5, 234.9, 220.5);
}
.form-range::-moz-range-track {
width: 100%;
@ -2618,7 +2618,7 @@ textarea.form-control-lg {
}
.form-floating > :disabled ~ label::after,
.form-floating > .form-control:disabled ~ label::after {
background-color: #2b2b2b;
background-color: rgb(42.5, 42.5, 42.5);
}
.input-group {
@ -2975,12 +2975,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: #1ac398;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
--bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: #1ac398;
--bs-btn-active-bg: rgb(51, 201.4, 163);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c;
@ -2992,12 +2992,12 @@ textarea.form-control-lg {
--bs-btn-bg: #adb5bd;
--bs-btn-border-color: #adb5bd;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #b9c0c7;
--bs-btn-hover-border-color: #b5bcc4;
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9);
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6);
--bs-btn-focus-shadow-rgb: 147, 154, 161;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #bdc4ca;
--bs-btn-active-border-color: #b5bcc4;
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #adb5bd;
@ -3009,12 +3009,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: #1ac398;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25);
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5);
--bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: #1ac398;
--bs-btn-active-bg: rgb(51, 201.4, 163);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c;
@ -3026,12 +3026,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #2c81ba;
--bs-btn-hover-border-color: #2a7aaf;
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15);
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2);
--bs-btn-focus-shadow-rgb: 82, 167, 224;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #2a7aaf;
--bs-btn-active-border-color: #2772a4;
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #3498db;
@ -3043,12 +3043,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: #f4a62a;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55);
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7);
--bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: #f4a62a;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12;
@ -3060,12 +3060,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: #b93d30;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51);
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48);
--bs-btn-focus-shadow-rgb: 235, 103, 89;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: #ad392d;
--bs-btn-active-bg: rgb(184.8, 60.8, 48);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #e74c3c;
@ -3077,11 +3077,11 @@ textarea.form-control-lg {
--bs-btn-bg: #303030;
--bs-btn-border-color: #303030;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #292929;
--bs-btn-hover-border-color: #262626;
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8);
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4);
--bs-btn-focus-shadow-rgb: 79, 79, 79;
--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-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff;
@ -3094,12 +3094,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: #e1e5e9;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);
--bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-bg: rgb(228.6, 231.8, 235);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6;
@ -4494,7 +4494,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%23004b38' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4612,8 +4612,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {
@ -4658,16 +4658,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius);
--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-focus-color: var(--bs-link-hover-color);
--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-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-disabled-color: #fff;
--bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936);
--bs-pagination-disabled-border-color: transparent;
display: flex;
padding-left: 0;

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
@import "variables.i386";
@import "variables.i386-dark";
@import "../../../../node_modules/bootstrap/scss/bootstrap";
.btn-outline-secondary {

File diff suppressed because it is too large Load diff

View file

@ -74,7 +74,7 @@ hr.my-3 {
--bs-success: #6610f2;
--bs-info: #007bff;
--bs-warning: #ffc107;
--bs-danger: #873208;
--bs-danger: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 241, 100, 30;
@ -85,28 +85,28 @@ hr.my-3 {
--bs-danger-rgb: 135, 50, 8;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #60280c;
--bs-secondary-text-emphasis: #00431c;
--bs-success-text-emphasis: #290661;
--bs-info-text-emphasis: #003166;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #361403;
--bs-primary-text-emphasis: rgb(96.4, 40, 12);
--bs-secondary-text-emphasis: rgb(0, 67.2, 28);
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8);
--bs-info-text-emphasis: rgb(0, 49.2, 102);
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8);
--bs-danger-text-emphasis: rgb(54.0376569038, 20.1740585774, 3.3623430962);
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #fce0d2;
--bs-secondary-bg-subtle: #cceeda;
--bs-success-bg-subtle: #e0cffc;
--bs-info-bg-subtle: #cce5ff;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #e7d6ce;
--bs-light-bg-subtle: #fcfcfd;
--bs-primary-bg-subtle: rgb(252.2, 224, 210);
--bs-secondary-bg-subtle: rgb(204, 237.6, 218);
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4);
--bs-info-bg-subtle: rgb(204, 228.6, 255);
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4);
--bs-danger-bg-subtle: rgb(231.0188284519, 214.0870292887, 205.6811715481);
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #f9c1a5;
--bs-secondary-border-subtle: #99dcb5;
--bs-success-border-subtle: #c29ffa;
--bs-info-border-subtle: #99caff;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #cfad9c;
--bs-primary-border-subtle: rgb(249.4, 193, 165);
--bs-secondary-border-subtle: rgb(153, 220.2, 181);
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8);
--bs-info-border-subtle: rgb(153, 202.2, 255);
--bs-warning-border-subtle: rgb(255, 230.2, 155.8);
--bs-danger-border-subtle: rgb(207.0376569038, 173.1740585774, 156.3623430962);
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
@ -137,7 +137,7 @@ hr.my-3 {
--bs-link-color: #f1641e;
--bs-link-color-rgb: 241, 100, 30;
--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-code-color: #d63384;
--bs-highlight-color: #495057;
@ -162,8 +162,8 @@ hr.my-3 {
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
--bs-form-valid-color: #007bff;
--bs-form-valid-border-color: #007bff;
--bs-form-invalid-color: #873208;
--bs-form-invalid-border-color: #873208;
--bs-form-invalid-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-form-invalid-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
}
[data-bs-theme=dark] {
@ -180,46 +180,46 @@ hr.my-3 {
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--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-primary-text-emphasis: #f7a278;
--bs-secondary-text-emphasis: #66cb90;
--bs-success-text-emphasis: #a370f7;
--bs-info-text-emphasis: #66b0ff;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #b7846b;
--bs-primary-text-emphasis: rgb(246.6, 162, 120);
--bs-secondary-text-emphasis: rgb(102, 202.8, 144);
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2);
--bs-info-text-emphasis: rgb(102, 175.8, 255);
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2);
--bs-danger-text-emphasis: rgb(183.0564853556, 132.2610878661, 107.0435146444);
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #301406;
--bs-secondary-bg-subtle: #00220e;
--bs-success-bg-subtle: #140330;
--bs-info-bg-subtle: #001933;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #1b0a02;
--bs-primary-bg-subtle: rgb(48.2, 20, 6);
--bs-secondary-bg-subtle: rgb(0, 33.6, 14);
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4);
--bs-info-bg-subtle: rgb(0, 24.6, 51);
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4);
--bs-danger-bg-subtle: rgb(27.0188284519, 10.0870292887, 1.6811715481);
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #2b2e31;
--bs-primary-border-subtle: #913c12;
--bs-secondary-border-subtle: #00652a;
--bs-success-border-subtle: #3d0a91;
--bs-info-border-subtle: #004a99;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #511e05;
--bs-primary-border-subtle: rgb(144.6, 60, 18);
--bs-secondary-border-subtle: rgb(0, 100.8, 42);
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2);
--bs-info-border-subtle: rgb(0, 73.8, 153);
--bs-warning-border-subtle: rgb(153, 115.8, 4.2);
--bs-danger-border-subtle: rgb(81.0564853556, 30.2610878661, 5.0435146444);
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #f7a278;
--bs-link-hover-color: #f9b593;
--bs-link-color: rgb(246.6, 162, 120);
--bs-link-hover-color: rgb(248.28, 180.6, 147);
--bs-link-color-rgb: 247, 162, 120;
--bs-link-hover-color-rgb: 249, 181, 147;
--bs-code-color: #e685b5;
--bs-link-hover-color-rgb: 248, 181, 147;
--bs-code-color: rgb(230.4, 132.6, 181.2);
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-highlight-bg: rgb(102, 77.2, 2.8);
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #66cb90;
--bs-form-valid-border-color: #66cb90;
--bs-form-invalid-color: #e891a6;
--bs-form-invalid-border-color: #e891a6;
--bs-form-valid-color: rgb(102, 202.8, 144);
--bs-form-valid-border-color: rgb(102, 202.8, 144);
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6);
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6);
}
*,
@ -1950,13 +1950,13 @@ progress {
.table-primary {
--bs-table-color: #222;
--bs-table-bg: #fce0d2;
--bs-table-border-color: #d0baaf;
--bs-table-striped-bg: #f1d7c9;
--bs-table-bg: rgb(252.2, 224, 210);
--bs-table-border-color: rgb(208.56, 186, 174.8);
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2);
--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-hover-bg: #ecd2c5;
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1964,13 +1964,13 @@ progress {
.table-secondary {
--bs-table-color: #222;
--bs-table-bg: #cceeda;
--bs-table-border-color: #aac5b5;
--bs-table-striped-bg: #c4e4d1;
--bs-table-bg: rgb(204, 237.6, 218);
--bs-table-border-color: rgb(170, 196.88, 181.2);
--bs-table-striped-bg: rgb(195.5, 227.42, 208.8);
--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-hover-bg: #bfdfcc;
--bs-table-hover-bg: rgb(191.25, 222.33, 204.2);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1978,13 +1978,13 @@ progress {
.table-success {
--bs-table-color: #222;
--bs-table-bg: #e0cffc;
--bs-table-border-color: #baacd0;
--bs-table-striped-bg: #d7c6f1;
--bs-table-bg: rgb(224.4, 207.2, 252.4);
--bs-table-border-color: rgb(186.32, 172.56, 208.72);
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48);
--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-hover-bg: #d2c2ec;
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1992,13 +1992,13 @@ progress {
.table-info {
--bs-table-color: #222;
--bs-table-bg: #cce5ff;
--bs-table-border-color: #aabed3;
--bs-table-striped-bg: #c4dbf4;
--bs-table-bg: rgb(204, 228.6, 255);
--bs-table-border-color: rgb(170, 189.68, 210.8);
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95);
--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-hover-bg: #bfd6ee;
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2006,13 +2006,13 @@ progress {
.table-warning {
--bs-table-color: #222;
--bs-table-bg: #fff3cd;
--bs-table-border-color: #d3c9ab;
--bs-table-striped-bg: #f4e9c4;
--bs-table-bg: rgb(255, 242.6, 205.4);
--bs-table-border-color: rgb(210.8, 200.88, 171.12);
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83);
--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-hover-bg: #eee3c0;
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2020,13 +2020,13 @@ progress {
.table-danger {
--bs-table-color: #222;
--bs-table-bg: #e7d6ce;
--bs-table-border-color: #c0b2ac;
--bs-table-striped-bg: #ddcdc5;
--bs-table-bg: rgb(231.0188284519, 214.0870292887, 205.6811715481);
--bs-table-border-color: rgb(191.6150627615, 178.069623431, 171.3449372385);
--bs-table-striped-bg: rgb(221.1678870293, 205.0826778243, 197.0971129707);
--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-hover-bg: #d8c9c1;
--bs-table-hover-bg: rgb(216.242416318, 200.5805020921, 192.805083682);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2035,12 +2035,12 @@ progress {
.table-light {
--bs-table-color: #222;
--bs-table-bg: #f8f9fa;
--bs-table-border-color: #cdcecf;
--bs-table-striped-bg: #edeeef;
--bs-table-border-color: rgb(205.2, 206, 206.8);
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2);
--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-hover-bg: #e8e9ea;
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2049,12 +2049,12 @@ progress {
.table-dark {
--bs-table-color: #fff;
--bs-table-bg: #212529;
--bs-table-border-color: #4d5154;
--bs-table-striped-bg: #2c3034;
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
--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-hover-bg: #323539;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2154,7 +2154,7 @@ progress {
.form-control:focus {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
}
@ -2299,7 +2299,7 @@ textarea.form-control-lg {
}
}
.form-select:focus {
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
}
@ -2383,7 +2383,7 @@ textarea.form-control-lg {
filter: brightness(90%);
}
.form-check-input:focus {
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2500,7 +2500,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #fbd1bc;
background-color: rgb(250.8, 208.5, 187.5);
}
.form-range::-webkit-slider-runnable-track {
width: 100%;
@ -2526,7 +2526,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #fbd1bc;
background-color: rgb(250.8, 208.5, 187.5);
}
.form-range::-moz-range-track {
width: 100%;
@ -2849,7 +2849,7 @@ textarea.form-control-lg {
.was-validated .form-control:invalid, .form-control.is-invalid {
border-color: var(--bs-form-invalid-border-color);
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-position: right calc(0.375em + 0.1875rem) center;
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);
}
.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;
background-position: right 0.75rem center, center right 2.25rem;
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2990,12 +2990,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f1641e;
--bs-btn-border-color: #f1641e;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #cd551a;
--bs-btn-hover-border-color: #c15018;
--bs-btn-hover-bg: rgb(204.85, 85, 25.5);
--bs-btn-hover-border-color: rgb(192.8, 80, 24);
--bs-btn-focus-shadow-rgb: 243, 123, 64;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #c15018;
--bs-btn-active-border-color: #b54b17;
--bs-btn-active-bg: rgb(192.8, 80, 24);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #f1641e;
@ -3007,12 +3007,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00a846;
--bs-btn-border-color: #00a846;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #008f3c;
--bs-btn-hover-border-color: #008638;
--bs-btn-hover-bg: rgb(0, 142.8, 59.5);
--bs-btn-hover-border-color: rgb(0, 134.4, 56);
--bs-btn-focus-shadow-rgb: 38, 181, 98;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #008638;
--bs-btn-active-border-color: #007e35;
--bs-btn-active-bg: rgb(0, 134.4, 56);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #00a846;
@ -3024,12 +3024,12 @@ textarea.form-control-lg {
--bs-btn-bg: #6610f2;
--bs-btn-border-color: #6610f2;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #570ece;
--bs-btn-hover-border-color: #520dc2;
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7);
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6);
--bs-btn-focus-shadow-rgb: 125, 52, 244;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #520dc2;
--bs-btn-active-border-color: #4d0cb6;
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #6610f2;
@ -3041,12 +3041,12 @@ textarea.form-control-lg {
--bs-btn-bg: #007bff;
--bs-btn-border-color: #007bff;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #0069d9;
--bs-btn-hover-border-color: #0062cc;
--bs-btn-hover-bg: rgb(0, 104.55, 216.75);
--bs-btn-hover-border-color: rgb(0, 98.4, 204);
--bs-btn-focus-shadow-rgb: 38, 143, 255;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #0062cc;
--bs-btn-active-border-color: #005cbf;
--bs-btn-active-bg: rgb(0, 98.4, 204);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #007bff;
@ -3058,12 +3058,12 @@ textarea.form-control-lg {
--bs-btn-bg: #ffc107;
--bs-btn-border-color: #ffc107;
--bs-btn-hover-color: #222;
--bs-btn-hover-bg: #ffca2c;
--bs-btn-hover-border-color: #ffc720;
--bs-btn-hover-bg: rgb(255, 202.3, 44.2);
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8);
--bs-btn-focus-shadow-rgb: 222, 169, 11;
--bs-btn-active-color: #222;
--bs-btn-active-bg: #ffcd39;
--bs-btn-active-border-color: #ffc720;
--bs-btn-active-bg: rgb(255, 205.4, 56.6);
--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-disabled-color: #222;
--bs-btn-disabled-bg: #ffc107;
@ -3072,19 +3072,19 @@ textarea.form-control-lg {
.btn-danger {
--bs-btn-color: #fff;
--bs-btn-bg: #873208;
--bs-btn-border-color: #873208;
--bs-btn-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #732b07;
--bs-btn-hover-border-color: #6c2806;
--bs-btn-hover-bg: rgb(114.8300209205, 42.869874477, 7.1449790795);
--bs-btn-hover-border-color: rgb(108.0753138075, 40.3481171548, 6.7246861925);
--bs-btn-focus-shadow-rgb: 153, 81, 45;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #6c2806;
--bs-btn-active-border-color: #652606;
--bs-btn-active-bg: rgb(108.0753138075, 40.3481171548, 6.7246861925);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #873208;
--bs-btn-disabled-border-color: #873208;
--bs-btn-disabled-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
}
.btn-light {
@ -3092,12 +3092,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f8f9fa;
--bs-btn-border-color: #f8f9fa;
--bs-btn-hover-color: #222;
--bs-btn-hover-bg: #d3d4d5;
--bs-btn-hover-border-color: #c6c7c8;
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5);
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200);
--bs-btn-focus-shadow-rgb: 216, 217, 218;
--bs-btn-active-color: #222;
--bs-btn-active-bg: #c6c7c8;
--bs-btn-active-border-color: #babbbc;
--bs-btn-active-bg: rgb(198.4, 199.2, 200);
--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-disabled-color: #222;
--bs-btn-disabled-bg: #f8f9fa;
@ -3109,12 +3109,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529;
--bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: #373b3e;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
--bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: #373b3e;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #212529;
@ -3207,19 +3207,19 @@ textarea.form-control-lg {
}
.btn-outline-danger {
--bs-btn-color: #873208;
--bs-btn-border-color: #873208;
--bs-btn-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #873208;
--bs-btn-hover-border-color: #873208;
--bs-btn-hover-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-hover-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-focus-shadow-rgb: 135, 50, 8;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #873208;
--bs-btn-active-border-color: #873208;
--bs-btn-active-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--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-disabled-color: #873208;
--bs-btn-disabled-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--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;
}
@ -4505,7 +4505,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%2360280c' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4623,8 +4623,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {
@ -6846,8 +6846,8 @@ textarea.form-control-lg {
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
}
.link-danger:hover, .link-danger:focus {
color: RGBA(108, 40, 6, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(108, 40, 6, var(--bs-link-underline-opacity, 1)) !important;
color: RGBA(108, 40, 7, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(108, 40, 7, var(--bs-link-underline-opacity, 1)) !important;
}
.link-light {

View file

@ -34,7 +34,7 @@
--bs-success: #6610f2;
--bs-info: #007bff;
--bs-warning: #ffc107;
--bs-danger: #8c3409;
--bs-danger: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 241, 100, 30;
@ -45,28 +45,28 @@
--bs-danger-rgb: 140, 52, 9;
--bs-light-rgb: 248, 249, 250;
--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-success-text-emphasis: #290661;
--bs-info-text-emphasis: #003166;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #381504;
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8);
--bs-info-text-emphasis: rgb(0, 49.2, 102);
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8);
--bs-danger-text-emphasis: rgb(55.9581589958, 20.8910460251, 3.4818410042);
--bs-light-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-success-bg-subtle: #e0cffc;
--bs-info-bg-subtle: #cce5ff;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #e8d6ce;
--bs-light-bg-subtle: #fcfcfd;
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4);
--bs-info-bg-subtle: rgb(204, 228.6, 255);
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4);
--bs-danger-bg-subtle: rgb(231.9790794979, 214.4455230126, 205.7409205021);
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
--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-success-border-subtle: #c29ffa;
--bs-info-border-subtle: #99caff;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #d1ae9d;
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8);
--bs-info-border-subtle: rgb(153, 202.2, 255);
--bs-warning-border-subtle: rgb(255, 230.2, 155.8);
--bs-danger-border-subtle: rgb(208.9581589958, 173.8910460251, 156.4818410042);
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #f1641e;
--bs-link-color-rgb: 241, 100, 30;
--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-code-color: #d63384;
--bs-highlight-color: #495057;
@ -122,8 +122,8 @@
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
--bs-form-valid-color: #007bff;
--bs-form-valid-border-color: #007bff;
--bs-form-invalid-color: #8c3409;
--bs-form-invalid-border-color: #8c3409;
--bs-form-invalid-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-form-invalid-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
}
[data-bs-theme=dark] {
@ -140,46 +140,46 @@
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--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-primary-text-emphasis: #f7a278;
--bs-primary-text-emphasis: rgb(246.6, 162, 120);
--bs-secondary-text-emphasis: #de6666;
--bs-success-text-emphasis: #a370f7;
--bs-info-text-emphasis: #66b0ff;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ba856b;
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2);
--bs-info-text-emphasis: rgb(102, 175.8, 255);
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2);
--bs-danger-text-emphasis: rgb(185.9372384937, 133.3365690377, 107.2227615063);
--bs-light-text-emphasis: #f8f9fa;
--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-success-bg-subtle: #140330;
--bs-info-bg-subtle: #001933;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #1c0a02;
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4);
--bs-info-bg-subtle: rgb(0, 24.6, 51);
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4);
--bs-danger-bg-subtle: rgb(27.9790794979, 10.4455230126, 1.7409205021);
--bs-light-bg-subtle: #343a40;
--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-success-border-subtle: #3d0a91;
--bs-info-border-subtle: #004a99;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #541f05;
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2);
--bs-info-border-subtle: rgb(0, 73.8, 153);
--bs-warning-border-subtle: rgb(153, 115.8, 4.2);
--bs-danger-border-subtle: rgb(83.9372384937, 31.3365690377, 5.2227615063);
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #f7a278;
--bs-link-hover-color: #f9b593;
--bs-link-color: rgb(246.6, 162, 120);
--bs-link-hover-color: rgb(248.28, 180.6, 147);
--bs-link-color-rgb: 247, 162, 120;
--bs-link-hover-color-rgb: 249, 181, 147;
--bs-code-color: #e685b5;
--bs-link-hover-color-rgb: 248, 181, 147;
--bs-code-color: rgb(230.4, 132.6, 181.2);
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-highlight-bg: rgb(102, 77.2, 2.8);
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #66cb90;
--bs-form-valid-border-color: #66cb90;
--bs-form-invalid-color: #e891a6;
--bs-form-invalid-border-color: #e891a6;
--bs-form-valid-color: rgb(102, 202.8, 144);
--bs-form-valid-border-color: rgb(102, 202.8, 144);
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6);
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6);
}
*,
@ -1934,13 +1934,13 @@ progress {
.table-primary {
--bs-table-color: #222;
--bs-table-bg: #fce0d2;
--bs-table-border-color: #d0baaf;
--bs-table-striped-bg: #f1d7c9;
--bs-table-bg: rgb(252.2, 224, 210);
--bs-table-border-color: rgb(208.56, 186, 174.8);
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2);
--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-hover-bg: #ecd2c5;
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1950,11 +1950,11 @@ progress {
--bs-table-color: #222;
--bs-table-bg: #f4cccc;
--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-active-bg: #dfbbbb;
--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;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1962,13 +1962,13 @@ progress {
.table-success {
--bs-table-color: #222;
--bs-table-bg: #e0cffc;
--bs-table-border-color: #baacd0;
--bs-table-striped-bg: #d7c6f1;
--bs-table-bg: rgb(224.4, 207.2, 252.4);
--bs-table-border-color: rgb(186.32, 172.56, 208.72);
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48);
--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-hover-bg: #d2c2ec;
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1976,13 +1976,13 @@ progress {
.table-info {
--bs-table-color: #222;
--bs-table-bg: #cce5ff;
--bs-table-border-color: #aabed3;
--bs-table-striped-bg: #c4dbf4;
--bs-table-bg: rgb(204, 228.6, 255);
--bs-table-border-color: rgb(170, 189.68, 210.8);
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95);
--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-hover-bg: #bfd6ee;
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1990,13 +1990,13 @@ progress {
.table-warning {
--bs-table-color: #222;
--bs-table-bg: #fff3cd;
--bs-table-border-color: #d3c9ab;
--bs-table-striped-bg: #f4e9c4;
--bs-table-bg: rgb(255, 242.6, 205.4);
--bs-table-border-color: rgb(210.8, 200.88, 171.12);
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83);
--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-hover-bg: #eee3c0;
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2004,13 +2004,13 @@ progress {
.table-danger {
--bs-table-color: #222;
--bs-table-bg: #e8d6ce;
--bs-table-border-color: #c0b2ac;
--bs-table-striped-bg: #decdc5;
--bs-table-bg: rgb(231.9790794979, 214.4455230126, 205.7409205021);
--bs-table-border-color: rgb(192.3832635983, 178.35641841, 171.3927364017);
--bs-table-striped-bg: rgb(222.080125523, 205.4232468619, 197.153874477);
--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-hover-bg: #d9c9c1;
--bs-table-hover-bg: rgb(217.1306485356, 200.9121087866, 192.8603514644);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2019,12 +2019,12 @@ progress {
.table-light {
--bs-table-color: #222;
--bs-table-bg: #f8f9fa;
--bs-table-border-color: #cdcecf;
--bs-table-striped-bg: #edeeef;
--bs-table-border-color: rgb(205.2, 206, 206.8);
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2);
--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-hover-bg: #e8e9ea;
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2033,12 +2033,12 @@ progress {
.table-dark {
--bs-table-color: #fff;
--bs-table-bg: #212529;
--bs-table-border-color: #4d5154;
--bs-table-striped-bg: #2c3034;
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
--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-hover-bg: #323539;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2138,7 +2138,7 @@ progress {
.form-control:focus {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
}
@ -2283,7 +2283,7 @@ textarea.form-control-lg {
}
}
.form-select:focus {
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
}
@ -2367,7 +2367,7 @@ textarea.form-control-lg {
filter: brightness(90%);
}
.form-check-input:focus {
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2484,7 +2484,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #fbd1bc;
background-color: rgb(250.8, 208.5, 187.5);
}
.form-range::-webkit-slider-runnable-track {
width: 100%;
@ -2510,7 +2510,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #fbd1bc;
background-color: rgb(250.8, 208.5, 187.5);
}
.form-range::-moz-range-track {
width: 100%;
@ -2833,7 +2833,7 @@ textarea.form-control-lg {
.was-validated .form-control:invalid, .form-control.is-invalid {
border-color: var(--bs-form-invalid-border-color);
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-position: right calc(0.375em + 0.1875rem) center;
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);
}
.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;
background-position: right 0.75rem center, center right 2.25rem;
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2974,12 +2974,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f1641e;
--bs-btn-border-color: #f1641e;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #cd551a;
--bs-btn-hover-border-color: #c15018;
--bs-btn-hover-bg: rgb(204.85, 85, 25.5);
--bs-btn-hover-border-color: rgb(192.8, 80, 24);
--bs-btn-focus-shadow-rgb: 243, 123, 64;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #c15018;
--bs-btn-active-border-color: #b54b17;
--bs-btn-active-bg: rgb(192.8, 80, 24);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #f1641e;
@ -3008,12 +3008,12 @@ textarea.form-control-lg {
--bs-btn-bg: #6610f2;
--bs-btn-border-color: #6610f2;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #570ece;
--bs-btn-hover-border-color: #520dc2;
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7);
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6);
--bs-btn-focus-shadow-rgb: 125, 52, 244;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #520dc2;
--bs-btn-active-border-color: #4d0cb6;
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #6610f2;
@ -3025,12 +3025,12 @@ textarea.form-control-lg {
--bs-btn-bg: #007bff;
--bs-btn-border-color: #007bff;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #0069d9;
--bs-btn-hover-border-color: #0062cc;
--bs-btn-hover-bg: rgb(0, 104.55, 216.75);
--bs-btn-hover-border-color: rgb(0, 98.4, 204);
--bs-btn-focus-shadow-rgb: 38, 143, 255;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #0062cc;
--bs-btn-active-border-color: #005cbf;
--bs-btn-active-bg: rgb(0, 98.4, 204);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #007bff;
@ -3042,12 +3042,12 @@ textarea.form-control-lg {
--bs-btn-bg: #ffc107;
--bs-btn-border-color: #ffc107;
--bs-btn-hover-color: #222;
--bs-btn-hover-bg: #ffca2c;
--bs-btn-hover-border-color: #ffc720;
--bs-btn-hover-bg: rgb(255, 202.3, 44.2);
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8);
--bs-btn-focus-shadow-rgb: 222, 169, 11;
--bs-btn-active-color: #222;
--bs-btn-active-bg: #ffcd39;
--bs-btn-active-border-color: #ffc720;
--bs-btn-active-bg: rgb(255, 205.4, 56.6);
--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-disabled-color: #222;
--bs-btn-disabled-bg: #ffc107;
@ -3056,19 +3056,19 @@ textarea.form-control-lg {
.btn-danger {
--bs-btn-color: #fff;
--bs-btn-bg: #8c3409;
--bs-btn-border-color: #8c3409;
--bs-btn-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-btn-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #772c08;
--bs-btn-hover-border-color: #702a07;
--bs-btn-focus-shadow-rgb: 157, 82, 46;
--bs-btn-hover-bg: rgb(118.9110878661, 44.3934728033, 7.3989121339);
--bs-btn-hover-border-color: rgb(111.9163179916, 41.7820920502, 6.9636820084);
--bs-btn-focus-shadow-rgb: 157, 83, 46;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #702a07;
--bs-btn-active-border-color: #692707;
--bs-btn-active-bg: rgb(111.9163179916, 41.7820920502, 6.9636820084);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #8c3409;
--bs-btn-disabled-border-color: #8c3409;
--bs-btn-disabled-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-btn-disabled-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
}
.btn-light {
@ -3076,12 +3076,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f8f9fa;
--bs-btn-border-color: #f8f9fa;
--bs-btn-hover-color: #222;
--bs-btn-hover-bg: #d3d4d5;
--bs-btn-hover-border-color: #c6c7c8;
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5);
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200);
--bs-btn-focus-shadow-rgb: 216, 217, 218;
--bs-btn-active-color: #222;
--bs-btn-active-bg: #c6c7c8;
--bs-btn-active-border-color: #babbbc;
--bs-btn-active-bg: rgb(198.4, 199.2, 200);
--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-disabled-color: #222;
--bs-btn-disabled-bg: #f8f9fa;
@ -3093,12 +3093,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529;
--bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: #373b3e;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
--bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: #373b3e;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #212529;
@ -3191,19 +3191,19 @@ textarea.form-control-lg {
}
.btn-outline-danger {
--bs-btn-color: #8c3409;
--bs-btn-border-color: #8c3409;
--bs-btn-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-btn-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #8c3409;
--bs-btn-hover-border-color: #8c3409;
--bs-btn-hover-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-btn-hover-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--bs-btn-focus-shadow-rgb: 140, 52, 9;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #8c3409;
--bs-btn-active-border-color: #8c3409;
--bs-btn-active-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--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-disabled-color: #8c3409;
--bs-btn-disabled-color: rgb(139.8953974895, 52.2276150628, 8.7046025105);
--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;
}
@ -4493,7 +4493,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%2360280c' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4611,8 +4611,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {

View file

@ -34,7 +34,7 @@
--bs-success: #6610f2;
--bs-info: #007bff;
--bs-warning: #ffc107;
--bs-danger: #873208;
--bs-danger: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 241, 100, 30;
@ -45,28 +45,28 @@
--bs-danger-rgb: 135, 50, 8;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #60280c;
--bs-secondary-text-emphasis: #00431c;
--bs-success-text-emphasis: #290661;
--bs-info-text-emphasis: #003166;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #361403;
--bs-primary-text-emphasis: rgb(96.4, 40, 12);
--bs-secondary-text-emphasis: rgb(0, 67.2, 28);
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8);
--bs-info-text-emphasis: rgb(0, 49.2, 102);
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8);
--bs-danger-text-emphasis: rgb(54.0376569038, 20.1740585774, 3.3623430962);
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #fce0d2;
--bs-secondary-bg-subtle: #cceeda;
--bs-success-bg-subtle: #e0cffc;
--bs-info-bg-subtle: #cce5ff;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #e7d6ce;
--bs-light-bg-subtle: #fcfcfd;
--bs-primary-bg-subtle: rgb(252.2, 224, 210);
--bs-secondary-bg-subtle: rgb(204, 237.6, 218);
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4);
--bs-info-bg-subtle: rgb(204, 228.6, 255);
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4);
--bs-danger-bg-subtle: rgb(231.0188284519, 214.0870292887, 205.6811715481);
--bs-light-bg-subtle: rgb(251.5, 252, 252.5);
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #f9c1a5;
--bs-secondary-border-subtle: #99dcb5;
--bs-success-border-subtle: #c29ffa;
--bs-info-border-subtle: #99caff;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #cfad9c;
--bs-primary-border-subtle: rgb(249.4, 193, 165);
--bs-secondary-border-subtle: rgb(153, 220.2, 181);
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8);
--bs-info-border-subtle: rgb(153, 202.2, 255);
--bs-warning-border-subtle: rgb(255, 230.2, 155.8);
--bs-danger-border-subtle: rgb(207.0376569038, 173.1740585774, 156.3623430962);
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #f1641e;
--bs-link-color-rgb: 241, 100, 30;
--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-code-color: #d63384;
--bs-highlight-color: #495057;
@ -122,8 +122,8 @@
--bs-focus-ring-color: rgba(241, 100, 30, 0.25);
--bs-form-valid-color: #007bff;
--bs-form-valid-border-color: #007bff;
--bs-form-invalid-color: #873208;
--bs-form-invalid-border-color: #873208;
--bs-form-invalid-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-form-invalid-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
}
[data-bs-theme=dark] {
@ -140,46 +140,46 @@
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--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-primary-text-emphasis: #f7a278;
--bs-secondary-text-emphasis: #66cb90;
--bs-success-text-emphasis: #a370f7;
--bs-info-text-emphasis: #66b0ff;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #b7846b;
--bs-primary-text-emphasis: rgb(246.6, 162, 120);
--bs-secondary-text-emphasis: rgb(102, 202.8, 144);
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2);
--bs-info-text-emphasis: rgb(102, 175.8, 255);
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2);
--bs-danger-text-emphasis: rgb(183.0564853556, 132.2610878661, 107.0435146444);
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #301406;
--bs-secondary-bg-subtle: #00220e;
--bs-success-bg-subtle: #140330;
--bs-info-bg-subtle: #001933;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #1b0a02;
--bs-primary-bg-subtle: rgb(48.2, 20, 6);
--bs-secondary-bg-subtle: rgb(0, 33.6, 14);
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4);
--bs-info-bg-subtle: rgb(0, 24.6, 51);
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4);
--bs-danger-bg-subtle: rgb(27.0188284519, 10.0870292887, 1.6811715481);
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #2b2e31;
--bs-primary-border-subtle: #913c12;
--bs-secondary-border-subtle: #00652a;
--bs-success-border-subtle: #3d0a91;
--bs-info-border-subtle: #004a99;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #511e05;
--bs-primary-border-subtle: rgb(144.6, 60, 18);
--bs-secondary-border-subtle: rgb(0, 100.8, 42);
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2);
--bs-info-border-subtle: rgb(0, 73.8, 153);
--bs-warning-border-subtle: rgb(153, 115.8, 4.2);
--bs-danger-border-subtle: rgb(81.0564853556, 30.2610878661, 5.0435146444);
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #f7a278;
--bs-link-hover-color: #f9b593;
--bs-link-color: rgb(246.6, 162, 120);
--bs-link-hover-color: rgb(248.28, 180.6, 147);
--bs-link-color-rgb: 247, 162, 120;
--bs-link-hover-color-rgb: 249, 181, 147;
--bs-code-color: #e685b5;
--bs-link-hover-color-rgb: 248, 181, 147;
--bs-code-color: rgb(230.4, 132.6, 181.2);
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-highlight-bg: rgb(102, 77.2, 2.8);
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #66cb90;
--bs-form-valid-border-color: #66cb90;
--bs-form-invalid-color: #e891a6;
--bs-form-invalid-border-color: #e891a6;
--bs-form-valid-color: rgb(102, 202.8, 144);
--bs-form-valid-border-color: rgb(102, 202.8, 144);
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6);
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6);
}
*,
@ -1934,13 +1934,13 @@ progress {
.table-primary {
--bs-table-color: #222;
--bs-table-bg: #fce0d2;
--bs-table-border-color: #d0baaf;
--bs-table-striped-bg: #f1d7c9;
--bs-table-bg: rgb(252.2, 224, 210);
--bs-table-border-color: rgb(208.56, 186, 174.8);
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2);
--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-hover-bg: #ecd2c5;
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1948,13 +1948,13 @@ progress {
.table-secondary {
--bs-table-color: #222;
--bs-table-bg: #cceeda;
--bs-table-border-color: #aac5b5;
--bs-table-striped-bg: #c4e4d1;
--bs-table-bg: rgb(204, 237.6, 218);
--bs-table-border-color: rgb(170, 196.88, 181.2);
--bs-table-striped-bg: rgb(195.5, 227.42, 208.8);
--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-hover-bg: #bfdfcc;
--bs-table-hover-bg: rgb(191.25, 222.33, 204.2);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1962,13 +1962,13 @@ progress {
.table-success {
--bs-table-color: #222;
--bs-table-bg: #e0cffc;
--bs-table-border-color: #baacd0;
--bs-table-striped-bg: #d7c6f1;
--bs-table-bg: rgb(224.4, 207.2, 252.4);
--bs-table-border-color: rgb(186.32, 172.56, 208.72);
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48);
--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-hover-bg: #d2c2ec;
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1976,13 +1976,13 @@ progress {
.table-info {
--bs-table-color: #222;
--bs-table-bg: #cce5ff;
--bs-table-border-color: #aabed3;
--bs-table-striped-bg: #c4dbf4;
--bs-table-bg: rgb(204, 228.6, 255);
--bs-table-border-color: rgb(170, 189.68, 210.8);
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95);
--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-hover-bg: #bfd6ee;
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1990,13 +1990,13 @@ progress {
.table-warning {
--bs-table-color: #222;
--bs-table-bg: #fff3cd;
--bs-table-border-color: #d3c9ab;
--bs-table-striped-bg: #f4e9c4;
--bs-table-bg: rgb(255, 242.6, 205.4);
--bs-table-border-color: rgb(210.8, 200.88, 171.12);
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83);
--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-hover-bg: #eee3c0;
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2004,13 +2004,13 @@ progress {
.table-danger {
--bs-table-color: #222;
--bs-table-bg: #e7d6ce;
--bs-table-border-color: #c0b2ac;
--bs-table-striped-bg: #ddcdc5;
--bs-table-bg: rgb(231.0188284519, 214.0870292887, 205.6811715481);
--bs-table-border-color: rgb(191.6150627615, 178.069623431, 171.3449372385);
--bs-table-striped-bg: rgb(221.1678870293, 205.0826778243, 197.0971129707);
--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-hover-bg: #d8c9c1;
--bs-table-hover-bg: rgb(216.242416318, 200.5805020921, 192.805083682);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2019,12 +2019,12 @@ progress {
.table-light {
--bs-table-color: #222;
--bs-table-bg: #f8f9fa;
--bs-table-border-color: #cdcecf;
--bs-table-striped-bg: #edeeef;
--bs-table-border-color: rgb(205.2, 206, 206.8);
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2);
--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-hover-bg: #e8e9ea;
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8);
--bs-table-hover-color: #222;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2033,12 +2033,12 @@ progress {
.table-dark {
--bs-table-color: #fff;
--bs-table-bg: #212529;
--bs-table-border-color: #4d5154;
--bs-table-striped-bg: #2c3034;
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
--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-hover-bg: #323539;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2138,7 +2138,7 @@ progress {
.form-control:focus {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
}
@ -2283,7 +2283,7 @@ textarea.form-control-lg {
}
}
.form-select:focus {
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
}
@ -2367,7 +2367,7 @@ textarea.form-control-lg {
filter: brightness(90%);
}
.form-check-input:focus {
border-color: #f8b28f;
border-color: rgb(248, 177.5, 142.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2484,7 +2484,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #fbd1bc;
background-color: rgb(250.8, 208.5, 187.5);
}
.form-range::-webkit-slider-runnable-track {
width: 100%;
@ -2510,7 +2510,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #fbd1bc;
background-color: rgb(250.8, 208.5, 187.5);
}
.form-range::-moz-range-track {
width: 100%;
@ -2833,7 +2833,7 @@ textarea.form-control-lg {
.was-validated .form-control:invalid, .form-control.is-invalid {
border-color: var(--bs-form-invalid-border-color);
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-position: right calc(0.375em + 0.1875rem) center;
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);
}
.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;
background-position: right 0.75rem center, center right 2.25rem;
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2974,12 +2974,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f1641e;
--bs-btn-border-color: #f1641e;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #cd551a;
--bs-btn-hover-border-color: #c15018;
--bs-btn-hover-bg: rgb(204.85, 85, 25.5);
--bs-btn-hover-border-color: rgb(192.8, 80, 24);
--bs-btn-focus-shadow-rgb: 243, 123, 64;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #c15018;
--bs-btn-active-border-color: #b54b17;
--bs-btn-active-bg: rgb(192.8, 80, 24);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #f1641e;
@ -2991,12 +2991,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00a846;
--bs-btn-border-color: #00a846;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #008f3c;
--bs-btn-hover-border-color: #008638;
--bs-btn-hover-bg: rgb(0, 142.8, 59.5);
--bs-btn-hover-border-color: rgb(0, 134.4, 56);
--bs-btn-focus-shadow-rgb: 38, 181, 98;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #008638;
--bs-btn-active-border-color: #007e35;
--bs-btn-active-bg: rgb(0, 134.4, 56);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #00a846;
@ -3008,12 +3008,12 @@ textarea.form-control-lg {
--bs-btn-bg: #6610f2;
--bs-btn-border-color: #6610f2;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #570ece;
--bs-btn-hover-border-color: #520dc2;
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7);
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6);
--bs-btn-focus-shadow-rgb: 125, 52, 244;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #520dc2;
--bs-btn-active-border-color: #4d0cb6;
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #6610f2;
@ -3025,12 +3025,12 @@ textarea.form-control-lg {
--bs-btn-bg: #007bff;
--bs-btn-border-color: #007bff;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #0069d9;
--bs-btn-hover-border-color: #0062cc;
--bs-btn-hover-bg: rgb(0, 104.55, 216.75);
--bs-btn-hover-border-color: rgb(0, 98.4, 204);
--bs-btn-focus-shadow-rgb: 38, 143, 255;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #0062cc;
--bs-btn-active-border-color: #005cbf;
--bs-btn-active-bg: rgb(0, 98.4, 204);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #007bff;
@ -3042,12 +3042,12 @@ textarea.form-control-lg {
--bs-btn-bg: #ffc107;
--bs-btn-border-color: #ffc107;
--bs-btn-hover-color: #222;
--bs-btn-hover-bg: #ffca2c;
--bs-btn-hover-border-color: #ffc720;
--bs-btn-hover-bg: rgb(255, 202.3, 44.2);
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8);
--bs-btn-focus-shadow-rgb: 222, 169, 11;
--bs-btn-active-color: #222;
--bs-btn-active-bg: #ffcd39;
--bs-btn-active-border-color: #ffc720;
--bs-btn-active-bg: rgb(255, 205.4, 56.6);
--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-disabled-color: #222;
--bs-btn-disabled-bg: #ffc107;
@ -3056,19 +3056,19 @@ textarea.form-control-lg {
.btn-danger {
--bs-btn-color: #fff;
--bs-btn-bg: #873208;
--bs-btn-border-color: #873208;
--bs-btn-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #732b07;
--bs-btn-hover-border-color: #6c2806;
--bs-btn-hover-bg: rgb(114.8300209205, 42.869874477, 7.1449790795);
--bs-btn-hover-border-color: rgb(108.0753138075, 40.3481171548, 6.7246861925);
--bs-btn-focus-shadow-rgb: 153, 81, 45;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #6c2806;
--bs-btn-active-border-color: #652606;
--bs-btn-active-bg: rgb(108.0753138075, 40.3481171548, 6.7246861925);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #873208;
--bs-btn-disabled-border-color: #873208;
--bs-btn-disabled-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
}
.btn-light {
@ -3076,12 +3076,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f8f9fa;
--bs-btn-border-color: #f8f9fa;
--bs-btn-hover-color: #222;
--bs-btn-hover-bg: #d3d4d5;
--bs-btn-hover-border-color: #c6c7c8;
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5);
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200);
--bs-btn-focus-shadow-rgb: 216, 217, 218;
--bs-btn-active-color: #222;
--bs-btn-active-bg: #c6c7c8;
--bs-btn-active-border-color: #babbbc;
--bs-btn-active-bg: rgb(198.4, 199.2, 200);
--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-disabled-color: #222;
--bs-btn-disabled-bg: #f8f9fa;
@ -3093,12 +3093,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529;
--bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: #373b3e;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
--bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: #373b3e;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #212529;
@ -3191,19 +3191,19 @@ textarea.form-control-lg {
}
.btn-outline-danger {
--bs-btn-color: #873208;
--bs-btn-border-color: #873208;
--bs-btn-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #873208;
--bs-btn-hover-border-color: #873208;
--bs-btn-hover-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-hover-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--bs-btn-focus-shadow-rgb: 135, 50, 8;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #873208;
--bs-btn-active-border-color: #873208;
--bs-btn-active-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--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-disabled-color: #873208;
--bs-btn-disabled-color: rgb(135.0941422594, 50.4351464435, 8.4058577406);
--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;
}
@ -4493,7 +4493,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%2360280c' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4611,8 +4611,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {
@ -6834,8 +6834,8 @@ textarea.form-control-lg {
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
}
.link-danger:hover, .link-danger:focus {
color: RGBA(108, 40, 6, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(108, 40, 6, var(--bs-link-underline-opacity, 1)) !important;
color: RGBA(108, 40, 7, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(108, 40, 7, var(--bs-link-underline-opacity, 1)) !important;
}
.link-light {

View file

@ -45,27 +45,27 @@
--bs-danger-rgb: 255, 95, 110;
--bs-light-rgb: 68, 68, 68;
--bs-dark-rgb: 235, 235, 235;
--bs-primary-text-emphasis: #661a4a;
--bs-secondary-text-emphasis: #005266;
--bs-success-text-emphasis: #026640;
--bs-info-text-emphasis: #005266;
--bs-warning-text-emphasis: #66643c;
--bs-primary-text-emphasis: rgb(102, 25.6, 74.4);
--bs-secondary-text-emphasis: rgb(0.4, 82, 101.6);
--bs-success-text-emphasis: rgb(2, 102, 64.4);
--bs-info-text-emphasis: rgb(0.4, 82, 101.6);
--bs-warning-text-emphasis: rgb(102, 100.4, 60);
--bs-danger-text-emphasis: #66262c;
--bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: #ffd9f1;
--bs-secondary-bg-subtle: #ccf5ff;
--bs-success-bg-subtle: #cdffec;
--bs-info-bg-subtle: #ccf5ff;
--bs-warning-bg-subtle: #fffeea;
--bs-primary-bg-subtle: rgb(255, 216.8, 241.2);
--bs-secondary-bg-subtle: rgb(204.2, 245, 254.8);
--bs-success-bg-subtle: rgb(205, 255, 236.2);
--bs-info-bg-subtle: rgb(204.2, 245, 254.8);
--bs-warning-bg-subtle: rgb(255, 254.2, 234);
--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-primary-border-subtle: #ffb3e3;
--bs-secondary-border-subtle: #99ebff;
--bs-success-border-subtle: #9bffd9;
--bs-info-border-subtle: #99ebff;
--bs-warning-border-subtle: #fffdd5;
--bs-primary-border-subtle: rgb(255, 178.6, 227.4);
--bs-secondary-border-subtle: rgb(153.4, 235, 254.6);
--bs-success-border-subtle: rgb(155, 255, 217.4);
--bs-info-border-subtle: rgb(153.4, 235, 254.6);
--bs-warning-border-subtle: rgb(255, 253.4, 213);
--bs-danger-border-subtle: #ffbfc5;
--bs-light-border-subtle: #ebebeb;
--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-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-code-color: rgb(255, 64, 186);
--bs-highlight-color: #ebebeb;
@ -142,42 +142,42 @@
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: #ff8cd6;
--bs-secondary-text-emphasis: #67e1fe;
--bs-success-text-emphasis: #69ffc7;
--bs-info-text-emphasis: #67e1fe;
--bs-warning-text-emphasis: #fffdc0;
--bs-primary-text-emphasis: rgb(255, 140.4, 213.6);
--bs-secondary-text-emphasis: rgb(102.6, 225, 254.4);
--bs-success-text-emphasis: rgb(105, 255, 198.6);
--bs-info-text-emphasis: rgb(102.6, 225, 254.4);
--bs-warning-text-emphasis: rgb(255, 252.6, 192);
--bs-danger-text-emphasis: #ff9fa8;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #330d25;
--bs-secondary-bg-subtle: #002933;
--bs-success-bg-subtle: #013320;
--bs-info-bg-subtle: #002933;
--bs-warning-bg-subtle: #33321e;
--bs-primary-bg-subtle: rgb(51, 12.8, 37.2);
--bs-secondary-bg-subtle: rgb(0.2, 41, 50.8);
--bs-success-bg-subtle: rgb(1, 51, 32.2);
--bs-info-bg-subtle: rgb(0.2, 41, 50.8);
--bs-warning-bg-subtle: rgb(51, 50.2, 30);
--bs-danger-bg-subtle: #331316;
--bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: #992670;
--bs-secondary-border-subtle: #017b98;
--bs-success-border-subtle: #039961;
--bs-info-border-subtle: #017b98;
--bs-warning-border-subtle: #99975a;
--bs-primary-border-subtle: rgb(153, 38.4, 111.6);
--bs-secondary-border-subtle: rgb(0.6, 123, 152.4);
--bs-success-border-subtle: rgb(3, 153, 96.6);
--bs-info-border-subtle: rgb(0.6, 123, 152.4);
--bs-warning-border-subtle: rgb(153, 150.6, 90);
--bs-danger-border-subtle: #993942;
--bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030;
--bs-heading-color: inherit;
--bs-link-color: #ff8cd6;
--bs-link-hover-color: #ffa3de;
--bs-link-color: rgb(255, 140.4, 213.6);
--bs-link-hover-color: rgb(255, 163.32, 221.88);
--bs-link-color-rgb: 255, 140, 214;
--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-bg: #888;
--bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #69ffc7;
--bs-form-valid-border-color: #69ffc7;
--bs-form-valid-color: rgb(105, 255, 198.6);
--bs-form-valid-border-color: rgb(105, 255, 198.6);
--bs-form-invalid-color: #ff9fa8;
--bs-form-invalid-border-color: #ff9fa8;
}
@ -1936,13 +1936,13 @@ progress {
.table-primary {
--bs-table-color: #000;
--bs-table-bg: #ffd9f1;
--bs-table-border-color: #ccaec1;
--bs-table-striped-bg: #f2cee5;
--bs-table-bg: rgb(255, 216.8, 241.2);
--bs-table-border-color: rgb(204, 173.44, 192.96);
--bs-table-striped-bg: rgb(242.25, 205.96, 229.14);
--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-hover-bg: #ecc9df;
--bs-table-hover-bg: rgb(235.875, 200.54, 223.11);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1950,13 +1950,13 @@ progress {
.table-secondary {
--bs-table-color: #000;
--bs-table-bg: #ccf5ff;
--bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: #c2e9f2;
--bs-table-bg: rgb(204.2, 245, 254.8);
--bs-table-border-color: rgb(163.36, 196, 203.84);
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
--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-hover-bg: #bde3ec;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1964,13 +1964,13 @@ progress {
.table-success {
--bs-table-color: #000;
--bs-table-bg: #cdffec;
--bs-table-border-color: #a4ccbd;
--bs-table-striped-bg: #c3f2e0;
--bs-table-bg: rgb(205, 255, 236.2);
--bs-table-border-color: rgb(164, 204, 188.96);
--bs-table-striped-bg: rgb(194.75, 242.25, 224.39);
--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-hover-bg: #beecda;
--bs-table-hover-bg: rgb(189.625, 235.875, 218.485);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1978,13 +1978,13 @@ progress {
.table-info {
--bs-table-color: #000;
--bs-table-bg: #ccf5ff;
--bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: #c2e9f2;
--bs-table-bg: rgb(204.2, 245, 254.8);
--bs-table-border-color: rgb(163.36, 196, 203.84);
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
--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-hover-bg: #bde3ec;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1992,13 +1992,13 @@ progress {
.table-warning {
--bs-table-color: #000;
--bs-table-bg: #fffeea;
--bs-table-border-color: #cccbbb;
--bs-table-striped-bg: #f2f1de;
--bs-table-bg: rgb(255, 254.2, 234);
--bs-table-border-color: rgb(204, 203.36, 187.2);
--bs-table-striped-bg: rgb(242.25, 241.49, 222.3);
--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-hover-bg: #ecebd8;
--bs-table-hover-bg: rgb(235.875, 235.135, 216.45);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2007,12 +2007,12 @@ progress {
.table-danger {
--bs-table-color: #000;
--bs-table-bg: #ffdfe2;
--bs-table-border-color: #ccb2b5;
--bs-table-striped-bg: #f2d4d7;
--bs-table-border-color: rgb(204, 178.4, 180.8);
--bs-table-striped-bg: rgb(242.25, 211.85, 214.7);
--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-hover-bg: #ecced1;
--bs-table-hover-bg: rgb(235.875, 206.275, 209.05);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2021,12 +2021,12 @@ progress {
.table-light {
--bs-table-color: #fff;
--bs-table-bg: #444;
--bs-table-border-color: dimgray;
--bs-table-striped-bg: #4d4d4d;
--bs-table-border-color: rgb(105.4, 105.4, 105.4);
--bs-table-striped-bg: rgb(77.35, 77.35, 77.35);
--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-hover-bg: #525252;
--bs-table-hover-bg: rgb(82.025, 82.025, 82.025);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2036,11 +2036,11 @@ progress {
--bs-table-color: #000;
--bs-table-bg: #ebebeb;
--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-active-bg: #d4d4d4;
--bs-table-active-bg: rgb(211.5, 211.5, 211.5);
--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;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2141,7 +2141,7 @@ progress {
.form-control:focus {
color: #fff;
background-color: #888;
border-color: #ffa0dd;
border-color: rgb(255, 159.5, 220.5);
outline: 0;
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 {
border-color: #ffa0dd;
border-color: rgb(255, 159.5, 220.5);
outline: 0;
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%);
}
.form-check-input:focus {
border-color: #ffa0dd;
border-color: rgb(255, 159.5, 220.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2491,7 +2491,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #ffc6ea;
background-color: rgb(255, 197.7, 234.3);
background-image: var(--bs-gradient);
}
.form-range::-webkit-slider-runnable-track {
@ -2521,7 +2521,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #ffc6ea;
background-color: rgb(255, 197.7, 234.3);
background-image: var(--bs-gradient);
}
.form-range::-moz-range-track {
@ -2994,12 +2994,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 64, 186);
--bs-btn-border-color: rgb(255, 64, 186);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #d9369e;
--bs-btn-hover-border-color: #cc3395;
--bs-btn-hover-bg: rgb(216.75, 54.4, 158.1);
--bs-btn-hover-border-color: rgb(204, 51.2, 148.8);
--bs-btn-focus-shadow-rgb: 255, 93, 196;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #cc3395;
--bs-btn-active-border-color: #bf308c;
--bs-btn-active-bg: rgb(204, 51.2, 148.8);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: rgb(255, 64, 186);
@ -3011,12 +3011,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: #1ad2fe;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
--bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe;
@ -3028,12 +3028,12 @@ textarea.form-control-lg {
--bs-btn-bg: #05ffa1;
--bs-btn-border-color: #05ffa1;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #2bffaf;
--bs-btn-hover-border-color: #1effaa;
--bs-btn-hover-bg: rgb(42.5, 255, 175.1);
--bs-btn-hover-border-color: rgb(30, 255, 170.4);
--bs-btn-focus-shadow-rgb: 4, 217, 137;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #37ffb4;
--bs-btn-active-border-color: #1effaa;
--bs-btn-active-bg: rgb(55, 255, 179.8);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #05ffa1;
@ -3045,12 +3045,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: #1ad2fe;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
--bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe;
@ -3062,12 +3062,12 @@ textarea.form-control-lg {
--bs-btn-bg: #fffb96;
--bs-btn-border-color: #fffb96;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #fffca6;
--bs-btn-hover-border-color: #fffba1;
--bs-btn-hover-bg: rgb(255, 251.6, 165.75);
--bs-btn-hover-border-color: rgb(255, 251.4, 160.5);
--bs-btn-focus-shadow-rgb: 217, 213, 128;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #fffcab;
--bs-btn-active-border-color: #fffba1;
--bs-btn-active-bg: rgb(255, 251.8, 171);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #fffb96;
@ -3079,12 +3079,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 95, 110);
--bs-btn-border-color: rgb(255, 95, 110);
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #ff7784;
--bs-btn-hover-border-color: #ff6f7d;
--bs-btn-hover-bg: rgb(255, 119, 131.75);
--bs-btn-hover-border-color: rgb(255, 111, 124.5);
--bs-btn-focus-shadow-rgb: 217, 81, 94;
--bs-btn-active-color: #000;
--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-disabled-color: #000;
--bs-btn-disabled-bg: rgb(255, 95, 110);
@ -3096,11 +3096,11 @@ textarea.form-control-lg {
--bs-btn-bg: #444;
--bs-btn-border-color: #444;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #3a3a3a;
--bs-btn-hover-border-color: #363636;
--bs-btn-hover-bg: rgb(57.8, 57.8, 57.8);
--bs-btn-hover-border-color: rgb(54.4, 54.4, 54.4);
--bs-btn-focus-shadow-rgb: 96, 96, 96;
--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-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff;
@ -4534,7 +4534,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%23661a4a' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4652,8 +4652,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {

View file

@ -35,7 +35,7 @@
--bs-info: #01cdfe;
--bs-warning: #fffb96;
--bs-danger: rgb(255, 95, 110);
--bs-light: #dadee3;
--bs-light: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-dark: #212529;
--bs-primary-rgb: 255, 64, 186;
--bs-secondary-rgb: 1, 205, 254;
@ -45,27 +45,27 @@
--bs-danger-rgb: 255, 95, 110;
--bs-light-rgb: 218, 222, 227;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #661a4a;
--bs-secondary-text-emphasis: #005266;
--bs-success-text-emphasis: #026640;
--bs-info-text-emphasis: #005266;
--bs-warning-text-emphasis: #66643c;
--bs-primary-text-emphasis: rgb(102, 25.6, 74.4);
--bs-secondary-text-emphasis: rgb(0.4, 82, 101.6);
--bs-success-text-emphasis: rgb(2, 102, 64.4);
--bs-info-text-emphasis: rgb(0.4, 82, 101.6);
--bs-warning-text-emphasis: rgb(102, 100.4, 60);
--bs-danger-text-emphasis: #66262c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #ffd9f1;
--bs-secondary-bg-subtle: #ccf5ff;
--bs-success-bg-subtle: #cdffec;
--bs-info-bg-subtle: #ccf5ff;
--bs-warning-bg-subtle: #fffeea;
--bs-primary-bg-subtle: rgb(255, 216.8, 241.2);
--bs-secondary-bg-subtle: rgb(204.2, 245, 254.8);
--bs-success-bg-subtle: rgb(205, 255, 236.2);
--bs-info-bg-subtle: rgb(204.2, 245, 254.8);
--bs-warning-bg-subtle: rgb(255, 254.2, 234);
--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-primary-border-subtle: #ffb3e3;
--bs-secondary-border-subtle: #99ebff;
--bs-success-border-subtle: #9bffd9;
--bs-info-border-subtle: #99ebff;
--bs-warning-border-subtle: #fffdd5;
--bs-primary-border-subtle: rgb(255, 178.6, 227.4);
--bs-secondary-border-subtle: rgb(153.4, 235, 254.6);
--bs-success-border-subtle: rgb(155, 255, 217.4);
--bs-info-border-subtle: rgb(153.4, 235, 254.6);
--bs-warning-border-subtle: rgb(255, 253.4, 213);
--bs-danger-border-subtle: #ffbfc5;
--bs-light-border-subtle: #e9ecef;
--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-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-code-color: rgb(255, 64, 186);
--bs-highlight-color: #495057;
--bs-highlight-bg: #fffeea;
--bs-highlight-bg: rgb(255, 254.2, 234);
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
@ -140,44 +140,44 @@
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--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-primary-text-emphasis: #ff8cd6;
--bs-secondary-text-emphasis: #67e1fe;
--bs-success-text-emphasis: #69ffc7;
--bs-info-text-emphasis: #67e1fe;
--bs-warning-text-emphasis: #fffdc0;
--bs-primary-text-emphasis: rgb(255, 140.4, 213.6);
--bs-secondary-text-emphasis: rgb(102.6, 225, 254.4);
--bs-success-text-emphasis: rgb(105, 255, 198.6);
--bs-info-text-emphasis: rgb(102.6, 225, 254.4);
--bs-warning-text-emphasis: rgb(255, 252.6, 192);
--bs-danger-text-emphasis: #ff9fa8;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #330d25;
--bs-secondary-bg-subtle: #002933;
--bs-success-bg-subtle: #013320;
--bs-info-bg-subtle: #002933;
--bs-warning-bg-subtle: #33321e;
--bs-primary-bg-subtle: rgb(51, 12.8, 37.2);
--bs-secondary-bg-subtle: rgb(0.2, 41, 50.8);
--bs-success-bg-subtle: rgb(1, 51, 32.2);
--bs-info-bg-subtle: rgb(0.2, 41, 50.8);
--bs-warning-bg-subtle: rgb(51, 50.2, 30);
--bs-danger-bg-subtle: #331316;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #992670;
--bs-secondary-border-subtle: #017b98;
--bs-success-border-subtle: #039961;
--bs-info-border-subtle: #017b98;
--bs-warning-border-subtle: #99975a;
--bs-primary-border-subtle: rgb(153, 38.4, 111.6);
--bs-secondary-border-subtle: rgb(0.6, 123, 152.4);
--bs-success-border-subtle: rgb(3, 153, 96.6);
--bs-info-border-subtle: rgb(0.6, 123, 152.4);
--bs-warning-border-subtle: rgb(153, 150.6, 90);
--bs-danger-border-subtle: #993942;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #ff8cd6;
--bs-link-hover-color: #ffa3de;
--bs-link-color: rgb(255, 140.4, 213.6);
--bs-link-hover-color: rgb(255, 163.32, 221.88);
--bs-link-color-rgb: 255, 140, 214;
--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-bg: #66643c;
--bs-highlight-bg: rgb(102, 100.4, 60);
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #69ffc7;
--bs-form-valid-border-color: #69ffc7;
--bs-form-valid-color: rgb(105, 255, 198.6);
--bs-form-valid-border-color: rgb(105, 255, 198.6);
--bs-form-invalid-color: #ff9fa8;
--bs-form-invalid-border-color: #ff9fa8;
}
@ -1935,13 +1935,13 @@ progress {
.table-primary {
--bs-table-color: #000;
--bs-table-bg: #ffd9f1;
--bs-table-border-color: #ccaec1;
--bs-table-striped-bg: #f2cee5;
--bs-table-bg: rgb(255, 216.8, 241.2);
--bs-table-border-color: rgb(204, 173.44, 192.96);
--bs-table-striped-bg: rgb(242.25, 205.96, 229.14);
--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-hover-bg: #ecc9df;
--bs-table-hover-bg: rgb(235.875, 200.54, 223.11);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary {
--bs-table-color: #000;
--bs-table-bg: #ccf5ff;
--bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: #c2e9f2;
--bs-table-bg: rgb(204.2, 245, 254.8);
--bs-table-border-color: rgb(163.36, 196, 203.84);
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
--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-hover-bg: #bde3ec;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success {
--bs-table-color: #000;
--bs-table-bg: #cdffec;
--bs-table-border-color: #a4ccbd;
--bs-table-striped-bg: #c3f2e0;
--bs-table-bg: rgb(205, 255, 236.2);
--bs-table-border-color: rgb(164, 204, 188.96);
--bs-table-striped-bg: rgb(194.75, 242.25, 224.39);
--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-hover-bg: #beecda;
--bs-table-hover-bg: rgb(189.625, 235.875, 218.485);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info {
--bs-table-color: #000;
--bs-table-bg: #ccf5ff;
--bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: #c2e9f2;
--bs-table-bg: rgb(204.2, 245, 254.8);
--bs-table-border-color: rgb(163.36, 196, 203.84);
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06);
--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-hover-bg: #bde3ec;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning {
--bs-table-color: #000;
--bs-table-bg: #fffeea;
--bs-table-border-color: #cccbbb;
--bs-table-striped-bg: #f2f1de;
--bs-table-bg: rgb(255, 254.2, 234);
--bs-table-border-color: rgb(204, 203.36, 187.2);
--bs-table-striped-bg: rgb(242.25, 241.49, 222.3);
--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-hover-bg: #ecebd8;
--bs-table-hover-bg: rgb(235.875, 235.135, 216.45);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2006,12 +2006,12 @@ progress {
.table-danger {
--bs-table-color: #000;
--bs-table-bg: #ffdfe2;
--bs-table-border-color: #ccb2b5;
--bs-table-striped-bg: #f2d4d7;
--bs-table-border-color: rgb(204, 178.4, 180.8);
--bs-table-striped-bg: rgb(242.25, 211.85, 214.7);
--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-hover-bg: #ecced1;
--bs-table-hover-bg: rgb(235.875, 206.275, 209.05);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2019,13 +2019,13 @@ progress {
.table-light {
--bs-table-color: #000;
--bs-table-bg: #dadee3;
--bs-table-border-color: #aeb2b6;
--bs-table-striped-bg: #cfd3d8;
--bs-table-bg: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-table-border-color: rgb(174.1179310345, 177.74, 181.3620689655);
--bs-table-striped-bg: rgb(206.7650431034, 211.06625, 215.3674568966);
--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-hover-bg: #cacdd2;
--bs-table-hover-bg: rgb(201.3238577586, 205.511875, 209.6998922414);
--bs-table-hover-color: #000;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark {
--bs-table-color: #fff;
--bs-table-bg: #212529;
--bs-table-border-color: #4d5154;
--bs-table-striped-bg: #2c3034;
--bs-table-border-color: rgb(77.4, 80.6, 83.8);
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);
--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-hover-bg: #323539;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);
--bs-table-hover-color: #fff;
color: var(--bs-table-color);
border-color: var(--bs-table-border-color);
@ -2140,7 +2140,7 @@ progress {
.form-control:focus {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: #ffa0dd;
border-color: rgb(255, 159.5, 220.5);
outline: 0;
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 {
border-color: #ffa0dd;
border-color: rgb(255, 159.5, 220.5);
outline: 0;
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%);
}
.form-check-input:focus {
border-color: #ffa0dd;
border-color: rgb(255, 159.5, 220.5);
outline: 0;
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 {
--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 {
background-position: right center;
@ -2490,7 +2490,7 @@ textarea.form-control-lg {
}
}
.form-range::-webkit-slider-thumb:active {
background-color: #ffc6ea;
background-color: rgb(255, 197.7, 234.3);
background-image: var(--bs-gradient);
}
.form-range::-webkit-slider-runnable-track {
@ -2520,7 +2520,7 @@ textarea.form-control-lg {
}
}
.form-range::-moz-range-thumb:active {
background-color: #ffc6ea;
background-color: rgb(255, 197.7, 234.3);
background-image: var(--bs-gradient);
}
.form-range::-moz-range-track {
@ -2993,12 +2993,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 64, 186);
--bs-btn-border-color: rgb(255, 64, 186);
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #d9369e;
--bs-btn-hover-border-color: #cc3395;
--bs-btn-hover-bg: rgb(216.75, 54.4, 158.1);
--bs-btn-hover-border-color: rgb(204, 51.2, 148.8);
--bs-btn-focus-shadow-rgb: 255, 93, 196;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #cc3395;
--bs-btn-active-border-color: #bf308c;
--bs-btn-active-bg: rgb(204, 51.2, 148.8);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: rgb(255, 64, 186);
@ -3010,12 +3010,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: #1ad2fe;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
--bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe;
@ -3027,12 +3027,12 @@ textarea.form-control-lg {
--bs-btn-bg: #05ffa1;
--bs-btn-border-color: #05ffa1;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #2bffaf;
--bs-btn-hover-border-color: #1effaa;
--bs-btn-hover-bg: rgb(42.5, 255, 175.1);
--bs-btn-hover-border-color: rgb(30, 255, 170.4);
--bs-btn-focus-shadow-rgb: 4, 217, 137;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #37ffb4;
--bs-btn-active-border-color: #1effaa;
--bs-btn-active-bg: rgb(55, 255, 179.8);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #05ffa1;
@ -3044,12 +3044,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: #1ad2fe;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15);
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1);
--bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-bg: rgb(51.8, 215, 254.2);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe;
@ -3061,12 +3061,12 @@ textarea.form-control-lg {
--bs-btn-bg: #fffb96;
--bs-btn-border-color: #fffb96;
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #fffca6;
--bs-btn-hover-border-color: #fffba1;
--bs-btn-hover-bg: rgb(255, 251.6, 165.75);
--bs-btn-hover-border-color: rgb(255, 251.4, 160.5);
--bs-btn-focus-shadow-rgb: 217, 213, 128;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #fffcab;
--bs-btn-active-border-color: #fffba1;
--bs-btn-active-bg: rgb(255, 251.8, 171);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #fffb96;
@ -3078,12 +3078,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 95, 110);
--bs-btn-border-color: rgb(255, 95, 110);
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #ff7784;
--bs-btn-hover-border-color: #ff6f7d;
--bs-btn-hover-bg: rgb(255, 119, 131.75);
--bs-btn-hover-border-color: rgb(255, 111, 124.5);
--bs-btn-focus-shadow-rgb: 217, 81, 94;
--bs-btn-active-color: #000;
--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-disabled-color: #000;
--bs-btn-disabled-bg: rgb(255, 95, 110);
@ -3092,19 +3092,19 @@ textarea.form-control-lg {
.btn-light {
--bs-btn-color: #000;
--bs-btn-bg: #dadee3;
--bs-btn-border-color: #dadee3;
--bs-btn-bg: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-btn-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #b9bdc1;
--bs-btn-hover-border-color: #aeb2b6;
--bs-btn-hover-bg: rgb(185.0003017241, 188.84875, 192.6971982759);
--bs-btn-hover-border-color: rgb(174.1179310345, 177.74, 181.3620689655);
--bs-btn-focus-shadow-rgb: 185, 189, 193;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #aeb2b6;
--bs-btn-active-border-color: #a4a7aa;
--bs-btn-active-bg: rgb(174.1179310345, 177.74, 181.3620689655);
--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-disabled-color: #000;
--bs-btn-disabled-bg: #dadee3;
--bs-btn-disabled-border-color: #dadee3;
--bs-btn-disabled-bg: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-btn-disabled-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
}
.btn-dark {
@ -3112,12 +3112,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529;
--bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff;
--bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: #373b3e;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);
--bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff;
--bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: #373b3e;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);
--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-disabled-color: #fff;
--bs-btn-disabled-bg: #212529;
@ -3227,19 +3227,19 @@ textarea.form-control-lg {
}
.btn-outline-light {
--bs-btn-color: #dadee3;
--bs-btn-border-color: #dadee3;
--bs-btn-color: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-btn-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-btn-hover-color: #000;
--bs-btn-hover-bg: #dadee3;
--bs-btn-hover-border-color: #dadee3;
--bs-btn-hover-bg: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-btn-hover-border-color: rgb(217.6474137931, 222.175, 226.7025862069);
--bs-btn-focus-shadow-rgb: 218, 222, 227;
--bs-btn-active-color: #000;
--bs-btn-active-bg: #dadee3;
--bs-btn-active-border-color: #dadee3;
--bs-btn-active-bg: rgb(217.6474137931, 222.175, 226.7025862069);
--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-disabled-color: #dadee3;
--bs-btn-disabled-color: rgb(217.6474137931, 222.175, 226.7025862069);
--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;
}
@ -4533,7 +4533,7 @@ textarea.form-control-lg {
--bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg);
--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='none' stroke='%23661a4a' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%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-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
--bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem;
@ -4651,8 +4651,8 @@ textarea.form-control-lg {
}
[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-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-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='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 {
@ -6896,8 +6896,8 @@ textarea.form-control-lg {
text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important;
}
.link-light:hover, .link-light:focus {
color: RGBA(225, 229, 233, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(225, 229, 233, var(--bs-link-underline-opacity, 1)) !important;
color: RGBA(225, 229, 232, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(225, 229, 232, var(--bs-link-underline-opacity, 1)) !important;
}
.link-dark {

View file

@ -305,5 +305,8 @@
<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" />
</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>
</svg>

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -5,6 +5,7 @@ import App from "../shared/components/app/app";
import { lazyHighlightjs } from "../shared/lazy-highlightjs";
import { loadUserLanguage } from "../shared/services/I18NextService";
import { verifyDynamicImports } from "../shared/dynamic-imports";
import { setupEmojiDataModel } from "../shared/markdown";
import "bootstrap/js/dist/collapse";
import "bootstrap/js/dist/dropdown";
@ -22,7 +23,7 @@ async function startClient() {
lazyHighlightjs.enableLazyLoading();
await loadUserLanguage();
await Promise.all([loadUserLanguage(), setupEmojiDataModel()]);
const wrapper = (
<BrowserRouter>

View file

@ -14,7 +14,7 @@ const themes: ReadonlyArray<string> = [
"litely-compact",
"vaporwave-dark",
"vaporwave-light",
"i386",
"i386-dark",
];
export async function buildThemeList(): Promise<ReadonlyArray<string>> {

View file

@ -33,22 +33,29 @@ export async function createSsrHtml(
);
if (!appleTouchIcon) {
appleTouchIcon = site?.site_view.site.icon
? `data:image/png;base64,${await sharp(
await fetchIconPng(site.site_view.site.icon),
)
.resize(180, 180)
.extend({
bottom: 20,
top: 20,
left: 20,
right: 20,
background: "#222222",
})
.png()
.toBuffer()
.then(buf => buf.toString("base64"))}`
: favIconPngUrl;
try {
appleTouchIcon = site?.site_view.site.icon
? `data:image/png;base64,${await sharp(
await fetchIconPng(site.site_view.site.icon),
)
.resize(180, 180)
.extend({
bottom: 20,
top: 20,
left: 20,
right: 20,
background: "#222222",
})
.png()
.toBuffer()
.then(buf => buf.toString("base64"))}`
: favIconPngUrl;
} catch {
console.log(
"Could not fetch site logo for apple touch icon. Using default icon.",
);
appleTouchIcon = favIconPngUrl;
}
}
const erudaStr =

View file

@ -1,19 +1,54 @@
import { readFile } from "fs/promises";
import { Site } from "lemmy-js-client";
import path from "path";
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];
let icons: Icon[] | null = null;
const defaultLogoPathDirectory = path.join(
process.cwd(),
"dist",
"assets",
"icons",
);
function mapIcon(src: string, size: number): Icon {
return {
sizes: `${size}x${size}`,
type: "image/png",
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) {
const icon = site.icon ? await fetchIconPng(site.icon) : null;
if (!icons) {
try {
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 {
name: site.name,
@ -24,29 +59,7 @@ export default async function (site: Site) {
id: "/",
background_color: "#222222",
theme_color: "#222222",
icons: await Promise.all(
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",
};
}),
),
icons,
shortcuts: [
{
name: "Search",

View file

@ -13,16 +13,18 @@ import { Navbar } from "./navbar";
import "./styles.scss";
import { Theme } from "./theme";
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";
function handleJumpToContent(event) {
function handleJumpToContent(app: App, event: any) {
event.preventDefault();
app.contentRef.current?.focus();
}
export default class App extends Component<any, any> {
private isoData: IsoDataOptionalSite = setIsoData(this.context);
private readonly rootRef = createRef<HTMLDivElement>();
readonly contentRef = createRef<HTMLDivElement>();
componentDidMount() {
setupTippy(this.rootRef);
@ -69,7 +71,7 @@ export default class App extends Component<any, any> {
return (
<ErrorGuard>
<div tabIndex={-1}>
<div tabIndex={-1} ref={this.contentRef}>
{RouteComponent &&
(isAuthPath(path ?? "") ? (
<AuthGuard {...routeProps}>

View file

@ -74,6 +74,9 @@ export class CommentForm extends Component<CommentFormProps, any> {
<Link className="alert-link" to="/login">
#
</Link>
<Link className="alert-link" to="/signup">
#
</Link>
</T>
</div>
)}

View file

@ -51,7 +51,7 @@ import { CommunityLink } from "../community/community-link";
import { PersonListing } from "../person/person-listing";
import { CommentForm } from "./comment-form";
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 { RequestState } from "../../services/HttpService";
import { VoteDisplay } from "../common/vote-display";
@ -294,7 +294,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
/>
)}
</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.markable && (
<button
@ -637,7 +637,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
async handleBanFromCommunity({
daysUntilExpires,
reason,
shouldRemove,
shouldRemoveOrRestoreData,
}: BanUpdateForm) {
const {
creator: { id: person_id },
@ -646,10 +646,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
} = this.commentView;
const ban = !creator_banned_from_community;
// If its an unban, restore all their data
if (ban === false) {
shouldRemove = false;
shouldRemoveOrRestoreData = true;
}
const expires = futureDaysToUnixTime(daysUntilExpires);
@ -657,7 +656,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
community_id,
person_id,
ban,
remove_data: shouldRemove,
remove_or_restore_data: shouldRemoveOrRestoreData,
reason,
expires,
});
@ -666,7 +665,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
async handleBanFromSite({
daysUntilExpires,
reason,
shouldRemove,
shouldRemoveOrRestoreData,
}: BanUpdateForm) {
const {
creator: { id: person_id, banned },
@ -676,14 +675,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
// If its an unban, restore all their data
if (ban === false) {
shouldRemove = false;
shouldRemoveOrRestoreData = true;
}
const expires = futureDaysToUnixTime(daysUntilExpires);
this.props.onBanPerson({
person_id,
ban,
remove_data: shouldRemove,
remove_or_restore_data: shouldRemoveOrRestoreData,
reason,
expires,
});

View file

@ -47,13 +47,13 @@ export class CommentSortSelect extends Component<
<option disabled aria-hidden="true">
{I18NextService.i18n.t("sort_type")}
</option>
<option value={"Hot"}>{I18NextService.i18n.t("hot")}</option>,
<option value={"Controversial"}>
<option value="Hot">{I18NextService.i18n.t("hot")}</option>
<option value="Controversial">
{I18NextService.i18n.t("controversial")}
</option>
<option value={"Top"}>{I18NextService.i18n.t("top")}</option>,
<option value={"New"}>{I18NextService.i18n.t("new")}</option>
<option value={"Old"}>{I18NextService.i18n.t("old")}</option>
<option value="Top">{I18NextService.i18n.t("top")}</option>
<option value="New">{I18NextService.i18n.t("new")}</option>
<option value="Old">{I18NextService.i18n.t("old")}</option>
</select>
<a
className="sort-select-help text-muted"

View file

@ -14,9 +14,11 @@ import {
import ActionButton from "./action-button";
import classNames from "classnames";
import { Link } from "inferno-router";
import ConfirmationModal from "../confirmation-modal";
import ViewVotesModal from "../view-votes-modal";
import ModActionFormModal, { BanUpdateForm } from "../mod-action-form-modal";
import ConfirmationModal from "../modal/confirmation-modal";
import ViewVotesModal from "../modal/view-votes-modal";
import ModActionFormModal, {
BanUpdateForm,
} from "../modal/mod-action-form-modal";
import { BanType, CommentNodeView, PurgeType } from "../../../interfaces";
import { getApubName, hostname } from "@utils/helpers";
import { tippyMixin } from "../../mixins/tippy-mixin";
@ -159,6 +161,26 @@ export default class ContentActionDropdown extends Component<
(amMod(community.id) || (amAdmin() && community.local)) &&
!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 (
<>
{type === "comment" && (
@ -349,15 +371,23 @@ export default class ContentActionDropdown extends Component<
<li>
<Link
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
to={`/modlog?${type === "post" ? "postId" : "commentId"}=${id}`}
title={I18NextService.i18n.t("moderation_history")}
aria-label={I18NextService.i18n.t("moderation_history")}
data-tippy-content={I18NextService.i18n.t(
"moderation_history",
)}
to={`/modlog?userId=${creator.id}`}
title={modHistoryUserTranslation}
aria-label={modHistoryUserTranslation}
data-tippy-content={modHistoryUserTranslation}
>
<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>
</li>
{(this.canMod || this.canAdmin) && (

View file

@ -13,8 +13,10 @@ interface EmojiPickerState {
showPicker: boolean;
}
function closeEmojiMartOnEsc(i, event): void {
event.key === "Escape" && i.setState({ showPicker: false });
function closeEmojiMartOnEsc(i: EmojiPicker, event: KeyboardEvent): void {
if (event.key === "Escape") {
i.setState({ showPicker: false });
}
}
@tippyMixin
@ -72,9 +74,11 @@ export class EmojiPicker extends Component<EmojiPickerProps, EmojiPickerState> {
e.preventDefault();
i.setState({ showPicker: !i.state.showPicker });
i.state.showPicker
? document.addEventListener("keyup", e => closeEmojiMartOnEsc(i, e))
: document.removeEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
if (i.state.showPicker) {
document.addEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
} else {
document.removeEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
}
}
handleEmojiClick(e: any) {

View file

@ -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> {
render() {
return Array.from({ length: this.props.itemCount ?? 10 }, (_, index) => (

View file

@ -76,8 +76,6 @@ export class MarkdownTextArea extends Component<
private id = `markdown-textarea-${randomStr()}`;
private formId = `markdown-form-${randomStr()}`;
private tribute: any;
state: MarkdownTextAreaState = {
content: this.props.initialContent,
languageId: this.props.initialLanguageId,
@ -91,26 +89,25 @@ export class MarkdownTextArea extends Component<
this.handleLanguageChange = this.handleLanguageChange.bind(this);
this.handleEmoji = this.handleEmoji.bind(this);
if (isBrowser()) {
this.tribute = setupTribute();
}
}
componentDidMount() {
const textarea: any = document.getElementById(this.id);
if (textarea) {
autosize(textarea);
this.tribute.attach(textarea);
textarea.addEventListener("tribute-replaced", () => {
this.setState({ content: textarea.value });
autosize.update(textarea);
});
async componentDidMount() {
if (isBrowser()) {
const tribute = await setupTribute();
const textarea: any = document.getElementById(this.id);
if (textarea) {
autosize(textarea);
tribute.attach(textarea);
textarea.addEventListener("tribute-replaced", () => {
this.setState({ content: textarea.value });
autosize.update(textarea);
});
this.quoteInsert();
this.quoteInsert();
if (this.props.focus) {
textarea.focus();
if (this.props.focus) {
textarea.focus();
}
}
}
}
@ -226,6 +223,7 @@ export class MarkdownTextArea extends Component<
this.props.maxLength ?? markdownFieldCharacterLimit
}
placeholder={this.props.placeholder}
spellCheck
/>
{this.state.previewMode && this.state.content && (
<div
@ -259,29 +257,14 @@ export class MarkdownTextArea extends Component<
</div>
<div className="col-12 d-flex align-items-center flex-wrap mt-2">
{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}
/>
)}
{/* A flex expander */}
<div className="flex-grow-1"></div>
{this.props.replyType && (
{this.props.buttonTitle && (
<button
type="button"
type="submit"
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
@ -296,16 +279,31 @@ export class MarkdownTextArea extends Component<
? I18NextService.i18n.t("edit")
: I18NextService.i18n.t("preview")}
</button>
{this.props.buttonTitle && (
{this.props.replyType && (
<button
type="submit"
type="button"
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" />}
{this.props.buttonTitle}
{I18NextService.i18n.t("cancel")}
</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>
</form>
@ -451,7 +449,7 @@ export class MarkdownTextArea extends Component<
}));
}),
);
} catch (e) {
} catch {
errorOccurred = true;
}
}
@ -462,12 +460,29 @@ export class MarkdownTextArea extends Component<
if (res.state === "success") {
if (res.data.msg === "ok") {
const imageMarkdown = `![](${res.data.url})`;
i.setState(({ content }) => ({
content: content ? `${content}\n${imageMarkdown}` : imageMarkdown,
}));
const textarea: HTMLTextAreaElement = document.getElementById(
i.id,
) as HTMLTextAreaElement;
const cursorPosition = textarea.selectionStart;
i.setState(({ content }) => {
const currentContent = content || "";
return {
content:
currentContent.slice(0, cursorPosition) +
imageMarkdown +
currentContent.slice(cursorPosition),
};
});
i.contentChange();
const textarea: any = document.getElementById(i.id);
autosize.update(textarea);
// Update cursor position to after the inserted image link
setTimeout(() => {
textarea.selectionStart = cursorPosition + imageMarkdown.length;
textarea.selectionEnd = cursorPosition + imageMarkdown.length;
autosize.update(textarea);
}, 10);
pictrsDeleteToast(image.name, res.data.delete_url as string);
} else if (res.data.msg === "too_large") {
toast(I18NextService.i18n.t("upload_too_large"), "danger");

View file

@ -1,10 +1,10 @@
import { Component, LinkedEvent, createRef, linkEvent } from "inferno";
import { modalMixin } from "../mixins/modal-mixin";
import { adultConsentCookieKey } from "../../config";
import { mdToHtml } from "../../markdown";
import { I18NextService } from "../../services";
import { modalMixin } from "../../mixins/modal-mixin";
import { adultConsentCookieKey } from "../../../config";
import { mdToHtml } from "../../../markdown";
import { I18NextService } from "../../../services";
import { isHttps } from "@utils/env";
import { IsoData } from "../../interfaces";
import { IsoData } from "../../../interfaces";
import { setIsoData } from "@utils/app";
interface AdultConsentModalProps {

View file

@ -1,20 +1,14 @@
import {
Component,
InfernoNode,
RefObject,
createRef,
linkEvent,
} from "inferno";
import { I18NextService } from "../../services";
import { Component, RefObject, createRef, linkEvent } from "inferno";
import { I18NextService } from "../../../services";
import type { Modal } from "bootstrap";
import { Spinner } from "./icon";
import { LoadingEllipses } from "./loading-ellipses";
import { modalMixin } from "../mixins/modal-mixin";
import { Spinner } from "../icon";
import { LoadingEllipses } from "../loading-ellipses";
import { modalMixin } from "../../mixins/modal-mixin";
import { MouseEventHandler } from "inferno";
interface ConfirmationModalProps {
children?: InfernoNode;
onYes: () => Promise<void>;
onNo: () => void;
onNo: MouseEventHandler<HTMLButtonElement>;
message: string;
loadingMessage: string;
show: boolean;

View file

@ -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: {} });
}
}

View 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>
);
}
}

View file

@ -5,18 +5,18 @@ import {
createRef,
linkEvent,
} from "inferno";
import { I18NextService } from "../../services/I18NextService";
import { PurgeWarning, Spinner } from "./icon";
import { I18NextService } from "../../../services/I18NextService";
import { PurgeWarning, Spinner } from "../icon";
import { getApubName, randomStr } from "@utils/helpers";
import type { Modal } from "bootstrap";
import classNames from "classnames";
import { Community, Person } from "lemmy-js-client";
import { LoadingEllipses } from "./loading-ellipses";
import { modalMixin } from "../mixins/modal-mixin";
import { LoadingEllipses } from "../loading-ellipses";
import { modalMixin } from "../../mixins/modal-mixin";
export interface BanUpdateForm {
reason?: string;
shouldRemove?: boolean;
shouldRemoveOrRestoreData?: boolean;
daysUntilExpires?: number;
}
@ -31,7 +31,7 @@ interface ModActionFormModalPropsCommunityBan {
modActionType: "community-ban";
onSubmit: (form: BanUpdateForm) => Promise<void>;
creator: Person;
community: Community;
community?: Community;
isBanned: boolean;
}
@ -69,7 +69,7 @@ interface ModActionFormFormState {
loading: boolean;
reason: string;
daysUntilExpire?: number;
shouldRemoveData?: boolean;
shouldRemoveOrRestoreData?: boolean;
shouldPermaBan?: boolean;
}
@ -84,7 +84,7 @@ function handleExpiryChange(i: ModActionFormModal, event: any) {
function handleToggleRemove(i: ModActionFormModal) {
i.setState(prev => ({
...prev,
shouldRemoveData: !prev.shouldRemoveData,
shouldRemoveOrRestoreData: !prev.shouldRemoveOrRestoreData,
}));
}
@ -104,7 +104,7 @@ async function handleSubmit(i: ModActionFormModal, event: any) {
await i.props.onSubmit({
reason: i.state.reason,
daysUntilExpires: i.state.daysUntilExpire!,
shouldRemove: i.state.shouldRemoveData!,
shouldRemoveOrRestoreData: i.state.shouldRemoveOrRestoreData!,
} as BanUpdateForm & string); // Need to & string to handle type weirdness
} else {
await i.props.onSubmit(i.state.reason);
@ -135,7 +135,7 @@ export default class ModActionFormModal extends Component<
this.reasonRef = createRef();
if (this.isBanModal) {
this.state.shouldRemoveData = false;
this.state.shouldRemoveOrRestoreData = false;
}
}
@ -144,7 +144,7 @@ export default class ModActionFormModal extends Component<
loading,
reason,
daysUntilExpire,
shouldRemoveData,
shouldRemoveOrRestoreData,
shouldPermaBan,
} = this.state;
const reasonId = `mod-form-reason-${randomStr()}`;
@ -249,7 +249,7 @@ export default class ModActionFormModal extends Component<
<input
className="form-check-input user-select-none"
type="checkbox"
checked={shouldRemoveData}
checked={shouldRemoveOrRestoreData}
onChange={linkEvent(this, handleToggleRemove)}
/>
{I18NextService.i18n.t("remove_content")}
@ -328,7 +328,12 @@ export default class ModActionFormModal extends Component<
: "ban_from_community_with_name",
{
user: getApubName(this.props.creator),
community: getApubName(this.props.community),
community: getApubName(
this.props.community ?? {
actor_id: "",
name: "",
},
),
},
);
}

View file

@ -6,10 +6,10 @@ import {
createRef,
linkEvent,
} from "inferno";
import { I18NextService } from "../../services";
import { toast } from "../../toast";
import { I18NextService } from "../../../services";
import { toast } from "../../../toast";
import type { Modal } from "bootstrap";
import { modalMixin } from "../mixins/modal-mixin";
import { modalMixin } from "../../mixins/modal-mixin";
interface TotpModalProps {
children?: InfernoNode;

View file

@ -5,10 +5,10 @@ import {
createRef,
linkEvent,
} from "inferno";
import { I18NextService } from "../../services";
import { I18NextService } from "../../../services";
import type { Modal } from "bootstrap";
import { Icon, Spinner } from "./icon";
import { Paginator } from "../common/paginator";
import { Icon, Spinner } from "../icon";
import { Paginator } from "../paginator";
import {
ListCommentLikesResponse,
ListPostLikesResponse,
@ -19,11 +19,11 @@ import {
HttpService,
LOADING_REQUEST,
RequestState,
} from "../../services/HttpService";
import { fetchLimit } from "../../config";
import { PersonListing } from "../person/person-listing";
import { modalMixin } from "../mixins/modal-mixin";
import { UserBadges } from "./user-badges";
} from "../../../services/HttpService";
import { fetchLimit } from "../../../config";
import { PersonListing } from "../../person/person-listing";
import { modalMixin } from "../../mixins/modal-mixin";
import { UserBadges } from "../user-badges";
import { isBrowser } from "@utils/browser";
interface ViewVotesModalProps {

View file

@ -5,6 +5,7 @@ interface PaginatorProps {
page: number;
onChange(val: number): any;
nextDisabled: boolean;
disabled?: boolean;
}
export class Paginator extends Component<PaginatorProps, any> {
@ -18,6 +19,7 @@ export class Paginator extends Component<PaginatorProps, any> {
<button
className="btn btn-secondary me-2"
onClick={linkEvent(this, this.handlePrev)}
disabled={this.props.disabled}
>
{I18NextService.i18n.t("prev")}
</button>
@ -26,6 +28,7 @@ export class Paginator extends Component<PaginatorProps, any> {
<button
className="btn btn-secondary"
onClick={linkEvent(this, this.handleNext)}
disabled={this.props.disabled}
>
{I18NextService.i18n.t("next")}
</button>

View file

@ -16,6 +16,7 @@ interface PasswordInputProps {
label?: string | null;
showForgotLink?: boolean;
isNew?: boolean;
required?: boolean;
}
interface PasswordInputState {
@ -77,6 +78,7 @@ class PasswordInput extends Component<PasswordInputProps, PasswordInputState> {
label,
showForgotLink,
isNew,
required,
},
state: { show },
} = this;
@ -98,9 +100,11 @@ class PasswordInput extends Component<PasswordInputProps, PasswordInputState> {
autoComplete={isNew ? "new-password" : "current-password"}
onInput={onInput}
value={value}
required
pattern=".{10,60}"
required={required !== false}
pattern=".+"
title={I18NextService.i18n.t("invalid_password")}
minLength={isNew ? 10 : undefined}
maxLength={isNew ? 60 : undefined}
/>
<button
className="btn btn-outline-dark"

View file

@ -1,19 +1,19 @@
import { randomStr } from "@utils/helpers";
import { Component, linkEvent } from "inferno";
import { SortType } from "lemmy-js-client";
import { PostSortType } from "lemmy-js-client";
import { relTags, sortingHelpUrl } from "../../config";
import { I18NextService } from "../../services";
import { Icon } from "./icon";
interface SortSelectProps {
sort: SortType;
onChange(val: SortType): void;
sort: PostSortType;
onChange(val: PostSortType): void;
hideHot?: boolean;
hideMostComments?: boolean;
}
interface SortSelectState {
sort: SortType;
sort: PostSortType;
}
export class SortSelect extends Component<SortSelectProps, SortSelectState> {
@ -47,55 +47,53 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
{I18NextService.i18n.t("sort_type")}
</option>
{!this.props.hideHot && [
<option key={"Hot"} value={"Hot"}>
<option key="Hot" value="Hot">
{I18NextService.i18n.t("hot")}
</option>,
<option key={"Active"} value={"Active"}>
<option key="Active" value="Active">
{I18NextService.i18n.t("active")}
</option>,
<option key={"Scaled"} value={"Scaled"}>
<option key="Scaled" value="Scaled">
{I18NextService.i18n.t("scaled")}
</option>,
]}
<option value={"Controversial"}>
<option value="Controversial">
{I18NextService.i18n.t("controversial")}
</option>
<option value={"New"}>{I18NextService.i18n.t("new")}</option>
<option value={"Old"}>{I18NextService.i18n.t("old")}</option>
<option value="New">{I18NextService.i18n.t("new")}</option>
<option value="Old">{I18NextService.i18n.t("old")}</option>
{!this.props.hideMostComments && [
<option key={"MostComments"} value={"MostComments"}>
<option key="MostComments" value="MostComments">
{I18NextService.i18n.t("most_comments")}
</option>,
<option key={"NewComments"} value={"NewComments"}>
<option key="NewComments" value="NewComments">
{I18NextService.i18n.t("new_comments")}
</option>,
]}
<option disabled aria-hidden="true">
</option>
<option value={"TopHour"}>{I18NextService.i18n.t("top_hour")}</option>
<option value={"TopSixHour"}>
<option value="TopHour">{I18NextService.i18n.t("top_hour")}</option>
<option value="TopSixHour">
{I18NextService.i18n.t("top_six_hours")}
</option>
<option value={"TopTwelveHour"}>
<option value="TopTwelveHour">
{I18NextService.i18n.t("top_twelve_hours")}
</option>
<option value={"TopDay"}>{I18NextService.i18n.t("top_day")}</option>
<option value={"TopWeek"}>{I18NextService.i18n.t("top_week")}</option>
<option value={"TopMonth"}>
{I18NextService.i18n.t("top_month")}
</option>
<option value={"TopThreeMonths"}>
<option value="TopDay">{I18NextService.i18n.t("top_day")}</option>
<option value="TopWeek">{I18NextService.i18n.t("top_week")}</option>
<option value="TopMonth">{I18NextService.i18n.t("top_month")}</option>
<option value="TopThreeMonths">
{I18NextService.i18n.t("top_three_months")}
</option>
<option value={"TopSixMonths"}>
<option value="TopSixMonths">
{I18NextService.i18n.t("top_six_months")}
</option>
<option value={"TopNineMonths"}>
<option value="TopNineMonths">
{I18NextService.i18n.t("top_nine_months")}
</option>
<option value={"TopYear"}>{I18NextService.i18n.t("top_year")}</option>
<option value={"TopAll"}>{I18NextService.i18n.t("top_all")}</option>
<option value="TopYear">{I18NextService.i18n.t("top_year")}</option>
<option value="TopAll">{I18NextService.i18n.t("top_all")}</option>
</select>
<a
className="sort-select-icon text-muted"

View file

@ -16,7 +16,7 @@ import {
ListCommunities,
ListCommunitiesResponse,
ListingType,
SortType,
PostSortType,
} from "lemmy-js-client";
import { InitialFetchRequest } from "../../interfaces";
import { FirstLoadService, I18NextService } from "../../services";
@ -55,7 +55,7 @@ interface CommunitiesState {
interface CommunitiesProps {
listingType: ListingType;
sort: SortType;
sort: PostSortType;
page: number;
}
@ -63,8 +63,8 @@ function getListingTypeFromQuery(listingType?: string): ListingType {
return listingType ? (listingType as ListingType) : "Local";
}
function getSortTypeFromQuery(type?: string): SortType {
return type ? (type as SortType) : "TopMonth";
function getSortTypeFromQuery(type?: string): PostSortType {
return type ? (type as PostSortType) : "TopMonth";
}
export function getCommunitiesQueryParams(source?: string): CommunitiesProps {
@ -302,7 +302,7 @@ export class Communities extends Component<
this.updateUrl({ page });
}
handleSortChange(val: SortType) {
handleSortChange(val: PostSortType) {
this.updateUrl({ sort: val, page: 1 });
}

View file

@ -14,6 +14,7 @@ import { ImageUploadForm } from "../common/image-upload-form";
import { LanguageSelect } from "../common/language-select";
import { MarkdownTextArea } from "../common/markdown-textarea";
import { tippyMixin } from "../mixins/tippy-mixin";
import { validActorRegexPattern } from "../../config";
interface CommunityFormProps {
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)}
required
minLength={3}
pattern="[a-z0-9_]+"
pattern={validActorRegexPattern}
title={I18NextService.i18n.t("community_reqs")}
/>
</div>

View file

@ -1,5 +1,6 @@
import {
commentsToFlatNodes,
commentToPostSortType,
communityRSSUrl,
editComment,
editPost,
@ -81,9 +82,10 @@ import {
RemovePost,
SaveComment,
SavePost,
SortType,
PostSortType,
SuccessResponse,
TransferCommunity,
CommentSortType,
} from "lemmy-js-client";
import { fetchLimit, relTags } from "../../config";
import {
@ -121,6 +123,7 @@ import { IRoutePropsWithFetch } from "../../routes";
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<{
communityRes: GetCommunityResponse;
@ -139,12 +142,12 @@ interface State {
interface CommunityProps {
dataType: DataType;
sort: SortType;
sort: PostSortType;
pageCursor?: PaginationCursor;
showHidden?: StringBoolean;
}
type Fallbacks = { sort: SortType };
type Fallbacks = { sort: PostSortType };
export function getCommunityQueryParams(
source: string | undefined,
@ -162,7 +165,8 @@ export function getCommunityQueryParams(
},
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,
},
);
}
@ -171,12 +175,11 @@ function getDataTypeFromQuery(type?: string): DataType {
return type ? DataType[type] : DataType.Post;
}
function getSortTypeFromQuery(type?: string): SortType {
const mySortType =
UserService.Instance.myUserInfo?.local_user_view.local_user
.default_sort_type;
return type ? (type as SortType) : (mySortType ?? "Active");
function getSortTypeFromQuery(
type?: string,
fallback: PostSortType,
): PostSortType {
return type ? (type as PostSortType) : fallback;
}
type CommunityPathProps = { name: string };
@ -215,6 +218,7 @@ export class Community extends Component<CommunityRouteProps, State> {
super(props, context);
this.handleSortChange = this.handleSortChange.bind(this);
this.handleCommentSortChange = this.handleCommentSortChange.bind(this);
this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.handlePageNext = this.handlePageNext.bind(this);
this.handlePagePrev = this.handlePagePrev.bind(this);
@ -485,7 +489,6 @@ export class Community extends Component<CommunityRouteProps, State> {
return (
<PostListings
posts={this.state.postsRes.data.posts}
removeDuplicates
enableDownvotes={enableDownvotes(siteRes)}
voteDisplayMode={voteDisplayMode(siteRes)}
enableNsfw={enableNsfw(siteRes)}
@ -629,7 +632,14 @@ export class Community extends Component<CommunityRouteProps, State> {
</span>
)}
<span className="me-2">
<SortSelect sort={sort} onChange={this.handleSortChange} />
{this.props.dataType === DataType.Post ? (
<SortSelect sort={sort} onChange={this.handleSortChange} />
) : (
<CommentSortSelect
sort={postToCommentSortType(sort)}
onChange={this.handleCommentSortChange}
/>
)}
</span>
{communityRss && (
<>
@ -655,8 +665,18 @@ export class Community extends Component<CommunityRouteProps, State> {
this.updateUrl({ pageCursor: nextPage });
}
handleSortChange(sort: SortType) {
this.updateUrl({ sort, pageCursor: undefined });
handleSortChange(sort: PostSortType) {
this.updateUrl({
sort: sort,
pageCursor: undefined,
});
}
handleCommentSortChange(sort: CommentSortType) {
this.updateUrl({
sort: commentToPostSortType(sort),
pageCursor: undefined,
});
}
handleDataTypeChange(dataType: DataType) {

View file

@ -6,9 +6,9 @@ import classNames from "classnames";
import { Component } from "inferno";
import {
BannedPersonsResponse,
CreateCustomEmoji,
DeleteCustomEmoji,
EditCustomEmoji,
CreateOAuthProvider,
DeleteOAuthProvider,
EditOAuthProvider,
EditSite,
GetFederatedInstancesResponse,
GetSiteResponse,
@ -17,7 +17,6 @@ import {
PersonView,
} from "lemmy-js-client";
import { InitialFetchRequest } from "../../interfaces";
import { removeFromEmojiDataModel, updateEmojiDataModel } from "../../markdown";
import { FirstLoadService, I18NextService } from "../../services";
import {
EMPTY_REQUEST,
@ -42,7 +41,8 @@ import { MediaUploads } from "../common/media-uploads";
import { Paginator } from "../common/paginator";
import { snapToTop } from "@utils/browser";
import { isBrowser } from "@utils/browser";
import ConfirmationModal from "../common/confirmation-modal";
import ConfirmationModal from "../common/modal/confirmation-modal";
import OAuthProvidersTab from "./oauth/oauth-providers-tab";
type AdminSettingsData = RouteDataResponse<{
bannedRes: BannedPersonsResponse;
@ -104,13 +104,13 @@ export class AdminSettings extends Component<
super(props, context);
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.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
if (FirstLoadService.isFirstLoad) {
@ -249,11 +249,7 @@ export class AdminSettings extends Component<
id="taglines-tab-pane"
>
<div className="row">
<TaglineForm
taglines={this.state.siteRes.taglines}
onSaveSite={this.handleEditSite}
loading={this.state.loading}
/>
<TaglineForm />
</div>
</div>
),
@ -270,11 +266,7 @@ export class AdminSettings extends Component<
id="emojis-tab-pane"
>
<div className="row">
<EmojiForm
onCreate={this.handleCreateEmoji}
onDelete={this.handleDeleteEmoji}
onEdit={this.handleEditEmoji}
/>
<EmojiForm />
</div>
</div>
),
@ -294,6 +286,28 @@ export class AdminSettings extends Component<
</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>
@ -431,7 +445,6 @@ export class AdminSettings extends Component<
this.setState(s => {
s.siteRes.site_view = editRes.data.site_view;
// TODO: Where to get taglines from?
s.siteRes.taglines = editRes.data.taglines;
return s;
});
toast(I18NextService.i18n.t("site_saved"));
@ -464,30 +477,71 @@ export class AdminSettings extends Component<
}
}
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) {
this.setState({ uploadsPage: val });
snapToTop();
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 });
}
}

View file

@ -1,79 +1,81 @@
import { setIsoData } from "@utils/app";
import { capitalizeFirstLetter } from "@utils/helpers";
import { Component, linkEvent } from "inferno";
import {
CreateCustomEmoji,
DeleteCustomEmoji,
EditCustomEmoji,
GetSiteResponse,
} from "lemmy-js-client";
import { customEmojisLookup } from "../../markdown";
import { CustomEmojiView } from "lemmy-js-client";
import { emojiMartCategories, EmojiMartCategory } from "../../markdown";
import { HttpService, I18NextService } from "../../services";
import { pictrsDeleteToast, toast } from "../../toast";
import { EmojiMart } from "../common/emoji-mart";
import { Icon, Spinner } from "../common/icon";
import { Paginator } from "../common/paginator";
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 {
onEdit(form: EditCustomEmoji): void;
onCreate(form: CreateCustomEmoji): void;
onDelete(form: DeleteCustomEmoji): void;
interface EditableEmoji {
change?: "update" | "delete" | "create";
emoji: CustomEmojiView;
loading?: boolean;
}
function markForUpdate(editable: EditableEmoji) {
if (editable.change !== "create") {
editable.change = "update";
}
}
interface EmojiFormState {
siteRes: GetSiteResponse;
customEmojis: CustomEmojiViewForm[];
page: number;
}
interface CustomEmojiViewForm {
id: number;
category: string;
shortcode: string;
image_url: string;
alt_text: string;
keywords: string;
changed: boolean;
emojis: EditableEmoji[]; // Emojis for the current page
allEmojis: CustomEmojiView[]; // All emojis for emoji lookup across pages
emojiMartCustom: EmojiMartCategory[];
emojiMartKey: number;
page: number;
loading: boolean;
}
@tippyMixin
export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
private isoData = setIsoData(this.context);
export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
private itemsPerPage = 15;
private emptyState: EmojiFormState = {
siteRes: this.isoData.site_res,
customEmojis: this.isoData.site_res.custom_emojis.map((x, index) => ({
id: x.custom_emoji.id,
category: x.custom_emoji.category,
shortcode: x.custom_emoji.shortcode,
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,
})),
private needsRefetch = true;
state: EmojiFormState = {
emojis: [],
allEmojis: [],
emojiMartCustom: [],
emojiMartKey: 1,
loading: false,
page: 1,
};
state: EmojiFormState;
private scrollRef: any = {};
constructor(props: any, context: any) {
super(props, context);
this.state = this.emptyState;
this.handlePageChange = this.handlePageChange.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() {
return (
<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>
{customEmojisLookup.size > 0 && (
{this.state.emojiMartCustom.length > 0 && (
<div>
<EmojiMart
key={this.state.emojiMartKey}
onEmojiClick={this.handleEmojiClick}
pickerOptions={this.configurePicker()}
></EmojiMart>
@ -87,6 +89,10 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
<thead className="pointer">
<tr>
<th>{I18NextService.i18n.t("column_emoji")}</th>
<th
className="text-right"
// Upload button
/>
<th className="text-right">
{I18NextService.i18n.t("column_shortcode")}
</th>
@ -102,20 +108,15 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
<th className="text-right d-lg-table-cell">
{I18NextService.i18n.t("column_keywords")}
</th>
<th></th>
<th style="width:121px"></th>
</tr>
</thead>
<tbody>
{this.state.customEmojis
.slice(
Number((this.state.page - 1) * this.itemsPerPage),
Number(
(this.state.page - 1) * this.itemsPerPage +
this.itemsPerPage,
),
)
.map((cv, index) => (
<tr key={index} ref={e => (this.scrollRef[cv.shortcode] = e)}>
{this.state.emojis.map((editable: EditableEmoji, index) => {
const cv = editable.emoji.custom_emoji;
return (
<tr key={index}>
<td style="text-align:center;">
{cv.image_url.length > 0 && (
<img
@ -124,7 +125,9 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
alt={cv.alt_text}
/>
)}
{cv.image_url.length === 0 && (
</td>
<td>
{
<label
// TODO: Fix this linting violation
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
@ -150,7 +153,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
)}
/>
</label>
)}
}
</td>
<td className="text-right">
<input
@ -167,6 +170,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
</td>
<td className="text-right">
<input
ref={e => (this.scrollRef[cv.shortcode] = e)}
type="text"
placeholder="Category"
className="form-control"
@ -206,31 +210,54 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
type="text"
placeholder="Keywords"
className="form-control"
value={cv.keywords}
value={editable.emoji.keywords
.map(k => k.keyword)
.join(" ")}
onInput={linkEvent(
{ form: this, index: index },
this.handleEmojiKeywordChange,
)}
/>
</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>
<div>
<span title={this.getEditTooltip(cv)}>
<div class="row flex-nowrap g-0">
<span class="col" title={this.getEditTooltip(editable)}>
<button
className={
(this.canEdit(cv)
? "text-success "
: "text-muted ") + "btn btn-link btn-animate"
}
className={classNames("btn btn-link btn-animate", {
"text-success": this.canSave(editable),
})}
onClick={linkEvent(
{ i: this, cv: cv },
this.handleEditEmojiClick,
{ i: this, cv: editable },
this.handleSaveEmojiClick,
)}
data-tippy-content={I18NextService.i18n.t("save")}
aria-label={I18NextService.i18n.t("save")}
disabled={!this.canEdit(cv)}
disabled={!this.canSave(editable)}
>
{cv.loading ? (
{editable.loading ? (
<Spinner />
) : (
capitalizeFirstLetter(
@ -240,14 +267,14 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
</button>
</span>
<button
className="btn btn-link btn-animate text-muted"
className="col btn btn-link btn-animate text-muted"
onClick={linkEvent(
{ i: this, index: index, cv: cv },
{ i: this, index: index, cv: editable },
this.handleDeleteEmojiClick,
)}
data-tippy-content={I18NextService.i18n.t("delete")}
aria-label={I18NextService.i18n.t("delete")}
disabled={cv.loading}
disabled={editable.loading}
title={I18NextService.i18n.t("delete")}
>
<Icon
@ -255,10 +282,28 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
classes="icon-inline text-danger"
/>
</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>
</td>
</tr>
))}
);
})}
</tbody>
</table>
<br />
@ -273,43 +318,91 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
page={this.state.page}
onChange={this.handlePageChange}
nextDisabled={false}
disabled={this.hasPendingChanges()}
/>
</div>
</div>
);
}
canEdit(cv: CustomEmojiViewForm) {
const noEmptyFields =
cv.alt_text.length > 0 &&
cv.category.length > 0 &&
cv.image_url.length > 0 &&
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;
canSave(cv: EditableEmoji) {
const requiredFields =
cv.emoji.custom_emoji.image_url.length > 0 &&
cv.emoji.custom_emoji.shortcode.length > 0;
return requiredFields && !cv.loading;
}
getEditTooltip(cv: CustomEmojiViewForm) {
if (this.canEdit(cv)) return I18NextService.i18n.t("save");
getEditTooltip(cv: EditableEmoji) {
if (this.canSave(cv)) return I18NextService.i18n.t("save");
else return I18NextService.i18n.t("custom_emoji_save_validation");
}
handlePageChange(page: number) {
this.setState({ page: page });
async handlePageChange(page: number) {
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) {
const view = customEmojisLookup.get(e.id);
if (view) {
const page = this.state.customEmojis.find(
x => x.id === view.custom_emoji.id,
)?.page;
if (page) {
this.setState({ page: page });
this.scrollRef[view.custom_emoji.shortcode].scrollIntoView();
async handleEmojiClick(e: any) {
const emojiIndex = this.state.allEmojis.findIndex(
x => x.custom_emoji.shortcode === e.id,
);
if (emojiIndex >= 0) {
const { shortcode } = this.state.allEmojis[emojiIndex].custom_emoji;
const page = Math.floor(emojiIndex / this.itemsPerPage) + 1;
if (page !== this.state.page) {
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 },
event: any,
) {
const custom_emojis = [...props.form.state.customEmojis];
const pagedIndex =
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
const item = {
...props.form.state.customEmojis[pagedIndex],
category: event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
const editable: EditableEmoji = props.form.state.emojis[props.index];
props.form.setState(() => {
markForUpdate(editable);
editable.emoji.custom_emoji.category = event.target.value;
});
}
handleEmojiShortCodeChange(
props: { form: EmojiForm; index: number },
event: any,
) {
const custom_emojis = [...props.form.state.customEmojis];
const pagedIndex =
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
const item = {
...props.form.state.customEmojis[pagedIndex],
shortcode: event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
const editable: EditableEmoji = props.form.state.emojis[props.index];
props.form.setState(() => {
markForUpdate(editable);
editable.emoji.custom_emoji.shortcode = event.target.value;
});
}
handleEmojiImageUrlChange(
@ -354,28 +437,11 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
}: { form: EmojiForm; index: number; overrideValue: string | null },
event: any,
) {
form.setState(prevState => {
const custom_emojis = [...form.state.customEmojis];
const pagedIndex = (form.state.page - 1) * form.itemsPerPage + index;
const item = {
...form.state.customEmojis[pagedIndex],
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,
),
};
const editable: EditableEmoji = form.state.emojis[index];
form.setState(() => {
markForUpdate(editable);
editable.emoji.custom_emoji.image_url =
overrideValue ?? event.target.value;
});
}
@ -383,97 +449,117 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
props: { form: EmojiForm; index: number },
event: any,
) {
const custom_emojis = [...props.form.state.customEmojis];
const pagedIndex =
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
const item = {
...props.form.state.customEmojis[pagedIndex],
alt_text: event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
const editable: EditableEmoji = props.form.state.emojis[props.index];
props.form.setState(() => {
markForUpdate(editable);
editable.emoji.custom_emoji.alt_text = event.target.value;
});
}
handleEmojiKeywordChange(
props: { form: EmojiForm; index: number },
event: any,
) {
const custom_emojis = [...props.form.state.customEmojis];
const pagedIndex =
(props.form.state.page - 1) * props.form.itemsPerPage + props.index;
const item = {
...props.form.state.customEmojis[pagedIndex],
keywords: event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
const editable: EditableEmoji = props.form.state.emojis[props.index];
props.form.setState(() => {
markForUpdate(editable);
editable.emoji.keywords = event.target.value
.split(" ")
.map((x: string) => ({ id: -1, keyword: x }));
});
}
handleDeleteEmojiClick(d: {
i: EmojiForm;
index: number;
cv: CustomEmojiViewForm;
cv: EditableEmoji;
}) {
const pagedIndex = (d.i.state.page - 1) * d.i.itemsPerPage + d.index;
if (d.cv.id !== 0) {
d.i.props.onDelete({
id: d.cv.id,
});
if (d.cv.change === "create") {
// This drops the entry immediately, other deletes have to be saved.
d.i.setState(prev => ({
emojis: prev.emojis.filter(x => x !== d.cv),
}));
} else {
const custom_emojis = [...d.i.state.customEmojis];
custom_emojis.splice(Number(pagedIndex), 1);
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,
d.i.setState(() => {
d.cv.change = "delete";
});
}
}
handleAddEmojiClick(form: EmojiForm, event: any) {
async handleSaveEmojiClick(d: { i: EmojiForm; cv: EditableEmoji }) {
d.i.needsRefetch = true;
const editable = d.cv;
if (editable.change === "update") {
const resp = await HttpService.client.editCustomEmoji({
...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;
});
}
} 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 {
emojis: d.i.state.emojis.filter(x => x !== d.cv),
};
});
} 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(prevState => {
const page =
1 + Math.floor(prevState.customEmojis.length / form.itemsPerPage);
const item: CustomEmojiViewForm = {
id: 0,
shortcode: "",
alt_text: "",
category: "",
image_url: "",
keywords: "",
changed: false,
page: page,
loading: false,
};
return {
...prevState,
customEmojis: [...prevState.customEmojis, item],
page,
};
form.setState(prev => {
prev.emojis.push({
emoji: {
custom_emoji: {
id: -1,
published: "",
category: "",
shortcode: "",
image_url: "",
alt_text: "",
},
keywords: [],
},
change: "create",
});
});
}
@ -489,14 +575,15 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
file = event;
}
form.setState(prevState => ({
...prevState,
customEmojis: prevState.customEmojis.map((cv, i) =>
i === index ? { ...cv, loading: true } : cv,
),
}));
const editable = form.state.emojis[index];
form.setState(() => {
editable.loading = true;
});
HttpService.client.uploadImage({ image: file }).then(res => {
form.setState(() => {
editable.loading = false;
});
if (res.state === "success") {
if (res.data.msg === "ok") {
pictrsDeleteToast(file.name, res.data.delete_url as string);
@ -517,10 +604,20 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
}
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 {
data: { categories: [], emojis: [], aliases: [] },
maxFrequentRows: 0,
dynamicWidth: true,
custom,
};
}
}

View file

@ -1,5 +1,6 @@
import {
commentsToFlatNodes,
commentToPostSortType,
editComment,
editPost,
editWith,
@ -16,12 +17,9 @@ import {
import {
getQueryParams,
getQueryString,
getRandomFromList,
resourcesSettled,
bareRoutePush,
} from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin";
import { canCreateCommunity } from "@utils/roles";
import type { QueryParams, StringBoolean } from "@utils/types";
import { RouteDataResponse } from "@utils/types";
import { NoOptionI18nKeys } from "i18next";
@ -56,8 +54,6 @@ import {
GetSiteResponse,
HidePost,
LemmyHttp,
ListCommunities,
ListCommunitiesResponse,
ListingType,
LockPost,
MarkCommentReplyAsRead,
@ -71,11 +67,12 @@ import {
RemovePost,
SaveComment,
SavePost,
SortType,
PostSortType,
SuccessResponse,
TransferCommunity,
CommentSortType,
} from "lemmy-js-client";
import { fetchLimit, relTags, trendingFetchLimit } from "../../config";
import { fetchLimit, relTags } from "../../config";
import {
CommentViewType,
DataType,
@ -106,19 +103,17 @@ import { getHttpBaseInternal } from "../../utils/env";
import {
CommentsLoadingSkeleton,
PostsLoadingSkeleton,
TrendingCommunitiesLoadingSkeleton,
} from "../common/loading-skeleton";
import { RouteComponentProps } from "inferno-router/dist/Route";
import { IRoutePropsWithFetch } from "../../routes";
import PostHiddenSelect from "../common/post-hidden-select";
import { isBrowser, snapToTop } from "@utils/browser";
import { CommentSortSelect } from "../common/comment-sort-select";
interface HomeState {
postsRes: RequestState<GetPostsResponse>;
commentsRes: RequestState<GetCommentsResponse>;
trendingCommunitiesRes: RequestState<ListCommunitiesResponse>;
showSubscribedMobile: boolean;
showTrendingMobile: boolean;
showSidebarMobile: boolean;
subscribedCollapsed: boolean;
tagline?: string;
@ -129,7 +124,7 @@ interface HomeState {
interface HomeProps {
listingType?: ListingType;
dataType: DataType;
sort: SortType;
sort: PostSortType;
pageCursor?: PaginationCursor;
showHidden?: StringBoolean;
}
@ -137,10 +132,9 @@ interface HomeProps {
type HomeData = RouteDataResponse<{
postsRes: GetPostsResponse;
commentsRes: GetCommentsResponse;
trendingCommunitiesRes: ListCommunitiesResponse;
}>;
function getRss(listingType: ListingType, sort: SortType) {
function getRss(listingType: ListingType, sort: PostSortType) {
let rss: string | undefined = undefined;
const queryString = getQueryString({ sort });
@ -185,13 +179,13 @@ function getListingTypeFromQuery(
function getSortTypeFromQuery(
type: string | undefined,
fallback: SortType,
): SortType {
return type ? (type as SortType) : fallback;
fallback: PostSortType,
): PostSortType {
return type ? (type as PostSortType) : fallback;
}
type Fallbacks = {
sort: SortType;
sort: PostSortType;
listingType: ListingType;
};
@ -212,7 +206,8 @@ export function getHomeQueryParams(
},
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:
local_user?.default_listing_type ??
local_site.default_post_listing_type,
@ -238,18 +233,6 @@ const MobileButton = ({
</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 HomeRouteProps = RouteComponentProps<HomePathProps> & HomeProps;
export type HomeFetchConfig = IRoutePropsWithFetch<
@ -265,10 +248,8 @@ export class Home extends Component<HomeRouteProps, HomeState> {
state: HomeState = {
postsRes: EMPTY_REQUEST,
commentsRes: EMPTY_REQUEST,
trendingCommunitiesRes: EMPTY_REQUEST,
siteRes: this.isoData.site_res,
showSubscribedMobile: false,
showTrendingMobile: false,
showSidebarMobile: false,
subscribedCollapsed: false,
isIsomorphic: false,
@ -276,7 +257,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
loadingSettled(): boolean {
return resourcesSettled([
this.state.trendingCommunitiesRes,
this.props.dataType === DataType.Post
? this.state.postsRes
: this.state.commentsRes,
@ -287,6 +267,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
super(props, context);
this.handleSortChange = this.handleSortChange.bind(this);
this.handleCommentSortChange = this.handleCommentSortChange.bind(this);
this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.handleShowHiddenChange = this.handleShowHiddenChange.bind(this);
@ -324,21 +305,17 @@ export class Home extends Component<HomeRouteProps, HomeState> {
// Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) {
const { trendingCommunitiesRes, commentsRes, postsRes } =
this.isoData.routeData;
const { commentsRes, postsRes } = this.isoData.routeData;
this.state = {
...this.state,
trendingCommunitiesRes,
commentsRes,
postsRes,
isIsomorphic: true,
};
}
this.state.tagline = getRandomFromList(
this.state?.siteRes?.taglines ?? [],
)?.content;
this.state.tagline = this.state?.siteRes?.tagline?.content;
}
async componentWillMount() {
@ -349,10 +326,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
)) &&
isBrowser()
) {
await Promise.all([
this.fetchTrendingCommunities(),
this.fetchData(this.props),
]);
await this.fetchData(this.props);
}
}
@ -360,10 +334,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
nextProps: HomeRouteProps & { children?: InfernoNode },
) {
this.fetchData(nextProps);
if (bareRoutePush(this.props, nextProps)) {
this.fetchTrendingCommunities();
}
}
static async fetchInitialData({
@ -401,24 +371,12 @@ export class Home extends Component<HomeRouteProps, HomeState> {
commentsFetch = client.getComments(getCommentsForm);
}
const trendingCommunitiesForm: ListCommunities = {
type_: "Local",
sort: "Hot",
limit: trendingFetchLimit,
};
const trendingCommunitiesFetch = client.listCommunities(
trendingCommunitiesForm,
);
const [postsRes, commentsRes, trendingCommunitiesRes] = await Promise.all([
const [postsRes, commentsRes] = await Promise.all([
postsFetch,
commentsFetch,
trendingCommunitiesFetch,
]);
return {
trendingCommunitiesRes,
commentsRes,
postsRes,
};
@ -481,7 +439,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
admins,
},
showSubscribedMobile,
showTrendingMobile,
showSidebarMobile,
} = this.state;
@ -495,11 +452,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
onClick={linkEvent(this, this.handleShowSubscribedMobile)}
/>
)}
<MobileButton
textKey="trending"
show={showTrendingMobile}
onClick={linkEvent(this, this.handleShowTrendingMobile)}
/>
<MobileButton
textKey="sidebar"
show={showSidebarMobile}
@ -514,11 +466,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
isMobile={true}
/>
)}
{showTrendingMobile && (
<div className="card border-secondary mb-3">
{this.trendingCommunities()}
</div>
)}
{showSubscribedMobile && (
<div className="card border-secondary mb-3">
{this.subscribedCommunities(true)}
@ -539,9 +486,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
return (
<div id="sidebarContainer">
<section id="sidebarMain" className="card border-secondary mb-3">
{this.trendingCommunities()}
</section>
<SiteSidebar
site={site}
admins={admins}
@ -562,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) {
const { subscribedCollapsed } = this.state;
@ -829,7 +728,14 @@ export class Home extends Component<HomeRouteProps, HomeState> {
/>
</div>
<div className="col-auto">
<SortSelect sort={sort} onChange={this.handleSortChange} />
{this.props.dataType === DataType.Post ? (
<SortSelect sort={sort} onChange={this.handleSortChange} />
) : (
<CommentSortSelect
sort={postToCommentSortType(sort)}
onChange={this.handleCommentSortChange}
/>
)}
</div>
<div className="col-auto ps-0">
{getRss(
@ -842,17 +748,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
);
}
async fetchTrendingCommunities() {
this.setState({ trendingCommunitiesRes: LOADING_REQUEST });
this.setState({
trendingCommunitiesRes: await HttpService.client.listCommunities({
type_: "Local",
sort: "Hot",
limit: trendingFetchLimit,
}),
});
}
fetchDataToken?: symbol;
async fetchData({
dataType,
@ -893,10 +788,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
i.setState({ showSubscribedMobile: !i.state.showSubscribedMobile });
}
handleShowTrendingMobile(i: Home) {
i.setState({ showTrendingMobile: !i.state.showTrendingMobile });
}
handleShowSidebarMobile(i: Home) {
i.setState({ showSidebarMobile: !i.state.showSidebarMobile });
}
@ -917,10 +808,14 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.updateUrl({ pageCursor: nextPage });
}
handleSortChange(val: SortType) {
handleSortChange(val: PostSortType) {
this.updateUrl({ sort: val, pageCursor: undefined });
}
handleCommentSortChange(val: CommentSortType) {
this.updateUrl({ sort: commentToPostSortType(val), pageCursor: undefined });
}
handleListingTypeChange(val: ListingType) {
this.updateUrl({ listingType: val, pageCursor: undefined });
}

View file

@ -3,7 +3,12 @@ import { isBrowser, refreshTheme } from "@utils/browser";
import { getQueryParams } from "@utils/helpers";
import { Component, linkEvent } from "inferno";
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 {
EMPTY_REQUEST,
@ -15,7 +20,7 @@ import { toast } from "../../toast";
import { HtmlTags } from "../common/html-tags";
import { Spinner } from "../common/icon";
import PasswordInput from "../common/password-input";
import TotpModal from "../common/totp-modal";
import TotpModal from "../common/modal/totp-modal";
import { UnreadCounterService } from "../../services";
import { RouteData } from "../../interfaces";
import { IRoutePropsWithFetch } from "../../routes";
@ -42,6 +47,7 @@ interface State {
};
siteRes: GetSiteResponse;
show2faModal: boolean;
showOAuthModal: boolean;
}
async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
@ -52,16 +58,21 @@ async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
if (site.state === "success") {
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();
}
const { prev } = i.props;
prev
? i.props.history.replace(prev)
: i.props.history.action === "PUSH"
? i.props.history.back()
: i.props.history.replace("/");
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();
}
@ -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) {
i.setState(
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,
show2faModal: false,
showOAuthModal: false,
};
constructor(props: any, context: any) {
super(props, context);
this.handleSubmitTotp = this.handleSubmitTotp.bind(this);
this.handleLoginWithProvider = this.handleLoginWithProvider.bind(this);
}
get documentTitle(): string {
@ -172,6 +224,35 @@ export class Login extends Component<LoginRouteProps, State> {
<div className="row">
<div className="col-12 col-lg-6 offset-lg-3">{this.loginForm()}</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>
);
}
@ -194,6 +275,13 @@ export class Login extends Component<LoginRouteProps, State> {
return successful;
}
async handleLoginWithProvider(params: { oauth_provider: OAuthProvider }) {
handleUseOAuthProvider({
oauth_provider: params.oauth_provider,
prev: this.props.prev ?? "/",
});
}
loginForm() {
return (
<div>

View 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();
}

View file

@ -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>
);
}

View 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,
});
}
}

View file

@ -3,7 +3,7 @@ import classNames from "classnames";
import { Component, FormEventHandler, linkEvent } from "inferno";
import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
import { I18NextService } from "../../services";
import { Spinner } from "../common/icon";
import { Icon, Spinner } from "../common/icon";
import Tabs from "../common/tabs";
const rateLimitTypes = [
@ -144,6 +144,10 @@ export default class RateLimitsForm extends Component<
<h1 className="h4 mb-4">
{I18NextService.i18n.t("rate_limit_header")}
</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={rateLimitTypes.map(rateLimitType => ({
key: rateLimitType,

View file

@ -1,6 +1,6 @@
import { setIsoData } from "@utils/app";
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 { Component, linkEvent } from "inferno";
import { T } from "inferno-i18next-dess";
@ -11,7 +11,7 @@ import {
LoginResponse,
SiteView,
} from "lemmy-js-client";
import { joinLemmyUrl } from "../../config";
import { joinLemmyUrl, validActorRegexPattern } from "../../config";
import { mdToHtml } from "../../markdown";
import { I18NextService, UserService } from "../../services";
import {
@ -26,6 +26,13 @@ import { Icon, Spinner } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea";
import PasswordInput from "../common/password-input";
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 {
registerRes: RequestState<LoginResponse>;
@ -45,11 +52,25 @@ interface State {
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
export class Signup extends Component<
RouteComponentProps<Record<string, never>>,
State
> {
export class Signup extends Component<SignupRouteProps, State> {
private isoData = setIsoData(this.context);
private audio?: HTMLAudioElement;
@ -132,6 +153,8 @@ export class Signup extends Component<
registerForm() {
const siteView = this.state.siteRes.site_view;
const oauth_provider = getOAuthProvider(this);
return (
<form
className="was-validated"
@ -166,63 +189,85 @@ export class Signup extends Component<
onInput={linkEvent(this, this.handleRegisterUsernameChange)}
required
minLength={3}
pattern="[a-zA-Z0-9_]+"
pattern={validActorRegexPattern}
title={I18NextService.i18n.t("community_reqs")}
/>
</div>
</div>
<div className="mb-3 row">
<label className="col-sm-2 col-form-label" htmlFor="register-email">
{I18NextService.i18n.t("email")}
</label>
<div className="col-sm-10">
<input
type="email"
id="register-email"
className="form-control"
placeholder={
siteView.local_site.require_email_verification
? I18NextService.i18n.t("required")
: I18NextService.i18n.t("optional")
}
value={this.state.form.email}
autoComplete="email"
onInput={linkEvent(this, this.handleRegisterEmailChange)}
required={siteView.local_site.require_email_verification}
minLength={3}
/>
{!siteView.local_site.require_email_verification &&
this.state.form.email &&
!validEmail(this.state.form.email) && (
<div 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")}
{!oauth_provider && (
<>
{
<div className="mb-3 row">
<label
className="col-sm-2 col-form-label"
htmlFor="register-email"
>
{I18NextService.i18n.t("email")}
</label>
<div className="col-sm-10">
<input
type="email"
id="register-email"
className="form-control"
placeholder={
siteView.local_site.require_email_verification
? I18NextService.i18n.t("required")
: I18NextService.i18n.t("optional")
}
value={this.state.form.email}
autoComplete="email"
onInput={linkEvent(this, this.handleRegisterEmailChange)}
required={siteView.local_site.require_email_verification}
minLength={3}
/>
{!siteView.local_site.require_email_verification &&
this.state.form.email &&
!validEmail(this.state.form.email) && (
<div
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")}
</div>
)}
</div>
)}
</div>
</div>
</div>
}
<div className="mb-3">
<PasswordInput
id="register-password"
value={this.state.form.password}
onInput={linkEvent(this, this.handleRegisterPasswordChange)}
showStrength
label={I18NextService.i18n.t("password")}
isNew
/>
</div>
{
<div className="mb-3">
<PasswordInput
id="register-password"
value={this.state.form.password}
onInput={linkEvent(this, this.handleRegisterPasswordChange)}
showStrength
label={I18NextService.i18n.t("password")}
isNew
/>
</div>
}
<div className="mb-3">
<PasswordInput
id="register-verify-password"
value={this.state.form.password_verify}
onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
label={I18NextService.i18n.t("verify_password")}
isNew
/>
</div>
{
<div className="mb-3">
<PasswordInput
id="register-verify-password"
value={this.state.form.password_verify}
onInput={linkEvent(
this,
this.handleRegisterPasswordVerifyChange,
)}
label={I18NextService.i18n.t("verify_password")}
isNew
/>
</div>
}
</>
)}
{siteView.local_site.registration_mode === "RequireApplication" && (
<>
@ -296,7 +341,12 @@ export class Signup extends Component<
{this.state.registerRes.state === "loading" ? (
<Spinner />
) : (
this.titleName(siteView)
[
this.titleName(siteView),
...(oauth_provider
? [`(${oauth_provider.display_name})`]
: []),
].join(" ")
)}
</button>
</div>
@ -389,6 +439,19 @@ export class Signup extends Component<
password_verify,
username,
} = 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) {
i.setState({ registerRes: LOADING_REQUEST });
@ -516,3 +579,9 @@ export class Signup extends Component<
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),
);
}

View file

@ -2,7 +2,6 @@ import { capitalizeFirstLetter, validInstanceTLD } from "@utils/helpers";
import {
Component,
InfernoKeyboardEvent,
InfernoMouseEvent,
InfernoNode,
linkEvent,
} from "inferno";
@ -64,7 +63,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
description: site.description,
enable_downvotes: ls.enable_downvotes,
registration_mode: ls.registration_mode,
enable_nsfw: ls.enable_nsfw,
oauth_registration: ls.oauth_registration,
community_creation_admin_only: ls.community_creation_admin_only,
icon: site.icon,
banner: site.banner,
@ -334,6 +333,25 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
</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="col-12">
<div className="form-check">
@ -783,6 +801,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
enable_downvotes: stateSiteForm.enable_downvotes,
application_question: stateSiteForm.application_question,
registration_mode: stateSiteForm.registration_mode,
oauth_registration: stateSiteForm.oauth_registration,
require_email_verification: stateSiteForm.require_email_verification,
private_instance: stateSiteForm.private_instance,
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));
}
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) {
this.setState(s => ((s.siteForm.application_question = val), s));
}
@ -933,6 +916,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
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) {
i.state.siteForm.community_creation_admin_only = event.target.checked;
i.setState(i.state);

View file

@ -1,49 +1,84 @@
import { capitalizeFirstLetter } from "@utils/helpers";
import { Component, InfernoMouseEvent, linkEvent } from "inferno";
import { EditSite, Tagline } from "lemmy-js-client";
import { I18NextService } from "../../services";
import { Tagline } from "lemmy-js-client";
import { HttpService, I18NextService } from "../../services";
import { Icon, Spinner } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea";
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 {
taglines: Array<Tagline>;
onSaveSite(form: EditSite): void;
loading: boolean;
interface EditableTagline {
change?: "update" | "delete" | "create";
editMode?: boolean;
tagline: Tagline;
}
function markForUpdate(editable: EditableTagline) {
if (editable.change !== "create") {
editable.change = "update";
}
}
interface TaglineFormState {
taglines: Array<string>;
editingRow?: number;
taglines: Array<EditableTagline>;
page: number;
loading: boolean;
}
@tippyMixin
export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
export class TaglineForm extends Component<
Record<never, never>,
TaglineFormState
> {
state: TaglineFormState = {
editingRow: undefined,
taglines: this.props.taglines.map(x => x.content),
taglines: [],
page: 1,
loading: false,
};
constructor(props: any, context: any) {
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() {
return (
<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>
<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">
<th></th>
<th style="width:60px"></th>
<th style="width:121px"></th>
</thead>
<tbody>
{this.state.taglines.map((cv, index) => (
<tr key={index}>
<td>
{this.state.editingRow === index && (
{cv.editMode ? (
<MarkdownTextArea
initialContent={cv}
initialContent={cv.tagline.content}
focus={true}
onContentChange={s =>
this.handleTaglineChange(this, index, s)
}
@ -51,8 +86,32 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
allLanguages={[]}
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 className="text-right">
<button
@ -99,65 +158,153 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
<button
onClick={linkEvent(this, this.handleSaveClick)}
className="btn btn-secondary me-2"
disabled={this.props.loading}
disabled={this.state.loading || !this.hasPendingChanges()}
>
{this.props.loading ? (
{this.state.loading ? (
<Spinner />
) : (
capitalizeFirstLetter(I18NextService.i18n.t("save"))
)}
</button>
{this.hasPendingChanges() && (
<button
onClick={linkEvent(this, this.handleCancelClick)}
className="btn btn-secondary me-2"
>
{I18NextService.i18n.t("cancel")}
</button>
)}
</div>
</div>
<div>
<Paginator
page={this.state.page}
onChange={this.handlePageChange}
nextDisabled={false}
disabled={this.hasPendingChanges()}
/>
</div>
</div>
</div>
);
}
handleTaglineChange(i: TaglineForm, index: number, val: string) {
if (i.state.taglines) {
i.setState(prev => ({
...prev,
taglines: prev.taglines.map((tl, i) => (i === index ? val : tl)),
}));
}
const editable = i.state.taglines[index];
i.setState(() => {
markForUpdate(editable);
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();
d.i.setState(prev => ({
...prev,
taglines: prev.taglines.filter((_, i) => i !== d.index),
editingRow: undefined,
}));
const editable = d.i.state.taglines[d.index];
if (editable.change === "create") {
// This drops the entry immediately, other deletes have to be saved.
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) {
event.preventDefault();
if (d.i.state.editingRow === d.index) {
d.i.setState({ editingRow: undefined });
} else {
d.i.setState({ editingRow: d.index });
}
}
async handleSaveClick(i: TaglineForm) {
i.props.onSaveSite({
taglines: i.state.taglines,
const editable = d.i.state.taglines[d.index];
d.i.setState(prev => {
prev.taglines
.filter(x => x !== editable)
.forEach(x => {
x.editMode = false;
});
editable.editMode = !editable.editMode;
});
}
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,
event: InfernoMouseEvent<HTMLButtonElement>,
) {
event.preventDefault();
const newTaglines = [...i.state.taglines];
newTaglines.push("");
i.setState({
taglines: newTaglines,
editingRow: newTaglines.length - 1,
i.setState(prev => {
prev.taglines.forEach(x => {
x.editMode = false;
});
prev.taglines.push({
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 });
}
}
}

View file

@ -907,8 +907,9 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
options={userSearchOptions}
loading={loadingUserSearch}
/>
{!this.isoData.site_res.site_view.local_site
.hide_modlog_mod_names && (
{(this.amAdminOrMod ||
!this.isoData.site_res.site_view.local_site
.hide_modlog_mod_names) && (
<Filter
filterType="mod"
onChange={this.handleModChange}
@ -1057,10 +1058,7 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
limit: fetchLimit,
type_: actionType,
other_person_id: userId,
mod_person_id: !this.isoData.site_res.site_view.local_site
.hide_modlog_mod_names
? modId
: undefined,
mod_person_id: modId,
comment_id: commentId,
post_id: postId,
});
@ -1090,19 +1088,15 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
static async fetchInitialData({
headers,
query: { page, userId, modId: modId_, actionType, commentId, postId },
query: { page, userId, modId, actionType, commentId, postId },
match: {
params: { communityId: urlCommunityId },
},
site,
}: InitialFetchRequest<ModlogPathProps, ModlogProps>): Promise<ModlogData> {
const client = wrapClient(
new LemmyHttp(getHttpBaseInternal(), { headers }),
);
const communityId = getIdFromString(urlCommunityId);
const modId = !site.site_view.local_site.hide_modlog_mod_names
? modId_
: undefined;
const modlogForm: GetModlog = {
page,

View file

@ -37,7 +37,7 @@ import {
RemovePost,
SaveComment,
SavePost,
SortType,
PostSortType,
TransferCommunity,
} from "lemmy-js-client";
import { CommentViewType, PersonDetailsView } from "../../interfaces";
@ -53,7 +53,7 @@ interface PersonDetailsProps {
siteLanguages: number[];
page: number;
limit: number;
sort: SortType;
sort: PostSortType;
enableDownvotes: boolean;
voteDisplayMode: LocalUserVoteDisplayMode;
enableNsfw: boolean;

View file

@ -20,7 +20,7 @@ import {
resourcesSettled,
bareRoutePush,
} from "@utils/helpers";
import { canMod } from "@utils/roles";
import { amAdmin, canMod } from "@utils/roles";
import type { QueryParams } from "@utils/types";
import { RouteDataResponse } from "@utils/types";
import classNames from "classnames";
@ -70,9 +70,10 @@ import {
RemovePost,
SaveComment,
SavePost,
SortType,
PostSortType,
SuccessResponse,
TransferCommunity,
RegistrationApplicationResponse,
} from "lemmy-js-client";
import { fetchLimit, relTags } from "../../config";
import { InitialFetchRequest, PersonDetailsView } from "../../interfaces";
@ -100,6 +101,7 @@ import { IRoutePropsWithFetch } from "../../routes";
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<{
personRes: GetPersonDetailsResponse;
@ -112,18 +114,20 @@ interface ProfileState {
// to render the start of the profile while the new details are loading.
personDetailsRes: RequestState<GetPersonDetailsResponse>;
uploadsRes: RequestState<ListMediaResponse>;
registrationRes: RequestState<RegistrationApplicationResponse>;
personBlocked: boolean;
banReason?: string;
banExpireDays?: number;
showBanDialog: boolean;
removeData: boolean;
removeOrRestoreData: boolean;
siteRes: GetSiteResponse;
isIsomorphic: boolean;
showRegistrationDialog: boolean;
}
interface ProfileProps {
view: PersonDetailsView;
sort: SortType;
sort: PostSortType;
page: number;
}
@ -138,8 +142,8 @@ export function getProfileQueryParams(source?: string): ProfileProps {
);
}
function getSortTypeFromQuery(sort?: string): SortType {
return sort ? (sort as SortType) : "New";
function getSortTypeFromQuery(sort?: string): PostSortType {
return sort ? (sort as PostSortType) : "New";
}
function getViewFromProps(view?: string): PersonDetailsView {
@ -178,7 +182,7 @@ function isPersonBlocked(personRes: RequestState<GetPersonDetailsResponse>) {
return (
(personRes.state === "success" &&
UserService.Instance.myUserInfo?.person_blocks.some(
({ target: { id } }) => id === personRes.data.person_view.person.id,
({ id }) => id === personRes.data.person_view.person.id,
)) ??
false
);
@ -202,8 +206,10 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
personBlocked: false,
siteRes: this.isoData.site_res,
showBanDialog: false,
removeData: false,
removeOrRestoreData: false,
isIsomorphic: false,
showRegistrationDialog: false,
registrationRes: EMPTY_REQUEST,
};
loadingSettled() {
@ -252,6 +258,8 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleFeaturePost = this.handleFeaturePost.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
if (FirstLoadService.isFirstLoad) {
@ -628,6 +636,8 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
personBlocked,
siteRes: { admins },
showBanDialog,
showRegistrationDialog,
registrationRes,
} = this.state;
return (
@ -671,15 +681,27 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
<div className="flex-grow-1 unselectable pointer mx-2"></div>
{!this.amCurrentUser && UserService.Instance.myUserInfo && (
<>
<a
className={`d-flex align-self-start btn btn-secondary me-2 ${
!pv.person.matrix_user_id && "invisible"
}`}
rel={relTags}
href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
>
{I18NextService.i18n.t("send_secure_message")}
</a>
{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
className={`d-flex align-self-start btn btn-secondary me-2`}
rel={relTags}
href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
>
{I18NextService.i18n.t("send_secure_message")}
</a>
)}
<Link
className={
"d-flex align-self-start btn btn-secondary me-2"
@ -740,6 +762,46 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
{capitalizeFirstLetter(I18NextService.i18n.t("unban"))}
</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>
{pv.person.bio && (
<div className="d-flex align-items-center mb-2">
@ -829,7 +891,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
className="form-check-input"
id="mod-ban-remove-data"
type="checkbox"
checked={this.state.removeData}
checked={this.state.removeOrRestoreData}
onChange={linkEvent(this, this.handleModRemoveDataChange)}
/>
<label
@ -894,7 +956,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
this.updateUrl({ page });
}
handleSortChange(sort: SortType) {
handleSortChange(sort: PostSortType) {
this.updateUrl({ sort, page: 1 });
}
@ -918,16 +980,42 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
}
handleModRemoveDataChange(i: Profile, event: any) {
i.setState({ removeData: event.target.checked });
i.setState({ removeOrRestoreData: event.target.checked });
}
handleModBanSubmitCancel(i: Profile) {
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) {
event.preventDefault();
const { removeData, banReason, banExpireDays } = i.state;
const { banReason, banExpireDays } = i.state;
const personRes = i.state.personRes;
@ -937,13 +1025,13 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
// If its an unban, restore all their data
if (!ban) {
i.setState({ removeData: false });
i.setState({ removeOrRestoreData: true });
}
const res = await HttpService.client.banPerson({
person_id: person.id,
ban,
remove_data: removeData,
remove_or_restore_data: i.state.removeOrRestoreData,
reason: banReason,
expires: futureDaysToUnixTime(banExpireDays),
});

View file

@ -22,17 +22,17 @@ import {
BlockCommunityResponse,
BlockInstanceResponse,
BlockPersonResponse,
CommunityBlockView,
CommentSortType,
Community,
GenerateTotpSecretResponse,
GetFederatedInstancesResponse,
GetSiteResponse,
Instance,
InstanceBlockView,
LemmyHttp,
ListingType,
LoginResponse,
PersonBlockView,
SortType,
Person,
PostSortType,
SuccessResponse,
UpdateTotpResponse,
} from "lemmy-js-client";
@ -65,7 +65,7 @@ import Tabs from "../common/tabs";
import { CommunityLink } from "../community/community-link";
import { PersonListing } from "./person-listing";
import { InitialFetchRequest } from "../../interfaces";
import TotpModal from "../common/totp-modal";
import TotpModal from "../common/modal/totp-modal";
import { LoadingEllipses } from "../common/loading-ellipses";
import {
isBrowser,
@ -77,6 +77,7 @@ import { getHttpBaseInternal } from "../../utils/env";
import { IRoutePropsWithFetch } from "../../routes";
import { RouteComponentProps } from "inferno-router/dist/Route";
import { simpleScrollMixin } from "../mixins/scroll-mixin";
import { CommentSortSelect } from "../common/comment-sort-select";
type SettingsData = RouteDataResponse<{
instancesRes: GetFederatedInstancesResponse;
@ -95,7 +96,8 @@ interface SettingsState {
blur_nsfw?: boolean;
auto_expand?: boolean;
theme?: string;
default_sort_type?: SortType;
default_post_sort_type?: PostSortType;
default_comment_sort_type?: CommentSortType;
default_listing_type?: ListingType;
interface_language?: string;
avatar?: string;
@ -113,7 +115,6 @@ interface SettingsState {
bot_account?: boolean;
show_bot_accounts?: boolean;
show_read_posts?: boolean;
show_new_post_notifs?: boolean;
discussion_languages?: number[];
open_links_in_new_tab?: boolean;
};
@ -126,9 +127,9 @@ interface SettingsState {
delete_content?: boolean;
password?: string;
};
personBlocks: PersonBlockView[];
communityBlocks: CommunityBlockView[];
instanceBlocks: InstanceBlockView[];
personBlocks: Person[];
communityBlocks: Community[];
instanceBlocks: Instance[];
currentTab: string;
themeList: string[];
deleteAccountShowConfirm: boolean;
@ -250,7 +251,9 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
constructor(props: any, context: any) {
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.handleBioChange = this.handleBioChange.bind(this);
this.handleDiscussionLanguageChange =
@ -278,9 +281,9 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
local_user: {
show_nsfw,
blur_nsfw,
auto_expand,
theme,
default_sort_type,
default_post_sort_type,
default_comment_sort_type,
default_listing_type,
interface_language,
show_avatars,
@ -315,9 +318,9 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
...this.state.saveUserSettingsForm,
show_nsfw,
blur_nsfw,
auto_expand,
theme: theme ?? "browser",
default_sort_type,
default_post_sort_type,
default_comment_sort_type,
default_listing_type,
interface_language,
discussion_languages: mui.discussion_languages,
@ -516,6 +519,7 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
value={this.state.changePasswordForm.old_password}
onInput={linkEvent(this, this.handleOldPasswordChange)}
label={I18NextService.i18n.t("old_password")}
required={false}
/>
</div>
<div className="input-group mb-3">
@ -557,14 +561,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
<>
<h2 className="h5">{I18NextService.i18n.t("blocked_users")}</h2>
<ul className="list-unstyled mb-0">
{this.state.personBlocks.map(pb => (
<li key={pb.target.id}>
{this.state.personBlocks.map(p => (
<li key={p.id}>
<span>
<PersonListing person={pb.target} />
<PersonListing person={p} />
<button
className="btn btn-sm"
onClick={linkEvent(
{ ctx: this, recipientId: pb.target.id },
{ ctx: this, recipientId: p.id },
this.handleUnblockPerson,
)}
data-tippy-content={I18NextService.i18n.t("unblock_user")}
@ -601,14 +605,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
<>
<h2 className="h5">{I18NextService.i18n.t("blocked_communities")}</h2>
<ul className="list-unstyled mb-0">
{this.state.communityBlocks.map(cb => (
<li key={cb.community.id}>
{this.state.communityBlocks.map(c => (
<li key={c.id}>
<span>
<CommunityLink community={cb.community} />
<CommunityLink community={c} />
<button
className="btn btn-sm"
onClick={linkEvent(
{ ctx: this, communityId: cb.community.id },
{ ctx: this, communityId: c.id },
this.handleUnblockCommunity,
)}
data-tippy-content={I18NextService.i18n.t(
@ -646,14 +650,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
<>
<h2 className="h5">{I18NextService.i18n.t("blocked_instances")}</h2>
<ul className="list-unstyled mb-0">
{this.state.instanceBlocks.map(ib => (
<li key={ib.instance.id}>
{this.state.instanceBlocks.map(i => (
<li key={i.id}>
<span>
{ib.instance.domain}
{i.domain}
<button
className="btn btn-sm"
onClick={linkEvent(
{ ctx: this, instanceId: ib.instance.id },
{ ctx: this, instanceId: i.id },
this.handleUnblockInstance,
)}
data-tippy-content={I18NextService.i18n.t("unblock_instance")}
@ -907,14 +911,29 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
</form>
<form className="mb-3 row">
<label className="col-sm-3 col-form-label">
{I18NextService.i18n.t("sort_type")}
{I18NextService.i18n.t("post_sort_type")}
</label>
<div className="col-sm-9">
<SortSelect
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>
</form>
@ -1093,23 +1112,6 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
</label>
</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="form-check">
<input
@ -1367,7 +1369,7 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
instance =>
instance.domain.toLowerCase().includes(text.toLowerCase()) &&
!this.state.instanceBlocks.some(
blockedInstance => blockedInstance.instance.id === instance.id,
blockedInstance => blockedInstance.id === instance.id,
),
) ?? [];
}
@ -1496,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) {
i.setState(
s => (
@ -1607,8 +1601,16 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
);
}
handleSortTypeChange(val: SortType) {
this.setState(s => ((s.saveUserSettingsForm.default_sort_type = val), s));
handlePostSortTypeChange(val: PostSortType) {
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) {
@ -1708,12 +1710,12 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
const { new_password, new_password_verify, old_password } =
i.state.changePasswordForm;
if (new_password && old_password && new_password_verify) {
if (new_password && new_password_verify) {
i.setState({ changePasswordRes: LOADING_REQUEST });
const changePasswordRes = await HttpService.client.changePassword({
new_password,
new_password_verify,
old_password,
old_password: old_password || "",
});
if (changePasswordRes.state === "success") {
snapToTop();
@ -1770,14 +1772,13 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
local_user: {
show_nsfw,
blur_nsfw,
auto_expand,
theme,
default_sort_type,
default_post_sort_type,
default_comment_sort_type,
default_listing_type,
interface_language,
show_avatars,
show_bot_accounts,
show_scores,
show_read_posts,
send_notifications_to_email,
email,
@ -1810,18 +1811,17 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
display_name,
bio,
matrix_user_id,
auto_expand,
blur_nsfw,
bot_account,
default_listing_type,
default_sort_type,
default_post_sort_type,
default_comment_sort_type,
discussion_languages: siteRes.data.my_user?.discussion_languages,
email,
interface_language,
open_links_in_new_tab,
send_notifications_to_email,
show_read_posts,
show_scores,
},
}));
}

View file

@ -203,6 +203,9 @@ export class CreatePost extends Component<
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 }));
}
@ -234,6 +237,7 @@ export class CreatePost extends Component<
title,
nsfw,
url,
altText,
} = this.props;
const params: PostFormParams = {
@ -244,6 +248,7 @@ export class CreatePost extends Component<
custom_thumbnail: customThumbnailUrl,
language_id: languageId,
nsfw: nsfw === "true",
alt_text: altText,
};
return (
@ -278,6 +283,7 @@ export class CreatePost extends Component<
onUrlBlur={this.handleUrlBlur}
onThumbnailUrlBlur={this.handleThumbnailUrlBlur}
onNsfwChange={this.handleNsfwChange}
onAltTextBlur={this.handleAltTextBlur}
onCopySuggestedTitle={this.handleCopySuggestedTitle}
/>
</div>

View file

@ -27,7 +27,7 @@ import {
ghostArchiveUrl,
postMarkdownFieldCharacterLimit,
relTags,
trendingFetchLimit,
similarPostFetchLimit,
webArchiveUrl,
} from "../../config";
import { PostFormParams } from "../../interfaces";
@ -45,6 +45,14 @@ import { MarkdownTextArea } from "../common/markdown-textarea";
import { SearchableSelect } from "../common/searchable-select";
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;
@ -85,6 +93,8 @@ interface PostFormState {
honeypot?: string;
custom_thumbnail?: string;
alt_text?: string;
// Javascript treats this field as a string, that can't have timezone info.
scheduled_publish_time?: string;
};
suggestedPostsRes: RequestState<SearchResponse>;
metadataRes: RequestState<GetSiteMetadataResponse>;
@ -109,6 +119,7 @@ function handlePostSubmit(i: PostForm, event: any) {
const pForm = i.state.form;
const pv = i.props.post_view;
const scheduled_publish_time = getUnixTimeLemmy(pForm.scheduled_publish_time);
if (pv) {
i.props.onEdit?.(
@ -121,6 +132,7 @@ function handlePostSubmit(i: PostForm, event: any) {
language_id: pForm.language_id,
custom_thumbnail: pForm.custom_thumbnail,
alt_text: pForm.alt_text,
scheduled_publish_time,
},
() => {
i.setState({ bypassNavWarning: true });
@ -138,6 +150,7 @@ function handlePostSubmit(i: PostForm, event: any) {
honeypot: pForm.honeypot,
custom_thumbnail: pForm.custom_thumbnail,
alt_text: pForm.alt_text,
scheduled_publish_time,
},
() => {
i.setState({ bypassNavWarning: true });
@ -199,6 +212,18 @@ function handlePostNsfwChange(i: PostForm, event: any) {
);
}
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) {
i.setState(s => ((s.form.honeypot = event.target.value), s));
}
@ -314,9 +339,10 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
this.updateUrl = this.updateUrl.bind(this);
const { post_view, selectedCommunityChoice, params } = this.props;
// Means its an edit
if (post_view) {
const unix = getUnixTime(post_view.post.scheduled_publish_time);
var scheduled_publish_time = unixTimeToLocalDateStr(unix);
this.state = {
...this.state,
form: {
@ -328,6 +354,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
language_id: post_view.post.language_id,
custom_thumbnail: post_view.post.thumbnail_url,
alt_text: post_view.post.alt_text,
scheduled_publish_time,
},
};
} else if (selectedCommunityChoice) {
@ -681,6 +708,23 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
</label>
</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
tabIndex={-1}
autoComplete="false"
@ -806,10 +850,25 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
async fetchPageTitle() {
const url = this.state.form.url;
if (url && validURL(url)) {
this.setState({ metadataRes: LOADING_REQUEST });
this.setState({
metadataRes: await HttpService.client.getSiteMetadata({ 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: await HttpService.client.getSiteMetadata({ url }),
});
}
}
}
@ -825,7 +884,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
listing_type: "All",
community_id: this.state.form.community_id,
page: 1,
limit: trendingFetchLimit,
limit: similarPostFetchLimit,
}),
});
}

View file

@ -1,12 +1,13 @@
import { myAuth, setIsoData } from "@utils/app";
import { canShare, share } from "@utils/browser";
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 { canAdmin, canMod } from "@utils/roles";
import classNames from "classnames";
import { Component, linkEvent } from "inferno";
import { Link } from "inferno-router";
import { T } from "inferno-i18next-dess";
import {
AddAdmin,
AddModToCommunity,
@ -33,7 +34,7 @@ import {
SavePost,
TransferCommunity,
} from "lemmy-js-client";
import { relTags } from "../../config";
import { relTags, torrentHelpUrl } from "../../config";
import { IsoDataOptionalSite, VoteContentType } from "../../interfaces";
import { mdToHtml, mdToHtmlInline } from "../../markdown";
import { I18NextService, UserService } from "../../services";
@ -47,11 +48,14 @@ import { CommunityLink } from "../community/community-link";
import { PersonListing } from "../person/person-listing";
import { MetadataCard } from "./metadata-card";
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 { CrossPostParams } from "@utils/types";
import { RequestState } from "../../services/HttpService";
import { toast } from "../../toast";
import isMagnetLink, {
extractMagnetLinkDownloadName,
} from "@utils/media/is-magnet-link";
type PostListingState = {
showEdit: boolean;
@ -144,10 +148,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
UserService.Instance.myUserInfo &&
!this.isoData.showAdultConsentModal
) {
const { auto_expand, blur_nsfw } =
UserService.Instance.myUserInfo.local_user_view.local_user;
const blur_nsfw =
UserService.Instance.myUserInfo.local_user_view.local_user.blur_nsfw;
this.setState({
imageExpanded: auto_expand && !(blur_nsfw && this.postView.post.nsfw),
imageExpanded: !(blur_nsfw && this.postView.post.nsfw),
});
}
@ -176,9 +180,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<>
{this.listing()}
{this.state.imageExpanded && !this.props.hideImage && this.img}
{this.showBody &&
post.url &&
isMagnetLink(post.url) &&
this.torrentHelp()}
{this.showBody && post.url && post.embed_title && (
<MetadataCard post={post} />
)}
{this.showBody && this.videoBlock}
{this.showBody && this.body()}
</>
) : (
@ -217,37 +226,69 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
);
}
get img() {
const { post } = this.postView;
const { url } = post;
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>
);
}
if (this.isoData.showAdultConsentModal) {
return <></>;
}
get videoBlock() {
const post = this.postView.post;
const url = post.url;
// if direct video link or embedded video link
if (url && (isVideo(url) || post.embed_video_url)) {
if (url && isVideo(url)) {
return (
<div className="embed-responsive ratio ratio-16x9 mt-3">
<div className="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={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() {
if (this.isoData.showAdultConsentModal) {
return <></>;
}
if (this.imageSrc) {
// Use the full-size image for expands
const post = this.postView.post;
const url = post.url;
const thumbnail = post.thumbnail_url;
const imageSrc = url && isImage(url) ? url : thumbnail;
if (imageSrc) {
return (
<>
<div className="offset-sm-3 my-2 d-none d-sm-block">
<a href={this.imageSrc} className="d-inline-block">
<PictrsImage src={this.imageSrc} alt={post.alt_text} />
<a href={imageSrc} className="d-inline-block">
<PictrsImage src={imageSrc} alt={post.alt_text} />
</a>
</div>
<div className="my-2 d-block d-sm-none">
@ -256,7 +297,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
className="p-0 border-0 bg-transparent d-inline-block"
onClick={linkEvent(this, this.handleImageExpandClick)}
>
<PictrsImage src={this.imageSrc} alt={post.alt_text} />
<PictrsImage src={imageSrc} alt={post.alt_text} />
</button>
</div>
</>
@ -278,26 +319,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
);
}
get imageSrc(): string | undefined {
const post = this.postView.post;
const url = post.url;
const thumbnail = post.thumbnail_url;
if (thumbnail) {
return thumbnail;
} else if (url && isImage(url)) {
return url;
} else {
return undefined;
}
}
thumbnail() {
const post = this.postView.post;
const url = post.url;
const thumbnail = post.thumbnail_url;
if (!this.props.hideImage && url && isImage(url) && this.imageSrc) {
if (!this.props.hideImage && url && isImage(url) && thumbnail) {
return (
<button
type="button"
@ -306,20 +333,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onClick={linkEvent(this, this.handleImageExpandClick)}
aria-label={I18NextService.i18n.t("expand_here")}
>
{this.imgThumb(this.imageSrc)}
{this.imgThumb(thumbnail)}
<Icon
icon="image"
classes="d-block text-white position-absolute end-0 top-0 mini-overlay text-opacity-75 text-opacity-100-hover"
/>
</button>
);
} else if (
!this.props.hideImage &&
url &&
thumbnail &&
this.imageSrc &&
!isVideo(url)
) {
} else if (!this.props.hideImage && url && thumbnail && !isVideo(url)) {
return (
<a
className="thumbnail rounded overflow-hidden d-inline-block position-relative p-0 border-0"
@ -328,7 +349,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
title={url}
target={this.linkTarget}
>
{this.imgThumb(this.imageSrc)}
{this.imgThumb(thumbnail)}
<Icon
icon="external-link"
classes="d-block text-white position-absolute end-0 top-0 mini-overlay text-opacity-75 text-opacity-100-hover"
@ -396,7 +417,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
createdLine() {
const pv = this.postView;
return (
<div className="small mb-1 mb-md-0">
<PersonListing person={pv.creator} />
@ -422,6 +442,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
}
</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} />
</div>
);
@ -542,20 +569,31 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
const post = this.postView.post;
const url = post.url;
return (
<p className="small m-0">
{url && !(hostname(url) === getExternalHost()) && (
<a
className="fst-italic link-dark link-opacity-75 link-opacity-100-hover"
href={url}
title={url}
rel={relTags}
>
{hostname(url)}
</a>
)}
</p>
);
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 (
<p className="small m-0">
{url && !(hostname(url) === getExternalHost()) && (
<a
className="fst-italic link-dark link-opacity-75 link-opacity-100-hover"
href={url}
title={url}
rel={relTags}
>
{linkName}
</a>
)}
</p>
);
}
}
}
duplicatesLine() {
@ -878,7 +916,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
}
get crossPostParams(): CrossPostParams {
const { name, url } = this.postView.post;
const { name, url, alt_text, nsfw, language_id } = this.postView.post;
const crossPostParams: CrossPostParams = { name };
if (url) {
@ -890,6 +928,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
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;
}
@ -963,7 +1013,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
handleModBanFromCommunity({
daysUntilExpires,
reason,
shouldRemove,
shouldRemoveOrRestoreData,
}: BanUpdateForm) {
const {
creator: { id: person_id },
@ -974,7 +1024,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
// If its an unban, restore all their data
if (ban === false) {
shouldRemove = false;
shouldRemoveOrRestoreData = true;
}
const expires = futureDaysToUnixTime(daysUntilExpires);
@ -982,7 +1032,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
community_id,
person_id,
ban,
remove_data: shouldRemove,
remove_or_restore_data: shouldRemoveOrRestoreData,
reason,
expires,
});
@ -991,7 +1041,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
handleModBanFromSite({
daysUntilExpires,
reason,
shouldRemove,
shouldRemoveOrRestoreData,
}: BanUpdateForm) {
const {
creator: { id: person_id, banned },
@ -1000,14 +1050,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
// If its an unban, restore all their data
if (ban === false) {
shouldRemove = false;
shouldRemoveOrRestoreData = true;
}
const expires = futureDaysToUnixTime(daysUntilExpires);
return this.props.onBanPerson({
person_id,
ban,
remove_data: shouldRemove,
remove_or_restore_data: shouldRemoveOrRestoreData,
reason,
expires,
});

View file

@ -124,11 +124,12 @@ interface PostState {
lastCreatedCommentId?: CommentId;
}
const defaultCommentSort: CommentSortType = "Hot";
function getCommentSortTypeFromQuery(source?: string): CommentSortType {
function getCommentSortTypeFromQuery(
source: string | undefined,
fallback: CommentSortType,
): CommentSortType {
if (!source) {
return defaultCommentSort;
return fallback;
}
switch (source) {
case "Hot":
@ -138,14 +139,21 @@ function getCommentSortTypeFromQuery(source?: string): CommentSortType {
case "Controversial":
return source;
default:
return defaultCommentSort;
return fallback;
}
}
function getQueryStringFromCommentSortType(
sort: CommentSortType,
siteRes: GetSiteResponse,
): undefined | string {
if (sort === defaultCommentSort) {
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;
@ -185,14 +193,31 @@ interface PostProps {
view: CommentViewType;
scrollToComments: boolean;
}
export function getPostQueryParams(source: string | undefined): PostProps {
return getQueryParams<PostProps>(
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,
},
);
}
@ -325,7 +350,7 @@ export class Post extends Component<PostRouteProps, PostState> {
};
const query: QueryParams<PostProps> = {
sort: getQueryStringFromCommentSortType(sort),
sort: getQueryStringFromCommentSortType(sort, this.state.siteRes),
view: getQueryStringFromCommentView(view),
};

View file

@ -14,7 +14,7 @@ import { Icon, Spinner } from "../common/icon";
import { MomentTime } from "../common/moment-time";
import { PersonListing } from "../person/person-listing";
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";
interface PrivateMessageState {

View file

@ -18,6 +18,7 @@ import {
dedupByProperty,
getIdFromString,
getPageFromString,
getBoolFromString,
getQueryParams,
getQueryString,
numToSI,
@ -45,7 +46,7 @@ import {
Search as SearchForm,
SearchResponse,
SearchType,
SortType,
PostSortType,
} from "lemmy-js-client";
import { fetchLimit } from "../config";
import { CommentViewType, InitialFetchRequest } from "../interfaces";
@ -75,8 +76,9 @@ import { isBrowser } from "@utils/browser";
interface SearchProps {
q?: string;
type: SearchType;
sort: SortType;
sort: PostSortType;
listingType: ListingType;
titleOnly?: boolean;
communityId?: number;
creatorId?: number;
page: number;
@ -122,6 +124,7 @@ export function getSearchQueryParams(source?: string): SearchProps {
type: getSearchTypeFromQuery,
sort: getSortTypeFromQuery,
listingType: getListingTypeFromQuery,
titleOnly: getBoolFromString,
communityId: getIdFromString,
creatorId: getIdFromString,
page: getPageFromString,
@ -136,8 +139,8 @@ function getSearchTypeFromQuery(type_?: string): SearchType {
return type_ ? (type_ as SearchType) : defaultSearchType;
}
function getSortTypeFromQuery(sort?: string): SortType {
return sort ? (sort as SortType) : defaultSortType;
function getSortTypeFromQuery(sort?: string): PostSortType {
return sort ? (sort as PostSortType) : defaultSortType;
}
function getListingTypeFromQuery(listingType?: string): ListingType {
@ -283,6 +286,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
this.handleCommunityFilterChange =
this.handleCommunityFilterChange.bind(this);
this.handleCreatorFilterChange = this.handleCreatorFilterChange.bind(this);
this.handleTitleOnlyChange = this.handleTitleOnlyChange.bind(this);
// Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) {
@ -469,6 +473,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
type: searchType,
sort,
listingType: listing_type,
titleOnly: title_only,
communityId: community_id,
creatorId: creator_id,
page,
@ -514,6 +519,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
type_: searchType,
sort,
listing_type,
title_only,
page,
limit: fetchLimit,
};
@ -589,7 +595,6 @@ export class Search extends Component<SearchRouteProps, SearchState> {
case "Comments":
return this.comments;
case "Posts":
case "Url":
return this.posts;
case "Communities":
return this.communities;
@ -635,7 +640,8 @@ export class Search extends Component<SearchRouteProps, SearchState> {
}
get selects() {
const { type, listingType, sort, communityId, creatorId } = this.props;
const { type, listingType, titleOnly, sort, communityId, creatorId } =
this.props;
const {
communitySearchOptions,
creatorSearchOptions,
@ -673,6 +679,20 @@ export class Search extends Component<SearchRouteProps, SearchState> {
onChange={this.handleListingTypeChange}
/>
</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">
<SortSelect
sort={sort}
@ -1043,7 +1063,16 @@ export class Search extends Component<SearchRouteProps, SearchState> {
searchToken?: symbol;
async search(props: SearchRouteProps) {
const token = (this.searchToken = Symbol());
const { q, communityId, creatorId, type, sort, listingType, page } = props;
const {
q,
communityId,
creatorId,
type,
sort,
listingType,
titleOnly,
page,
} = props;
if (q) {
this.setState({ searchRes: LOADING_REQUEST });
@ -1054,6 +1083,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
type_: type,
sort,
listing_type: listingType,
title_only: titleOnly,
page,
limit: fetchLimit,
});
@ -1118,10 +1148,15 @@ export class Search extends Component<SearchRouteProps, SearchState> {
return this.searchInput.current?.value ?? this.props.q;
}
handleSortChange(sort: SortType) {
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) {
const type = event.target.value as SearchType;
@ -1170,7 +1205,16 @@ export class Search extends Component<SearchRouteProps, SearchState> {
}
async updateUrl(props: Partial<SearchProps>) {
const { q, type, listingType, sort, communityId, creatorId, page } = {
const {
q,
type,
listingType,
titleOnly,
sort,
communityId,
creatorId,
page,
} = {
...this.props,
...props,
};
@ -1179,6 +1223,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
q,
type: type,
listingType: listingType,
titleOnly: titleOnly?.toString(),
communityId: communityId?.toString(),
creatorId: creatorId?.toString(),
page: page?.toString(),

View file

@ -9,6 +9,7 @@ export const donateLemmyUrl = `${joinLemmyUrl}/donate`;
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 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 archiveTodayUrl = "https://archive.today";
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 postRefetchSeconds: number = 60 * 1000;
export const trendingFetchLimit = 6;
export const mentionDropdownFetchLimit = 10;
export const commentTreeMaxDepth = 8;
export const postMarkdownFieldCharacterLimit = 50000;
@ -25,6 +25,7 @@ export const maxUploadImages = 20;
export const concurrentImageUpload = 4;
export const updateUnreadCountsInterval = 30000;
export const fetchLimit = 20;
export const similarPostFetchLimit = 6;
export const relTags = "noopener nofollow";
export const emDash = "\u2014";
export const authCookieName = "jwt";
@ -49,3 +50,6 @@ export const instanceLinkRegex = new RegExp(
);
export const testHost = "0.0.0.0:8536";
export const validActorRegexPattern =
"^\\w+|[\\p{Script=Arabic}\\d_]+|[\\p{Script=Cyrillic}\\d_]+$";

View file

@ -1,5 +1,4 @@
import { communitySearch, personSearch } from "@utils/app";
import { isBrowser } from "@utils/browser";
import { debounce, groupBy } from "@utils/helpers";
import { CommunityTribute, PersonTribute } from "@utils/types";
import { Picker } from "emoji-mart";
@ -18,8 +17,10 @@ import markdown_it_highlightjs from "markdown-it-highlightjs/core";
import { Renderer, Token } from "markdown-it";
import { instanceLinkRegex, relTags } from "./config";
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();
@ -33,17 +34,13 @@ export const mdLimited: MarkdownIt = new MarkdownIt("zero").enable([
"strikethrough",
]);
export const customEmojis: EmojiMartCategory[] = [];
let customEmojis: EmojiMartCategory[] = [];
export let customEmojisLookup: Map<string, CustomEmojiView> = new Map<
string,
CustomEmojiView
>();
if (isBrowser()) {
Tribute = require("tributejs");
}
export function mdToHtml(text: string, rerender: () => void) {
return { __html: lazyHighlightjs.render(md, text, rerender) };
}
@ -209,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.
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 isEmoji = splitTitle[0] === "emoji";
let shortcode: string | undefined;
if (isEmoji) {
title = splitTitle[1];
shortcode = splitTitle[1];
}
const customEmoji = customEmojisLookup.get(title);
const isLocalEmoji = customEmoji !== undefined;
// customEmojisLookup is empty in SSR, CSR rerenders markdown anyway
const isLocalEmoji = shortcode && customEmojisLookup.has(shortcode);
if (!isLocalEmoji) {
const imgElement =
defaultImageRenderer?.(tokens, idx, options, env, self) ?? "";
@ -227,10 +227,8 @@ export function setupMarkdown() {
} else return "";
}
return `<img class="icon icon-emoji" src="${
customEmoji!.custom_emoji.image_url
}" title="${customEmoji!.custom_emoji.shortcode}" alt="${
customEmoji!.custom_emoji.alt_text
}"/>`;
url
}" title="${shortcode}" alt="${altText}"/>`;
};
md.renderer.rules.table_open = function () {
return '<table class="table">';
@ -252,11 +250,14 @@ export function setupMarkdown() {
};
}
export function setupEmojiDataModel(custom_emoji_views: CustomEmojiView[]) {
export function emojiMartCategories(
custom_emoji_views: CustomEmojiView[],
): EmojiMartCategory[] {
const groupedEmojis = groupBy(
custom_emoji_views,
x => x.custom_emoji.category,
);
const customEmojis: EmojiMartCategory[] = [];
for (const [category, emojis] of Object.entries(groupedEmojis)) {
customEmojis.push({
id: category,
@ -269,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(
custom_emoji_views.map(view => [view.custom_emoji.shortcode, view]),
);
}
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);
return true;
}
export function getEmojiMart(
@ -333,14 +295,20 @@ export function getEmojiMart(
customPickerOptions: any = {},
) {
const pickerOptions = {
...customPickerOptions,
onEmojiSelect: onEmojiSelect,
custom: customEmojis,
...customPickerOptions,
};
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({
noMatchTemplate: function () {
return "";
@ -414,7 +382,7 @@ export function setupTribute() {
});
}
interface EmojiMartCategory {
export interface EmojiMartCategory {
id: string;
name: string;
emojis: EmojiMartCustomEmoji[];

View file

@ -28,7 +28,11 @@ import {
} from "./components/home/login";
import { LoginReset } from "./components/home/login-reset";
import { Setup } from "./components/home/setup";
import { Signup } from "./components/home/signup";
import {
Signup,
SignupFetchConfig,
getSignupQueryParams,
} from "./components/home/signup";
import {
Modlog,
ModlogFetchConfig,
@ -75,6 +79,11 @@ import {
import { InitialFetchRequest, RouteData } from "./interfaces";
import { GetSiteResponse } from "lemmy-js-client";
import { Inferno } from "inferno";
import {
OAuthCallback,
OAuthCallbackConfig,
getOAuthCallbackQueryParams,
} from "./components/home/oauth/oauth-callback";
export interface IRoutePropsWithFetch<
DataT extends RouteData,
@ -114,8 +123,9 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
},
{
path: `/signup`,
getQueryParams: getSignupQueryParams,
component: Signup,
},
} as SignupFetchConfig,
{
path: `/create_post`,
component: CreatePost,
@ -218,6 +228,11 @@ export const routes: IRoutePropsWithFetch<RouteData, any, any>[] = [
path: `/verify_email/:token`,
component: VerifyEmail,
},
{
path: `/oauth/callback`,
getQueryParams: getOAuthCallbackQueryParams,
component: OAuthCallback,
} as OAuthCallbackConfig,
{
path: `/instances`,
component: Instances,

View file

@ -35,6 +35,7 @@ export const languages: TranslationDesc[] = [
{ resource: "ja", code: "ja", name: "日本語" },
{ resource: "ko", code: "ko", name: "한국어" },
{ resource: "nl", code: "nl", name: "Nederlands" },
{ resource: "nn", code: "nn", name: "nynorsk" },
{ resource: "oc", code: "oc", name: "Occitan" },
{ resource: "pl", code: "pl", name: "Polski" },
{ resource: "pt", code: "pt", name: "Português" },

View file

@ -37,7 +37,9 @@ export class UserService {
showToast?: boolean;
}) {
if (isBrowser() && res.jwt) {
showToast && toast(I18NextService.i18n.t("logged_in"));
if (showToast) {
toast(I18NextService.i18n.t("logged_in"));
}
setAuthCookie(res.jwt);
this.#setAuthInfo();
}

View file

@ -0,0 +1,21 @@
import { CommentSortType, PostSortType } from "lemmy-js-client";
function assertType<T>(_: T) {}
export default function commentToPostSortType(
sort: CommentSortType,
): PostSortType {
switch (sort) {
case "Hot":
case "New":
case "Old":
case "Controversial":
return sort;
case "Top":
return "TopAll";
default: {
assertType<never>(sort);
return "Hot";
}
}
}

View file

@ -1,31 +0,0 @@
import { CommentSortType, SortType } from "lemmy-js-client";
export default function convertCommentSortType(
sort: SortType,
): CommentSortType {
switch (sort) {
case "TopAll":
case "TopHour":
case "TopSixHour":
case "TopTwelveHour":
case "TopDay":
case "TopWeek":
case "TopMonth":
case "TopThreeMonths":
case "TopSixMonths":
case "TopNineMonths":
case "TopYear": {
return "Top";
}
case "New": {
return "New";
}
case "Hot":
case "Active": {
return "Hot";
}
default: {
return "Hot";
}
}
}

View file

@ -1,5 +1,5 @@
import { GetSiteResponse } from "lemmy-js-client";
export default function enableNsfw(siteRes: GetSiteResponse): boolean {
return siteRes.site_view.local_site.enable_nsfw;
return !!siteRes.site_view.site.content_warning;
}

View file

@ -1,11 +1,11 @@
import buildCommentsTree from "./build-comments-tree";
import { colorList } from "./color-list";
import commentToPostSortType from "./comment-to-post-sort-type";
import commentsToFlatNodes from "./comments-to-flat-nodes";
import communityRSSUrl from "./community-rss-url";
import communitySearch from "./community-search";
import communitySelectName from "./community-select-name";
import communityToChoice from "./community-to-choice";
import convertCommentSortType from "./convert-comment-sort-type";
import editComment from "./edit-comment";
import editCommentReply from "./edit-comment-reply";
import editCommentReport from "./edit-comment-report";
@ -59,12 +59,12 @@ import isAnonymousPath from "./is-anonymous-path";
export {
buildCommentsTree,
colorList,
commentToPostSortType,
commentsToFlatNodes,
communityRSSUrl,
communitySearch,
communitySelectName,
communityToChoice,
convertCommentSortType,
editComment,
editCommentReply,
editCommentReport,

View file

@ -1,11 +1,8 @@
import { GetSiteResponse } from "lemmy-js-client";
import { setupEmojiDataModel, setupMarkdown } from "../../markdown";
import { setupMarkdown } from "../../markdown";
import { UserService } from "../../services";
export default function initializeSite(site?: GetSiteResponse) {
UserService.Instance.myUserInfo = site?.my_user;
if (site) {
setupEmojiDataModel(site.custom_emojis ?? []);
}
setupMarkdown();
}

View file

@ -6,12 +6,8 @@ export default function isPostBlocked(
myUserInfo: MyUserInfo | undefined = UserService.Instance.myUserInfo,
): boolean {
return (
(myUserInfo?.community_blocks
.map(c => c.community.id)
.includes(pv.community.id) ||
myUserInfo?.person_blocks
.map(p => p.target.id)
.includes(pv.creator.id)) ??
(myUserInfo?.community_blocks.some(c => c.id === pv.community.id) ||
myUserInfo?.person_blocks.some(p => p.id === pv.creator.id)) ??
false
);
}

View file

@ -1,16 +1,39 @@
import { CommentSortType, SortType } from "lemmy-js-client";
import { CommentSortType, PostSortType } from "lemmy-js-client";
export default function postToCommentSortType(sort: SortType): CommentSortType {
function assertType<T>(_: T) {}
export default function postToCommentSortType(
sort: PostSortType,
): CommentSortType {
switch (sort) {
case "Active":
case "Hot":
return "Hot";
case "New":
case "NewComments":
return "New";
case "Old":
return "Old";
default:
case "Controversial": {
return sort;
}
case "TopAll":
case "TopHour":
case "TopSixHour":
case "TopTwelveHour":
case "TopDay":
case "TopWeek":
case "TopMonth":
case "TopThreeMonths":
case "TopSixMonths":
case "TopNineMonths":
case "TopYear": {
return "Top";
}
case "NewComments":
case "MostComments":
case "Scaled":
case "Active": {
return "Hot";
}
default: {
assertType<never>(sort);
return "Hot";
}
}
}

View file

@ -136,7 +136,7 @@ function langToLocale(lang: string): DateFnsDesc | undefined {
async function load(locale: DateFnsDesc): Promise<Locale> {
return import(
/* webpackChunkName: `date-fns-[request]` */
`date-fns/locale/${locale.resource}.mjs`
`date-fns/locale/${locale.resource}.js`
).then(x => x.default);
}
@ -184,7 +184,7 @@ export function findDateFnsChunkNames(languages: readonly string[]): string[] {
if (locale.bundled) {
return [];
}
return [`date-fns-${locale.resource}-mjs`];
return [`date-fns-${locale.resource}-js`];
}
export default async function () {

View file

@ -8,10 +8,7 @@ export default function updateCommunityBlock(
) {
if (myUserInfo) {
if (data.blocked) {
myUserInfo.community_blocks.push({
person: myUserInfo.local_user_view.person,
community: data.community_view.community,
});
myUserInfo.community_blocks.push(data.community_view.community);
toast(
`${I18NextService.i18n.t("blocked")} ${
data.community_view.community.name
@ -19,7 +16,7 @@ export default function updateCommunityBlock(
);
} else {
myUserInfo.community_blocks = myUserInfo.community_blocks.filter(
i => i.community.id !== data.community_view.community.id,
c => c.id !== data.community_view.community.id,
);
toast(
`${I18NextService.i18n.t("unblocked")} ${

View file

@ -12,14 +12,11 @@ export default function updateInstanceBlock(
const instance = linkedInstances.find(i => i.id === id)!;
if (data.blocked) {
myUserInfo.instance_blocks.push({
person: myUserInfo.local_user_view.person,
instance,
});
myUserInfo.instance_blocks.push(instance);
toast(`${I18NextService.i18n.t("blocked")} ${instance.domain}`);
} else {
myUserInfo.instance_blocks = myUserInfo.instance_blocks.filter(
i => i.instance.id !== id,
i => i.id !== id,
);
toast(`${I18NextService.i18n.t("unblocked")} ${instance.domain}`);
}

View file

@ -8,16 +8,13 @@ export default function updatePersonBlock(
) {
if (myUserInfo) {
if (data.blocked) {
myUserInfo.person_blocks.push({
person: myUserInfo.local_user_view.person,
target: data.person_view.person,
});
myUserInfo.person_blocks.push(data.person_view.person);
toast(
`${I18NextService.i18n.t("blocked")} ${data.person_view.person.name}`,
);
} else {
myUserInfo.person_blocks = myUserInfo.person_blocks.filter(
i => i.target.id !== data.person_view.person.id,
p => p.id !== data.person_view.person.id,
);
toast(
`${I18NextService.i18n.t("unblocked")} ${data.person_view.person.name}`,

View file

@ -5,7 +5,6 @@ export default function voteDisplayMode(
): LocalUserVoteDisplayMode {
return (
siteRes?.my_user?.local_user_view.local_user_vote_display_mode ?? {
local_user_id: -1,
upvotes: true,
downvotes: true,
score: false,

View file

@ -4,7 +4,7 @@ import { authCookieName } from "../../config";
export default function clearAuthCookie() {
document.cookie = cookie.serialize(authCookieName, "", {
maxAge: -1,
sameSite: true,
sameSite: "lax",
path: "/",
});
}

View file

@ -9,15 +9,7 @@ export default function dataBsTheme(siteResOrTheme?: GetSiteResponse | string) {
siteResOrTheme?.site_view.local_site.default_theme ??
"browser");
return (isDark() && theme === "browser") ||
[
"darkly",
"darkly-red",
"darkly-pureblack",
"darkly-compact",
"i386",
"vaporwave-dark",
].includes(theme)
return (isDark() && theme === "browser") || theme.includes("dark")
? "dark"
: "light";
}

View file

@ -6,7 +6,7 @@ export default function setAuthCookie(jwt: string) {
document.cookie = cookie.serialize(authCookieName, jwt, {
maxAge: 365 * 24 * 60 * 60 * 1000,
secure: isHttps(),
sameSite: true,
sameSite: "lax",
path: "/",
});
}

View file

@ -6,7 +6,7 @@ export default function (dateString?: string) {
return formatDistanceStrict(parsed, new Date(), {
addSuffix: true,
});
} catch (e) {
} catch {
return "indeterminate";
}
}

View file

@ -0,0 +1,5 @@
export default function getBoolFromString(
boolStr?: string,
): boolean | undefined {
return boolStr ? boolStr.toLowerCase() === "true" : undefined;
}

View file

@ -1,3 +1,27 @@
export default function getUnixTime(text?: string): number | undefined {
/**
* Converts timestamp string to unix timestamp in seconds, as used by Lemmy API
*/
export function getUnixTimeLemmy(text?: string): number | undefined {
return text ? new Date(text).getTime() / 1000 : undefined;
}
/**
* Converts timestamp string to unix timestamp in millis, as used by Javascript
*/
export function getUnixTime(text?: string): number | undefined {
return text ? new Date(text).getTime() : undefined;
}
/**
* This converts a unix time to a local date string,
* popping to tho nearest minute, and removing the Z for
* javascript fields.
*/
export function unixTimeToLocalDateStr(unixTime?: number): string | undefined {
return unixTime
? convertUTCDateToLocalDate(new Date(unixTime)).toISOString().slice(0, -8)
: undefined;
}
function convertUTCDateToLocalDate(date: Date): Date {
return new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000);
}

View file

@ -5,12 +5,12 @@ import editListImmutable from "./edit-list-immutable";
import formatPastDate from "./format-past-date";
import futureDaysToUnixTime from "./future-days-to-unix-time";
import getIdFromString from "./get-id-from-string";
import getBoolFromString from "./get-bool-from-string";
import getPageFromString from "./get-page-from-string";
import getQueryParams from "./get-query-params";
import getQueryString from "./get-query-string";
import getRandomCharFromAlphabet from "./get-random-char-from-alphabet";
import getRandomFromList from "./get-random-from-list";
import getUnixTime from "./get-unix-time";
import { groupBy } from "./group-by";
import hostname from "./hostname";
import hsl from "./hsl";
@ -36,12 +36,12 @@ export {
formatPastDate,
futureDaysToUnixTime,
getIdFromString,
getBoolFromString,
getPageFromString,
getQueryParams,
getQueryString,
getRandomCharFromAlphabet,
getRandomFromList,
getUnixTime,
groupBy,
hostname,
hsl,

View file

@ -0,0 +1,9 @@
const magnetLinkRegex = /^magnet:\?xt=urn:btih:[0-9a-fA-F]{40,}.*$/;
export default function isMagnetLink(url: string) {
return magnetLinkRegex.test(url);
}
export function extractMagnetLinkDownloadName(url: string) {
return new URLSearchParams(url).get("dn");
}

View file

@ -1,5 +1,10 @@
import StringBoolean from "./string-boolean";
export default interface CrossPostParams {
name: string;
url?: string;
body?: string;
altText?: string;
nsfw?: StringBoolean;
languageId?: number;
}

View file

@ -0,0 +1,6 @@
import { CreateOAuthProvider } from "lemmy-js-client";
export type ProviderToEdit = Omit<
CreateOAuthProvider,
"client_id" | "client_secret"
>;