mirror of
https://github.com/go-gitea/gitea
synced 2024-11-14 22:11:32 +01:00
Merge branch 'main' into lunny/rename_board_column
This commit is contained in:
commit
506f2ac9b8
43 changed files with 670 additions and 2017 deletions
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
|
@ -53,7 +53,7 @@ modifies/internal:
|
||||||
- ".gitpod.yml"
|
- ".gitpod.yml"
|
||||||
- ".markdownlint.yaml"
|
- ".markdownlint.yaml"
|
||||||
- ".spectral.yaml"
|
- ".spectral.yaml"
|
||||||
- ".stylelintrc.yaml"
|
- "stylelint.config.js"
|
||||||
- ".yamllint.yaml"
|
- ".yamllint.yaml"
|
||||||
- ".github/**"
|
- ".github/**"
|
||||||
- ".gitea/"
|
- ".gitea/"
|
||||||
|
|
2
.github/workflows/files-changed.yml
vendored
2
.github/workflows/files-changed.yml
vendored
|
@ -58,7 +58,7 @@ jobs:
|
||||||
- "package-lock.json"
|
- "package-lock.json"
|
||||||
- "Makefile"
|
- "Makefile"
|
||||||
- ".eslintrc.yaml"
|
- ".eslintrc.yaml"
|
||||||
- ".stylelintrc.yaml"
|
- "stylelint.config.js"
|
||||||
- ".npmrc"
|
- ".npmrc"
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
|
|
|
@ -1,223 +0,0 @@
|
||||||
plugins:
|
|
||||||
- stylelint-declaration-strict-value
|
|
||||||
- stylelint-declaration-block-no-ignored-properties
|
|
||||||
- "@stylistic/stylelint-plugin"
|
|
||||||
|
|
||||||
ignoreFiles:
|
|
||||||
- "**/*.go"
|
|
||||||
|
|
||||||
overrides:
|
|
||||||
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console.css", "font_i18n.css"]
|
|
||||||
rules:
|
|
||||||
scale-unlimited/declaration-strict-value: null
|
|
||||||
- files: ["**/chroma/*", "**/codemirror/*"]
|
|
||||||
rules:
|
|
||||||
block-no-empty: null
|
|
||||||
- files: ["**/*.vue"]
|
|
||||||
customSyntax: postcss-html
|
|
||||||
|
|
||||||
rules:
|
|
||||||
"@stylistic/at-rule-name-case": null
|
|
||||||
"@stylistic/at-rule-name-newline-after": null
|
|
||||||
"@stylistic/at-rule-name-space-after": null
|
|
||||||
"@stylistic/at-rule-semicolon-newline-after": null
|
|
||||||
"@stylistic/at-rule-semicolon-space-before": null
|
|
||||||
"@stylistic/block-closing-brace-empty-line-before": null
|
|
||||||
"@stylistic/block-closing-brace-newline-after": null
|
|
||||||
"@stylistic/block-closing-brace-newline-before": null
|
|
||||||
"@stylistic/block-closing-brace-space-after": null
|
|
||||||
"@stylistic/block-closing-brace-space-before": null
|
|
||||||
"@stylistic/block-opening-brace-newline-after": null
|
|
||||||
"@stylistic/block-opening-brace-newline-before": null
|
|
||||||
"@stylistic/block-opening-brace-space-after": null
|
|
||||||
"@stylistic/block-opening-brace-space-before": always
|
|
||||||
"@stylistic/color-hex-case": lower
|
|
||||||
"@stylistic/declaration-bang-space-after": never
|
|
||||||
"@stylistic/declaration-bang-space-before": null
|
|
||||||
"@stylistic/declaration-block-semicolon-newline-after": null
|
|
||||||
"@stylistic/declaration-block-semicolon-newline-before": null
|
|
||||||
"@stylistic/declaration-block-semicolon-space-after": null
|
|
||||||
"@stylistic/declaration-block-semicolon-space-before": never
|
|
||||||
"@stylistic/declaration-block-trailing-semicolon": null
|
|
||||||
"@stylistic/declaration-colon-newline-after": null
|
|
||||||
"@stylistic/declaration-colon-space-after": null
|
|
||||||
"@stylistic/declaration-colon-space-before": never
|
|
||||||
"@stylistic/function-comma-newline-after": null
|
|
||||||
"@stylistic/function-comma-newline-before": null
|
|
||||||
"@stylistic/function-comma-space-after": null
|
|
||||||
"@stylistic/function-comma-space-before": null
|
|
||||||
"@stylistic/function-max-empty-lines": 0
|
|
||||||
"@stylistic/function-parentheses-newline-inside": never-multi-line
|
|
||||||
"@stylistic/function-parentheses-space-inside": null
|
|
||||||
"@stylistic/function-whitespace-after": null
|
|
||||||
"@stylistic/indentation": 2
|
|
||||||
"@stylistic/linebreaks": null
|
|
||||||
"@stylistic/max-empty-lines": 1
|
|
||||||
"@stylistic/max-line-length": null
|
|
||||||
"@stylistic/media-feature-colon-space-after": null
|
|
||||||
"@stylistic/media-feature-colon-space-before": never
|
|
||||||
"@stylistic/media-feature-name-case": null
|
|
||||||
"@stylistic/media-feature-parentheses-space-inside": null
|
|
||||||
"@stylistic/media-feature-range-operator-space-after": always
|
|
||||||
"@stylistic/media-feature-range-operator-space-before": always
|
|
||||||
"@stylistic/media-query-list-comma-newline-after": null
|
|
||||||
"@stylistic/media-query-list-comma-newline-before": null
|
|
||||||
"@stylistic/media-query-list-comma-space-after": null
|
|
||||||
"@stylistic/media-query-list-comma-space-before": null
|
|
||||||
"@stylistic/named-grid-areas-alignment": null
|
|
||||||
"@stylistic/no-empty-first-line": null
|
|
||||||
"@stylistic/no-eol-whitespace": true
|
|
||||||
"@stylistic/no-extra-semicolons": true
|
|
||||||
"@stylistic/no-missing-end-of-source-newline": null
|
|
||||||
"@stylistic/number-leading-zero": null
|
|
||||||
"@stylistic/number-no-trailing-zeros": null
|
|
||||||
"@stylistic/property-case": lower
|
|
||||||
"@stylistic/selector-attribute-brackets-space-inside": null
|
|
||||||
"@stylistic/selector-attribute-operator-space-after": null
|
|
||||||
"@stylistic/selector-attribute-operator-space-before": null
|
|
||||||
"@stylistic/selector-combinator-space-after": null
|
|
||||||
"@stylistic/selector-combinator-space-before": null
|
|
||||||
"@stylistic/selector-descendant-combinator-no-non-space": null
|
|
||||||
"@stylistic/selector-list-comma-newline-after": null
|
|
||||||
"@stylistic/selector-list-comma-newline-before": null
|
|
||||||
"@stylistic/selector-list-comma-space-after": always-single-line
|
|
||||||
"@stylistic/selector-list-comma-space-before": never-single-line
|
|
||||||
"@stylistic/selector-max-empty-lines": 0
|
|
||||||
"@stylistic/selector-pseudo-class-case": lower
|
|
||||||
"@stylistic/selector-pseudo-class-parentheses-space-inside": never
|
|
||||||
"@stylistic/selector-pseudo-element-case": lower
|
|
||||||
"@stylistic/string-quotes": double
|
|
||||||
"@stylistic/unicode-bom": null
|
|
||||||
"@stylistic/unit-case": lower
|
|
||||||
"@stylistic/value-list-comma-newline-after": null
|
|
||||||
"@stylistic/value-list-comma-newline-before": null
|
|
||||||
"@stylistic/value-list-comma-space-after": null
|
|
||||||
"@stylistic/value-list-comma-space-before": null
|
|
||||||
"@stylistic/value-list-max-empty-lines": 0
|
|
||||||
alpha-value-notation: null
|
|
||||||
annotation-no-unknown: true
|
|
||||||
at-rule-allowed-list: null
|
|
||||||
at-rule-disallowed-list: null
|
|
||||||
at-rule-empty-line-before: null
|
|
||||||
at-rule-no-unknown: [true, {ignoreAtRules: [tailwind]}]
|
|
||||||
at-rule-no-vendor-prefix: true
|
|
||||||
at-rule-property-required-list: null
|
|
||||||
block-no-empty: true
|
|
||||||
color-function-notation: null
|
|
||||||
color-hex-alpha: null
|
|
||||||
color-hex-length: null
|
|
||||||
color-named: null
|
|
||||||
color-no-hex: null
|
|
||||||
color-no-invalid-hex: true
|
|
||||||
comment-empty-line-before: null
|
|
||||||
comment-no-empty: true
|
|
||||||
comment-pattern: null
|
|
||||||
comment-whitespace-inside: null
|
|
||||||
comment-word-disallowed-list: null
|
|
||||||
custom-media-pattern: null
|
|
||||||
custom-property-empty-line-before: null
|
|
||||||
custom-property-no-missing-var-function: true
|
|
||||||
custom-property-pattern: null
|
|
||||||
declaration-block-no-duplicate-custom-properties: true
|
|
||||||
declaration-block-no-duplicate-properties: [true, {ignore: [consecutive-duplicates-with-different-values]}]
|
|
||||||
declaration-block-no-redundant-longhand-properties: null
|
|
||||||
declaration-block-no-shorthand-property-overrides: null
|
|
||||||
declaration-block-single-line-max-declarations: null
|
|
||||||
declaration-empty-line-before: null
|
|
||||||
declaration-no-important: null
|
|
||||||
declaration-property-max-values: null
|
|
||||||
declaration-property-unit-allowed-list: null
|
|
||||||
declaration-property-unit-disallowed-list: {line-height: [em]}
|
|
||||||
declaration-property-value-allowed-list: null
|
|
||||||
declaration-property-value-disallowed-list: null
|
|
||||||
declaration-property-value-no-unknown: true
|
|
||||||
font-family-name-quotes: always-where-recommended
|
|
||||||
font-family-no-duplicate-names: true
|
|
||||||
font-family-no-missing-generic-family-keyword: true
|
|
||||||
font-weight-notation: null
|
|
||||||
function-allowed-list: null
|
|
||||||
function-calc-no-unspaced-operator: true
|
|
||||||
function-disallowed-list: null
|
|
||||||
function-linear-gradient-no-nonstandard-direction: true
|
|
||||||
function-name-case: lower
|
|
||||||
function-no-unknown: true
|
|
||||||
function-url-no-scheme-relative: null
|
|
||||||
function-url-quotes: always
|
|
||||||
function-url-scheme-allowed-list: null
|
|
||||||
function-url-scheme-disallowed-list: null
|
|
||||||
hue-degree-notation: null
|
|
||||||
import-notation: string
|
|
||||||
keyframe-block-no-duplicate-selectors: true
|
|
||||||
keyframe-declaration-no-important: true
|
|
||||||
keyframe-selector-notation: null
|
|
||||||
keyframes-name-pattern: null
|
|
||||||
length-zero-no-unit: [true, ignore: [custom-properties], ignoreFunctions: [var]]
|
|
||||||
max-nesting-depth: null
|
|
||||||
media-feature-name-allowed-list: null
|
|
||||||
media-feature-name-disallowed-list: null
|
|
||||||
media-feature-name-no-unknown: true
|
|
||||||
media-feature-name-no-vendor-prefix: true
|
|
||||||
media-feature-name-unit-allowed-list: null
|
|
||||||
media-feature-name-value-allowed-list: null
|
|
||||||
media-feature-name-value-no-unknown: true
|
|
||||||
media-feature-range-notation: null
|
|
||||||
media-query-no-invalid: true
|
|
||||||
named-grid-areas-no-invalid: true
|
|
||||||
no-descending-specificity: null
|
|
||||||
no-duplicate-at-import-rules: true
|
|
||||||
no-duplicate-selectors: true
|
|
||||||
no-empty-source: true
|
|
||||||
no-invalid-double-slash-comments: true
|
|
||||||
no-invalid-position-at-import-rule: [true, ignoreAtRules: [tailwind]]
|
|
||||||
no-irregular-whitespace: true
|
|
||||||
no-unknown-animations: null
|
|
||||||
no-unknown-custom-properties: null
|
|
||||||
number-max-precision: null
|
|
||||||
plugin/declaration-block-no-ignored-properties: true
|
|
||||||
property-allowed-list: null
|
|
||||||
property-disallowed-list: null
|
|
||||||
property-no-unknown: true
|
|
||||||
property-no-vendor-prefix: null
|
|
||||||
rule-empty-line-before: null
|
|
||||||
rule-selector-property-disallowed-list: null
|
|
||||||
scale-unlimited/declaration-strict-value: [[/color$/, font-weight], {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor|none)$/, ignoreFunctions: false, disableFix: true, expandShorthand: true}]
|
|
||||||
selector-anb-no-unmatchable: true
|
|
||||||
selector-attribute-name-disallowed-list: null
|
|
||||||
selector-attribute-operator-allowed-list: null
|
|
||||||
selector-attribute-operator-disallowed-list: null
|
|
||||||
selector-attribute-quotes: always
|
|
||||||
selector-class-pattern: null
|
|
||||||
selector-combinator-allowed-list: null
|
|
||||||
selector-combinator-disallowed-list: null
|
|
||||||
selector-disallowed-list: null
|
|
||||||
selector-id-pattern: null
|
|
||||||
selector-max-attribute: null
|
|
||||||
selector-max-class: null
|
|
||||||
selector-max-combinators: null
|
|
||||||
selector-max-compound-selectors: null
|
|
||||||
selector-max-id: null
|
|
||||||
selector-max-pseudo-class: null
|
|
||||||
selector-max-specificity: null
|
|
||||||
selector-max-type: null
|
|
||||||
selector-max-universal: null
|
|
||||||
selector-nested-pattern: null
|
|
||||||
selector-no-qualifying-type: null
|
|
||||||
selector-no-vendor-prefix: true
|
|
||||||
selector-not-notation: null
|
|
||||||
selector-pseudo-class-allowed-list: null
|
|
||||||
selector-pseudo-class-disallowed-list: null
|
|
||||||
selector-pseudo-class-no-unknown: true
|
|
||||||
selector-pseudo-element-allowed-list: null
|
|
||||||
selector-pseudo-element-colon-notation: double
|
|
||||||
selector-pseudo-element-disallowed-list: null
|
|
||||||
selector-pseudo-element-no-unknown: true
|
|
||||||
selector-type-case: lower
|
|
||||||
selector-type-no-unknown: [true, {ignore: [custom-elements]}]
|
|
||||||
shorthand-property-no-redundant-values: true
|
|
||||||
string-no-newline: true
|
|
||||||
time-min-milliseconds: null
|
|
||||||
unit-allowed-list: null
|
|
||||||
unit-disallowed-list: null
|
|
||||||
unit-no-unknown: true
|
|
||||||
value-keyword-case: null
|
|
||||||
value-no-vendor-prefix: [true, {ignoreValues: [box, inline-box]}]
|
|
|
@ -1485,6 +1485,11 @@ LEVEL = Info
|
||||||
;; - manage_ssh_keys: a user cannot configure ssh keys
|
;; - manage_ssh_keys: a user cannot configure ssh keys
|
||||||
;; - manage_gpg_keys: a user cannot configure gpg keys
|
;; - manage_gpg_keys: a user cannot configure gpg keys
|
||||||
;USER_DISABLED_FEATURES =
|
;USER_DISABLED_FEATURES =
|
||||||
|
;; Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
|
||||||
|
;; - deletion: a user cannot delete their own account
|
||||||
|
;; - manage_ssh_keys: a user cannot configure ssh keys
|
||||||
|
;; - manage_gpg_keys: a user cannot configure gpg keys
|
||||||
|
;;EXTERNAL_USER_DISABLE_FEATURES =
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -522,6 +522,10 @@ And the following unique queues:
|
||||||
- `deletion`: User cannot delete their own account.
|
- `deletion`: User cannot delete their own account.
|
||||||
- `manage_ssh_keys`: User cannot configure ssh keys.
|
- `manage_ssh_keys`: User cannot configure ssh keys.
|
||||||
- `manage_gpg_keys`: User cannot configure gpg keys.
|
- `manage_gpg_keys`: User cannot configure gpg keys.
|
||||||
|
- `EXTERNAL_USER_DISABLE_FEATURES`: **_empty_**: Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
|
||||||
|
- `deletion`: User cannot delete their own account.
|
||||||
|
- `manage_ssh_keys`: User cannot configure ssh keys.
|
||||||
|
- `manage_gpg_keys`: User cannot configure gpg keys.
|
||||||
|
|
||||||
## Security (`security`)
|
## Security (`security`)
|
||||||
|
|
||||||
|
|
|
@ -1232,3 +1232,21 @@ func GetOrderByName() string {
|
||||||
}
|
}
|
||||||
return "name"
|
return "name"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsFeatureDisabledWithLoginType checks if a user feature is disabled, taking into account the login type of the
|
||||||
|
// user if applicable
|
||||||
|
func IsFeatureDisabledWithLoginType(user *User, feature string) bool {
|
||||||
|
// NOTE: in the long run it may be better to check the ExternalLoginUser table rather than user.LoginType
|
||||||
|
return (user != nil && user.LoginType > auth.Plain && setting.Admin.ExternalUserDisableFeatures.Contains(feature)) ||
|
||||||
|
setting.Admin.UserDisabledFeatures.Contains(feature)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisabledFeaturesWithLoginType returns the set of user features disabled, taking into account the login type
|
||||||
|
// of the user if applicable
|
||||||
|
func DisabledFeaturesWithLoginType(user *User) *container.Set[string] {
|
||||||
|
// NOTE: in the long run it may be better to check the ExternalLoginUser table rather than user.LoginType
|
||||||
|
if user != nil && user.LoginType > auth.Plain {
|
||||||
|
return &setting.Admin.ExternalUserDisableFeatures
|
||||||
|
}
|
||||||
|
return &setting.Admin.UserDisabledFeatures
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/auth/password/hash"
|
"code.gitea.io/gitea/modules/auth/password/hash"
|
||||||
|
"code.gitea.io/gitea/modules/container"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -526,3 +527,37 @@ func Test_NormalizeUserFromEmail(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDisabledUserFeatures(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
testValues := container.SetOf(setting.UserFeatureDeletion,
|
||||||
|
setting.UserFeatureManageSSHKeys,
|
||||||
|
setting.UserFeatureManageGPGKeys)
|
||||||
|
|
||||||
|
oldSetting := setting.Admin.ExternalUserDisableFeatures
|
||||||
|
defer func() {
|
||||||
|
setting.Admin.ExternalUserDisableFeatures = oldSetting
|
||||||
|
}()
|
||||||
|
setting.Admin.ExternalUserDisableFeatures = testValues
|
||||||
|
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
|
assert.Len(t, setting.Admin.UserDisabledFeatures.Values(), 0)
|
||||||
|
|
||||||
|
// no features should be disabled with a plain login type
|
||||||
|
assert.LessOrEqual(t, user.LoginType, auth.Plain)
|
||||||
|
assert.Len(t, user_model.DisabledFeaturesWithLoginType(user).Values(), 0)
|
||||||
|
for _, f := range testValues.Values() {
|
||||||
|
assert.False(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// check disabled features with external login type
|
||||||
|
user.LoginType = auth.OAuth2
|
||||||
|
|
||||||
|
// all features should be disabled
|
||||||
|
assert.NotEmpty(t, user_model.DisabledFeaturesWithLoginType(user).Values())
|
||||||
|
for _, f := range testValues.Values() {
|
||||||
|
assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,12 @@ func convertPGPSignature(c *object.Commit) *CommitGPGSignature {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.Encoding != "" && c.Encoding != "UTF-8" {
|
||||||
|
if _, err = fmt.Fprintf(&w, "\nencoding %s\n", c.Encoding); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, err = fmt.Fprintf(&w, "\n\n%s", c.Message); err != nil {
|
if _, err = fmt.Fprintf(&w, "\n\n%s", c.Message); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,8 @@ readLoop:
|
||||||
commit.Committer = &Signature{}
|
commit.Committer = &Signature{}
|
||||||
commit.Committer.Decode(data)
|
commit.Committer.Decode(data)
|
||||||
_, _ = payloadSB.Write(line)
|
_, _ = payloadSB.Write(line)
|
||||||
|
case "encoding":
|
||||||
|
_, _ = payloadSB.Write(line)
|
||||||
case "gpgsig":
|
case "gpgsig":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "gpgsig-sha256": // FIXME: no intertop, so only 1 exists at present.
|
case "gpgsig-sha256": // FIXME: no intertop, so only 1 exists at present.
|
||||||
|
|
|
@ -125,6 +125,73 @@ empty commit`, commitFromReader.Signature.Payload)
|
||||||
assert.EqualValues(t, commitFromReader, commitFromReader2)
|
assert.EqualValues(t, commitFromReader, commitFromReader2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommitWithEncodingFromReader(t *testing.T) {
|
||||||
|
commitString := `feaf4ba6bc635fec442f46ddd4512416ec43c2c2 commit 1074
|
||||||
|
tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||||
|
parent 47b24e7ab977ed31c5a39989d570847d6d0052af
|
||||||
|
author KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||||
|
committer KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||||
|
encoding ISO-8859-1
|
||||||
|
gpgsig -----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQGzBAABCgAdFiEE9HRrbqvYxPT8PXbefPSEkrowAa8FAmYGg7IACgkQfPSEkrow
|
||||||
|
Aa9olwv+P0HhtCM6CRvlUmPaqswRsDPNR4i66xyXGiSxdI9V5oJL7HLiQIM7KrFR
|
||||||
|
gizKa2COiGtugv8fE+TKqXKaJx6uJUJEjaBd8E9Af9PrAzjWj+A84lU6/PgPS8hq
|
||||||
|
zOfZraLOEWRH4tZcS+u2yFLu3ez2Wqh1xW5LNy7xqEedMXEFD1HwSJ0+pjacNkzr
|
||||||
|
frp6Asyt7xRI6YmgFJZJoRsS3Ktr6rtKeRL2IErSQQyorOqj6gKrglhrhfG/114j
|
||||||
|
FKB1v4or0WZ1DE8iP2SJZ3n+/K1IuWAINh7MVdb7PndfBPEa+IL+ucNk5uzEE8Jd
|
||||||
|
G8smGxXUeFEt2cP1dj2W8EgAxuA9sTnH9dqI5aRqy5ifDjuya7Emm8sdOUvtGdmn
|
||||||
|
SONRzusmu5n3DgV956REL7x62h7JuqmBz/12HZkr0z0zgXkcZ04q08pSJATX5N1F
|
||||||
|
yN+tWxTsWg+zhDk96d5Esdo9JMjcFvPv0eioo30GAERaz1hoD7zCMT4jgUFTQwgz
|
||||||
|
jw4YcO5u
|
||||||
|
=r3UU
|
||||||
|
-----END PGP SIGNATURE-----
|
||||||
|
|
||||||
|
ISO-8859-1`
|
||||||
|
|
||||||
|
sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2}
|
||||||
|
gitRepo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, gitRepo)
|
||||||
|
defer gitRepo.Close()
|
||||||
|
|
||||||
|
commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if !assert.NotNil(t, commitFromReader) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.EqualValues(t, sha, commitFromReader.ID)
|
||||||
|
assert.EqualValues(t, `-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQGzBAABCgAdFiEE9HRrbqvYxPT8PXbefPSEkrowAa8FAmYGg7IACgkQfPSEkrow
|
||||||
|
Aa9olwv+P0HhtCM6CRvlUmPaqswRsDPNR4i66xyXGiSxdI9V5oJL7HLiQIM7KrFR
|
||||||
|
gizKa2COiGtugv8fE+TKqXKaJx6uJUJEjaBd8E9Af9PrAzjWj+A84lU6/PgPS8hq
|
||||||
|
zOfZraLOEWRH4tZcS+u2yFLu3ez2Wqh1xW5LNy7xqEedMXEFD1HwSJ0+pjacNkzr
|
||||||
|
frp6Asyt7xRI6YmgFJZJoRsS3Ktr6rtKeRL2IErSQQyorOqj6gKrglhrhfG/114j
|
||||||
|
FKB1v4or0WZ1DE8iP2SJZ3n+/K1IuWAINh7MVdb7PndfBPEa+IL+ucNk5uzEE8Jd
|
||||||
|
G8smGxXUeFEt2cP1dj2W8EgAxuA9sTnH9dqI5aRqy5ifDjuya7Emm8sdOUvtGdmn
|
||||||
|
SONRzusmu5n3DgV956REL7x62h7JuqmBz/12HZkr0z0zgXkcZ04q08pSJATX5N1F
|
||||||
|
yN+tWxTsWg+zhDk96d5Esdo9JMjcFvPv0eioo30GAERaz1hoD7zCMT4jgUFTQwgz
|
||||||
|
jw4YcO5u
|
||||||
|
=r3UU
|
||||||
|
-----END PGP SIGNATURE-----
|
||||||
|
`, commitFromReader.Signature.Signature)
|
||||||
|
assert.EqualValues(t, `tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||||
|
parent 47b24e7ab977ed31c5a39989d570847d6d0052af
|
||||||
|
author KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||||
|
committer KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||||
|
encoding ISO-8859-1
|
||||||
|
|
||||||
|
ISO-8859-1`, commitFromReader.Signature.Payload)
|
||||||
|
assert.EqualValues(t, "KN4CK3R <admin@oldschoolhack.me>", commitFromReader.Author.String())
|
||||||
|
|
||||||
|
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
commitFromReader.CommitMessage += "\n\n"
|
||||||
|
commitFromReader.Signature.Payload += "\n\n"
|
||||||
|
assert.EqualValues(t, commitFromReader, commitFromReader2)
|
||||||
|
}
|
||||||
|
|
||||||
func TestHasPreviousCommit(t *testing.T) {
|
func TestHasPreviousCommit(t *testing.T) {
|
||||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,16 @@
|
||||||
|
|
||||||
package setting
|
package setting
|
||||||
|
|
||||||
import "code.gitea.io/gitea/modules/container"
|
import (
|
||||||
|
"code.gitea.io/gitea/modules/container"
|
||||||
|
)
|
||||||
|
|
||||||
// Admin settings
|
// Admin settings
|
||||||
var Admin struct {
|
var Admin struct {
|
||||||
DisableRegularOrgCreation bool
|
DisableRegularOrgCreation bool
|
||||||
DefaultEmailNotification string
|
DefaultEmailNotification string
|
||||||
UserDisabledFeatures container.Set[string]
|
UserDisabledFeatures container.Set[string]
|
||||||
|
ExternalUserDisableFeatures container.Set[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAdminFrom(rootCfg ConfigProvider) {
|
func loadAdminFrom(rootCfg ConfigProvider) {
|
||||||
|
@ -17,6 +20,7 @@ func loadAdminFrom(rootCfg ConfigProvider) {
|
||||||
Admin.DisableRegularOrgCreation = sec.Key("DISABLE_REGULAR_ORG_CREATION").MustBool(false)
|
Admin.DisableRegularOrgCreation = sec.Key("DISABLE_REGULAR_ORG_CREATION").MustBool(false)
|
||||||
Admin.DefaultEmailNotification = sec.Key("DEFAULT_EMAIL_NOTIFICATIONS").MustString("enabled")
|
Admin.DefaultEmailNotification = sec.Key("DEFAULT_EMAIL_NOTIFICATIONS").MustString("enabled")
|
||||||
Admin.UserDisabledFeatures = container.SetOf(sec.Key("USER_DISABLED_FEATURES").Strings(",")...)
|
Admin.UserDisabledFeatures = container.SetOf(sec.Key("USER_DISABLED_FEATURES").Strings(",")...)
|
||||||
|
Admin.ExternalUserDisableFeatures = container.SetOf(sec.Key("EXTERNAL_USER_DISABLE_FEATURES").Strings(",")...)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -91,6 +91,7 @@
|
||||||
"stylelint": "16.3.0",
|
"stylelint": "16.3.0",
|
||||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||||
"stylelint-declaration-strict-value": "1.10.4",
|
"stylelint-declaration-strict-value": "1.10.4",
|
||||||
|
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||||
"svgo": "3.2.0",
|
"svgo": "3.2.0",
|
||||||
"updates": "16.0.0",
|
"updates": "16.0.0",
|
||||||
"vite-string-plugin": "1.1.5",
|
"vite-string-plugin": "1.1.5",
|
||||||
|
@ -10867,6 +10868,22 @@
|
||||||
"stylelint": ">=7 <=16"
|
"stylelint": ">=7 <=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stylelint-value-no-unknown-custom-properties": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/stylelint-value-no-unknown-custom-properties/-/stylelint-value-no-unknown-custom-properties-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-N60PTdaTknB35j6D4FhW0GL2LlBRV++bRpXMMldWMQZ240yFQaoltzlLY4lXXs7Z0J5mNUYZQ/gjyVtU2DhCMA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"postcss-value-parser": "^4.2.0",
|
||||||
|
"resolve": "^1.22.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"stylelint": ">=16"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/stylelint/node_modules/ansi-regex": {
|
"node_modules/stylelint/node_modules/ansi-regex": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
"stylelint": "16.3.0",
|
"stylelint": "16.3.0",
|
||||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||||
"stylelint-declaration-strict-value": "1.10.4",
|
"stylelint-declaration-strict-value": "1.10.4",
|
||||||
|
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||||
"svgo": "3.2.0",
|
"svgo": "3.2.0",
|
||||||
"updates": "16.0.0",
|
"updates": "16.0.0",
|
||||||
"vite-string-plugin": "1.1.5",
|
"vite-string-plugin": "1.1.5",
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
@ -133,7 +134,7 @@ func GetGPGKey(ctx *context.APIContext) {
|
||||||
|
|
||||||
// CreateUserGPGKey creates new GPG key to given user by ID.
|
// CreateUserGPGKey creates new GPG key to given user by ID.
|
||||||
func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid int64) {
|
func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid int64) {
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -274,7 +275,7 @@ func DeleteGPGKey(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ func GetPublicKey(ctx *context.APIContext) {
|
||||||
|
|
||||||
// CreateUserPublicKey creates new public key to given user by ID.
|
// CreateUserPublicKey creates new public key to given user by ID.
|
||||||
func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) {
|
func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) {
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ func DeletePublicKey(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,7 +235,7 @@ func DeleteEmail(ctx *context.Context) {
|
||||||
|
|
||||||
// DeleteAccount render user suicide page and response for delete user himself
|
// DeleteAccount render user suicide page and response for delete user himself
|
||||||
func DeleteAccount(ctx *context.Context) {
|
func DeleteAccount(ctx *context.Context) {
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureDeletion) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureDeletion) {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -319,7 +319,7 @@ func loadAccountData(ctx *context.Context) {
|
||||||
ctx.Data["EmailNotificationsPreference"] = ctx.Doer.EmailNotificationsPreference
|
ctx.Data["EmailNotificationsPreference"] = ctx.Doer.EmailNotificationsPreference
|
||||||
ctx.Data["ActivationsPending"] = pendingActivation
|
ctx.Data["ActivationsPending"] = pendingActivation
|
||||||
ctx.Data["CanAddEmails"] = !pendingActivation || !setting.Service.RegisterEmailConfirm
|
ctx.Data["CanAddEmails"] = !pendingActivation || !setting.Service.RegisterEmailConfirm
|
||||||
ctx.Data["UserDisabledFeatures"] = &setting.Admin.UserDisabledFeatures
|
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
|
||||||
|
|
||||||
if setting.Service.UserDeleteWithCommentsMaxTime != 0 {
|
if setting.Service.UserDeleteWithCommentsMaxTime != 0 {
|
||||||
ctx.Data["UserDeleteWithCommentsMaxTime"] = setting.Service.UserDeleteWithCommentsMaxTime.String()
|
ctx.Data["UserDeleteWithCommentsMaxTime"] = setting.Service.UserDeleteWithCommentsMaxTime.String()
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
@ -78,7 +79,7 @@ func KeysPost(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
|
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
case "gpg":
|
case "gpg":
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,7 @@ func KeysPost(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.verify_gpg_key_success", keyID))
|
ctx.Flash.Success(ctx.Tr("settings.verify_gpg_key_success", keyID))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
case "ssh":
|
case "ssh":
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -203,7 +204,7 @@ func KeysPost(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
|
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||||
case "verify_ssh":
|
case "verify_ssh":
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -240,7 +241,7 @@ func KeysPost(ctx *context.Context) {
|
||||||
func DeleteKey(ctx *context.Context) {
|
func DeleteKey(ctx *context.Context) {
|
||||||
switch ctx.FormString("type") {
|
switch ctx.FormString("type") {
|
||||||
case "gpg":
|
case "gpg":
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageGPGKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -250,7 +251,7 @@ func DeleteKey(ctx *context.Context) {
|
||||||
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
|
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
|
||||||
}
|
}
|
||||||
case "ssh":
|
case "ssh":
|
||||||
if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageSSHKeys) {
|
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureManageSSHKeys) {
|
||||||
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
ctx.NotFound("Not Found", fmt.Errorf("ssh keys setting is not allowed to be visited"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -333,5 +334,5 @@ func loadKeysData(ctx *context.Context) {
|
||||||
|
|
||||||
ctx.Data["VerifyingID"] = ctx.FormString("verify_gpg")
|
ctx.Data["VerifyingID"] = ctx.FormString("verify_gpg")
|
||||||
ctx.Data["VerifyingFingerprint"] = ctx.FormString("verify_ssh")
|
ctx.Data["VerifyingFingerprint"] = ctx.FormString("verify_ssh")
|
||||||
ctx.Data["UserDisabledFeatures"] = &setting.Admin.UserDisabledFeatures
|
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
|
||||||
}
|
}
|
||||||
|
|
245
stylelint.config.js
Normal file
245
stylelint.config.js
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
import {fileURLToPath} from 'node:url';
|
||||||
|
|
||||||
|
const cssVarFiles = [
|
||||||
|
fileURLToPath(new URL('web_src/css/base.css', import.meta.url)),
|
||||||
|
fileURLToPath(new URL('web_src/css/themes/theme-gitea-light.css', import.meta.url)),
|
||||||
|
fileURLToPath(new URL('web_src/css/themes/theme-gitea-dark.css', import.meta.url)),
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @type {import('stylelint').Config} */
|
||||||
|
export default {
|
||||||
|
plugins: [
|
||||||
|
'stylelint-declaration-strict-value',
|
||||||
|
'stylelint-declaration-block-no-ignored-properties',
|
||||||
|
'stylelint-value-no-unknown-custom-properties',
|
||||||
|
'@stylistic/stylelint-plugin',
|
||||||
|
],
|
||||||
|
ignoreFiles: [
|
||||||
|
'**/*.go',
|
||||||
|
],
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['**/chroma/*', '**/codemirror/*', '**/standalone/*', '**/console.css', 'font_i18n.css'],
|
||||||
|
rules: {
|
||||||
|
'scale-unlimited/declaration-strict-value': null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/chroma/*', '**/codemirror/*'],
|
||||||
|
rules: {
|
||||||
|
'block-no-empty': null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.vue'],
|
||||||
|
customSyntax: 'postcss-html',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'@stylistic/at-rule-name-case': null,
|
||||||
|
'@stylistic/at-rule-name-newline-after': null,
|
||||||
|
'@stylistic/at-rule-name-space-after': null,
|
||||||
|
'@stylistic/at-rule-semicolon-newline-after': null,
|
||||||
|
'@stylistic/at-rule-semicolon-space-before': null,
|
||||||
|
'@stylistic/block-closing-brace-empty-line-before': null,
|
||||||
|
'@stylistic/block-closing-brace-newline-after': null,
|
||||||
|
'@stylistic/block-closing-brace-newline-before': null,
|
||||||
|
'@stylistic/block-closing-brace-space-after': null,
|
||||||
|
'@stylistic/block-closing-brace-space-before': null,
|
||||||
|
'@stylistic/block-opening-brace-newline-after': null,
|
||||||
|
'@stylistic/block-opening-brace-newline-before': null,
|
||||||
|
'@stylistic/block-opening-brace-space-after': null,
|
||||||
|
'@stylistic/block-opening-brace-space-before': 'always',
|
||||||
|
'@stylistic/color-hex-case': 'lower',
|
||||||
|
'@stylistic/declaration-bang-space-after': 'never',
|
||||||
|
'@stylistic/declaration-bang-space-before': null,
|
||||||
|
'@stylistic/declaration-block-semicolon-newline-after': null,
|
||||||
|
'@stylistic/declaration-block-semicolon-newline-before': null,
|
||||||
|
'@stylistic/declaration-block-semicolon-space-after': null,
|
||||||
|
'@stylistic/declaration-block-semicolon-space-before': 'never',
|
||||||
|
'@stylistic/declaration-block-trailing-semicolon': null,
|
||||||
|
'@stylistic/declaration-colon-newline-after': null,
|
||||||
|
'@stylistic/declaration-colon-space-after': null,
|
||||||
|
'@stylistic/declaration-colon-space-before': 'never',
|
||||||
|
'@stylistic/function-comma-newline-after': null,
|
||||||
|
'@stylistic/function-comma-newline-before': null,
|
||||||
|
'@stylistic/function-comma-space-after': null,
|
||||||
|
'@stylistic/function-comma-space-before': null,
|
||||||
|
'@stylistic/function-max-empty-lines': 0,
|
||||||
|
'@stylistic/function-parentheses-newline-inside': 'never-multi-line',
|
||||||
|
'@stylistic/function-parentheses-space-inside': null,
|
||||||
|
'@stylistic/function-whitespace-after': null,
|
||||||
|
'@stylistic/indentation': 2,
|
||||||
|
'@stylistic/linebreaks': null,
|
||||||
|
'@stylistic/max-empty-lines': 1,
|
||||||
|
'@stylistic/max-line-length': null,
|
||||||
|
'@stylistic/media-feature-colon-space-after': null,
|
||||||
|
'@stylistic/media-feature-colon-space-before': 'never',
|
||||||
|
'@stylistic/media-feature-name-case': null,
|
||||||
|
'@stylistic/media-feature-parentheses-space-inside': null,
|
||||||
|
'@stylistic/media-feature-range-operator-space-after': 'always',
|
||||||
|
'@stylistic/media-feature-range-operator-space-before': 'always',
|
||||||
|
'@stylistic/media-query-list-comma-newline-after': null,
|
||||||
|
'@stylistic/media-query-list-comma-newline-before': null,
|
||||||
|
'@stylistic/media-query-list-comma-space-after': null,
|
||||||
|
'@stylistic/media-query-list-comma-space-before': null,
|
||||||
|
'@stylistic/named-grid-areas-alignment': null,
|
||||||
|
'@stylistic/no-empty-first-line': null,
|
||||||
|
'@stylistic/no-eol-whitespace': true,
|
||||||
|
'@stylistic/no-extra-semicolons': true,
|
||||||
|
'@stylistic/no-missing-end-of-source-newline': null,
|
||||||
|
'@stylistic/number-leading-zero': null,
|
||||||
|
'@stylistic/number-no-trailing-zeros': null,
|
||||||
|
'@stylistic/property-case': 'lower',
|
||||||
|
'@stylistic/selector-attribute-brackets-space-inside': null,
|
||||||
|
'@stylistic/selector-attribute-operator-space-after': null,
|
||||||
|
'@stylistic/selector-attribute-operator-space-before': null,
|
||||||
|
'@stylistic/selector-combinator-space-after': null,
|
||||||
|
'@stylistic/selector-combinator-space-before': null,
|
||||||
|
'@stylistic/selector-descendant-combinator-no-non-space': null,
|
||||||
|
'@stylistic/selector-list-comma-newline-after': null,
|
||||||
|
'@stylistic/selector-list-comma-newline-before': null,
|
||||||
|
'@stylistic/selector-list-comma-space-after': 'always-single-line',
|
||||||
|
'@stylistic/selector-list-comma-space-before': 'never-single-line',
|
||||||
|
'@stylistic/selector-max-empty-lines': 0,
|
||||||
|
'@stylistic/selector-pseudo-class-case': 'lower',
|
||||||
|
'@stylistic/selector-pseudo-class-parentheses-space-inside': 'never',
|
||||||
|
'@stylistic/selector-pseudo-element-case': 'lower',
|
||||||
|
'@stylistic/string-quotes': 'double',
|
||||||
|
'@stylistic/unicode-bom': null,
|
||||||
|
'@stylistic/unit-case': 'lower',
|
||||||
|
'@stylistic/value-list-comma-newline-after': null,
|
||||||
|
'@stylistic/value-list-comma-newline-before': null,
|
||||||
|
'@stylistic/value-list-comma-space-after': null,
|
||||||
|
'@stylistic/value-list-comma-space-before': null,
|
||||||
|
'@stylistic/value-list-max-empty-lines': 0,
|
||||||
|
'alpha-value-notation': null,
|
||||||
|
'annotation-no-unknown': true,
|
||||||
|
'at-rule-allowed-list': null,
|
||||||
|
'at-rule-disallowed-list': null,
|
||||||
|
'at-rule-empty-line-before': null,
|
||||||
|
'at-rule-no-unknown': [true, {ignoreAtRules: ['tailwind']}],
|
||||||
|
'at-rule-no-vendor-prefix': true,
|
||||||
|
'at-rule-property-required-list': null,
|
||||||
|
'block-no-empty': true,
|
||||||
|
'color-function-notation': null,
|
||||||
|
'color-hex-alpha': null,
|
||||||
|
'color-hex-length': null,
|
||||||
|
'color-named': null,
|
||||||
|
'color-no-hex': null,
|
||||||
|
'color-no-invalid-hex': true,
|
||||||
|
'comment-empty-line-before': null,
|
||||||
|
'comment-no-empty': true,
|
||||||
|
'comment-pattern': null,
|
||||||
|
'comment-whitespace-inside': null,
|
||||||
|
'comment-word-disallowed-list': null,
|
||||||
|
'csstools/value-no-unknown-custom-properties': [true, {importFrom: cssVarFiles}],
|
||||||
|
'custom-media-pattern': null,
|
||||||
|
'custom-property-empty-line-before': null,
|
||||||
|
'custom-property-no-missing-var-function': true,
|
||||||
|
'custom-property-pattern': null,
|
||||||
|
'declaration-block-no-duplicate-custom-properties': true,
|
||||||
|
'declaration-block-no-duplicate-properties': [true, {ignore: ['consecutive-duplicates-with-different-values']}],
|
||||||
|
'declaration-block-no-redundant-longhand-properties': null,
|
||||||
|
'declaration-block-no-shorthand-property-overrides': null,
|
||||||
|
'declaration-block-single-line-max-declarations': null,
|
||||||
|
'declaration-empty-line-before': null,
|
||||||
|
'declaration-no-important': null,
|
||||||
|
'declaration-property-max-values': null,
|
||||||
|
'declaration-property-unit-allowed-list': null,
|
||||||
|
'declaration-property-unit-disallowed-list': {'line-height': ['em']},
|
||||||
|
'declaration-property-value-allowed-list': null,
|
||||||
|
'declaration-property-value-disallowed-list': null,
|
||||||
|
'declaration-property-value-no-unknown': true,
|
||||||
|
'font-family-name-quotes': 'always-where-recommended',
|
||||||
|
'font-family-no-duplicate-names': true,
|
||||||
|
'font-family-no-missing-generic-family-keyword': true,
|
||||||
|
'font-weight-notation': null,
|
||||||
|
'function-allowed-list': null,
|
||||||
|
'function-calc-no-unspaced-operator': true,
|
||||||
|
'function-disallowed-list': null,
|
||||||
|
'function-linear-gradient-no-nonstandard-direction': true,
|
||||||
|
'function-name-case': 'lower',
|
||||||
|
'function-no-unknown': true,
|
||||||
|
'function-url-no-scheme-relative': null,
|
||||||
|
'function-url-quotes': 'always',
|
||||||
|
'function-url-scheme-allowed-list': null,
|
||||||
|
'function-url-scheme-disallowed-list': null,
|
||||||
|
'hue-degree-notation': null,
|
||||||
|
'import-notation': 'string',
|
||||||
|
'keyframe-block-no-duplicate-selectors': true,
|
||||||
|
'keyframe-declaration-no-important': true,
|
||||||
|
'keyframe-selector-notation': null,
|
||||||
|
'keyframes-name-pattern': null,
|
||||||
|
'length-zero-no-unit': [true, {ignore: ['custom-properties']}, {ignoreFunctions: ['var']}],
|
||||||
|
'max-nesting-depth': null,
|
||||||
|
'media-feature-name-allowed-list': null,
|
||||||
|
'media-feature-name-disallowed-list': null,
|
||||||
|
'media-feature-name-no-unknown': true,
|
||||||
|
'media-feature-name-no-vendor-prefix': true,
|
||||||
|
'media-feature-name-unit-allowed-list': null,
|
||||||
|
'media-feature-name-value-allowed-list': null,
|
||||||
|
'media-feature-name-value-no-unknown': true,
|
||||||
|
'media-feature-range-notation': null,
|
||||||
|
'media-query-no-invalid': true,
|
||||||
|
'named-grid-areas-no-invalid': true,
|
||||||
|
'no-descending-specificity': null,
|
||||||
|
'no-duplicate-at-import-rules': true,
|
||||||
|
'no-duplicate-selectors': true,
|
||||||
|
'no-empty-source': true,
|
||||||
|
'no-invalid-double-slash-comments': true,
|
||||||
|
'no-invalid-position-at-import-rule': [true, {ignoreAtRules: ['tailwind']}],
|
||||||
|
'no-irregular-whitespace': true,
|
||||||
|
'no-unknown-animations': null,
|
||||||
|
'no-unknown-custom-properties': null,
|
||||||
|
'number-max-precision': null,
|
||||||
|
'plugin/declaration-block-no-ignored-properties': true,
|
||||||
|
'property-allowed-list': null,
|
||||||
|
'property-disallowed-list': null,
|
||||||
|
'property-no-unknown': true,
|
||||||
|
'property-no-vendor-prefix': null,
|
||||||
|
'rule-empty-line-before': null,
|
||||||
|
'rule-selector-property-disallowed-list': null,
|
||||||
|
'scale-unlimited/declaration-strict-value': [['/color$/', 'font-weight'], {ignoreValues: '/^(inherit|transparent|unset|initial|currentcolor|none)$/', ignoreFunctions: false, disableFix: true, expandShorthand: true}],
|
||||||
|
'selector-anb-no-unmatchable': true,
|
||||||
|
'selector-attribute-name-disallowed-list': null,
|
||||||
|
'selector-attribute-operator-allowed-list': null,
|
||||||
|
'selector-attribute-operator-disallowed-list': null,
|
||||||
|
'selector-attribute-quotes': 'always',
|
||||||
|
'selector-class-pattern': null,
|
||||||
|
'selector-combinator-allowed-list': null,
|
||||||
|
'selector-combinator-disallowed-list': null,
|
||||||
|
'selector-disallowed-list': null,
|
||||||
|
'selector-id-pattern': null,
|
||||||
|
'selector-max-attribute': null,
|
||||||
|
'selector-max-class': null,
|
||||||
|
'selector-max-combinators': null,
|
||||||
|
'selector-max-compound-selectors': null,
|
||||||
|
'selector-max-id': null,
|
||||||
|
'selector-max-pseudo-class': null,
|
||||||
|
'selector-max-specificity': null,
|
||||||
|
'selector-max-type': null,
|
||||||
|
'selector-max-universal': null,
|
||||||
|
'selector-nested-pattern': null,
|
||||||
|
'selector-no-qualifying-type': null,
|
||||||
|
'selector-no-vendor-prefix': true,
|
||||||
|
'selector-not-notation': null,
|
||||||
|
'selector-pseudo-class-allowed-list': null,
|
||||||
|
'selector-pseudo-class-disallowed-list': null,
|
||||||
|
'selector-pseudo-class-no-unknown': true,
|
||||||
|
'selector-pseudo-element-allowed-list': null,
|
||||||
|
'selector-pseudo-element-colon-notation': 'double',
|
||||||
|
'selector-pseudo-element-disallowed-list': null,
|
||||||
|
'selector-pseudo-element-no-unknown': true,
|
||||||
|
'selector-type-case': 'lower',
|
||||||
|
'selector-type-no-unknown': [true, {ignore: ['custom-elements']}],
|
||||||
|
'shorthand-property-no-redundant-values': true,
|
||||||
|
'string-no-newline': true,
|
||||||
|
'time-min-milliseconds': null,
|
||||||
|
'unit-allowed-list': null,
|
||||||
|
'unit-disallowed-list': null,
|
||||||
|
'unit-no-unknown': true,
|
||||||
|
'value-keyword-case': null,
|
||||||
|
'value-no-vendor-prefix': [true, {ignoreValues: ['box', 'inline-box']}],
|
||||||
|
},
|
||||||
|
};
|
|
@ -7,14 +7,14 @@
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.disable_gravatar"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.disable_gravatar"}}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.disable_gravatar"}}">
|
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.disable_gravatar"}}">
|
||||||
<input type="checkbox" data-config-dyn-key="picture.disable_gravatar" {{if .SystemConfig.Picture.DisableGravatar.Value ctx}}checked{{end}}>
|
<input type="checkbox" data-config-dyn-key="picture.disable_gravatar" {{if .SystemConfig.Picture.DisableGravatar.Value ctx}}checked{{end}}><label></label>
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}">
|
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}">
|
||||||
<input type="checkbox" data-config-dyn-key="picture.enable_federated_avatar" {{if .SystemConfig.Picture.EnableFederatedAvatar.Value ctx}}checked{{end}}>
|
<input type="checkbox" data-config-dyn-key="picture.enable_federated_avatar" {{if .SystemConfig.Picture.EnableFederatedAvatar.Value ctx}}checked{{end}}><label></label>
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
|
@ -677,7 +677,7 @@
|
||||||
{{if and (not (eq .Issue.PullRequest.HeadRepo.FullName .Issue.PullRequest.BaseRepo.FullName)) .CanWriteToHeadRepo}}
|
{{if and (not (eq .Issue.PullRequest.HeadRepo.FullName .Issue.PullRequest.BaseRepo.FullName)) .CanWriteToHeadRepo}}
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<div class="ui checkbox" id="allow-edits-from-maintainers"
|
<div class="ui checkbox small-loading-icon" id="allow-edits-from-maintainers"
|
||||||
data-url="{{.Issue.Link}}"
|
data-url="{{.Issue.Link}}"
|
||||||
data-tooltip-content="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_desc"}}"
|
data-tooltip-content="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_desc"}}"
|
||||||
data-prompt-error="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_err"}}"
|
data-prompt-error="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_err"}}"
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
--height-loading: 16rem;
|
--height-loading: 16rem;
|
||||||
--min-height-textarea: 132px; /* padding + 6 lines + border = calc(1.57142em + 6lh + 2px), but lh is not fully supported */
|
--min-height-textarea: 132px; /* padding + 6 lines + border = calc(1.57142em + 6lh + 2px), but lh is not fully supported */
|
||||||
--tab-size: 4;
|
--tab-size: 4;
|
||||||
|
--checkbox-size: 16px; /* height and width of checkbox and radio inputs */
|
||||||
}
|
}
|
||||||
|
|
||||||
:root * {
|
:root * {
|
||||||
|
|
|
@ -32,10 +32,7 @@ textarea,
|
||||||
.ui.form input[type="text"],
|
.ui.form input[type="text"],
|
||||||
.ui.form input[type="time"],
|
.ui.form input[type="time"],
|
||||||
.ui.form input[type="url"],
|
.ui.form input[type="url"],
|
||||||
.ui.selection.dropdown,
|
.ui.selection.dropdown {
|
||||||
.ui.checkbox label::before,
|
|
||||||
.ui.checkbox input:checked ~ label::before,
|
|
||||||
.ui.checkbox input:not([type="radio"]):indeterminate ~ label::before {
|
|
||||||
background: var(--color-input-background);
|
background: var(--color-input-background);
|
||||||
border-color: var(--color-input-border);
|
border-color: var(--color-input-border);
|
||||||
color: var(--color-input-text);
|
color: var(--color-input-text);
|
||||||
|
@ -63,12 +60,7 @@ textarea:hover,
|
||||||
.ui.form input[type="text"]:hover,
|
.ui.form input[type="text"]:hover,
|
||||||
.ui.form input[type="time"]:hover,
|
.ui.form input[type="time"]:hover,
|
||||||
.ui.form input[type="url"]:hover,
|
.ui.form input[type="url"]:hover,
|
||||||
.ui.selection.dropdown:hover,
|
.ui.selection.dropdown:hover {
|
||||||
.ui.checkbox label:hover::before,
|
|
||||||
.ui.checkbox label:active::before,
|
|
||||||
.ui.radio.checkbox label::after,
|
|
||||||
.ui.radio.checkbox input:focus ~ label::before,
|
|
||||||
.ui.radio.checkbox input:checked ~ label::before {
|
|
||||||
background: var(--color-input-background);
|
background: var(--color-input-background);
|
||||||
border-color: var(--color-input-border-hover);
|
border-color: var(--color-input-border-hover);
|
||||||
color: var(--color-input-text);
|
color: var(--color-input-text);
|
||||||
|
@ -91,11 +83,7 @@ textarea:focus,
|
||||||
.ui.form input[type="text"]:focus,
|
.ui.form input[type="text"]:focus,
|
||||||
.ui.form input[type="time"]:focus,
|
.ui.form input[type="time"]:focus,
|
||||||
.ui.form input[type="url"]:focus,
|
.ui.form input[type="url"]:focus,
|
||||||
.ui.selection.dropdown:focus,
|
.ui.selection.dropdown:focus {
|
||||||
.ui.checkbox input:focus ~ label::before,
|
|
||||||
.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::before,
|
|
||||||
.ui.checkbox input:checked:focus ~ label::before,
|
|
||||||
.ui.radio.checkbox input:focus:checked ~ label::before {
|
|
||||||
background: var(--color-input-background);
|
background: var(--color-input-background);
|
||||||
border-color: var(--color-primary);
|
border-color: var(--color-primary);
|
||||||
color: var(--color-input-text);
|
color: var(--color-input-text);
|
||||||
|
@ -106,58 +94,21 @@ textarea:focus,
|
||||||
.ui.form .inline.fields .field > label,
|
.ui.form .inline.fields .field > label,
|
||||||
.ui.form .inline.fields .field > p,
|
.ui.form .inline.fields .field > p,
|
||||||
.ui.form .inline.field > label,
|
.ui.form .inline.field > label,
|
||||||
.ui.form .inline.field > p,
|
.ui.form .inline.field > p {
|
||||||
.ui.checkbox label,
|
|
||||||
.ui.checkbox + label,
|
|
||||||
.ui.checkbox label:hover,
|
|
||||||
.ui.checkbox + label:hover,
|
|
||||||
.ui.checkbox input:focus ~ label,
|
|
||||||
.ui.checkbox input:active ~ label {
|
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.form .required.fields:not(.grouped) > .field > label::after,
|
.ui.form .required.fields:not(.grouped) > .field > label::after,
|
||||||
.ui.form .required.fields.grouped > label::after,
|
.ui.form .required.fields.grouped > label::after,
|
||||||
.ui.form .required.field > label::after,
|
.ui.form .required.field > label::after,
|
||||||
.ui.form .required.fields:not(.grouped) > .field > .checkbox::after,
|
|
||||||
.ui.form .required.field > .checkbox::after,
|
|
||||||
.ui.form label.required::after {
|
.ui.form label.required::after {
|
||||||
color: var(--color-red);
|
color: var(--color-red);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.input,
|
.ui.input {
|
||||||
.ui.checkbox input:focus ~ label::after,
|
|
||||||
.ui.checkbox input:checked ~ label::after,
|
|
||||||
.ui.checkbox label:active::after,
|
|
||||||
.ui.checkbox input:not([type="radio"]):indeterminate ~ label::after,
|
|
||||||
.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::after,
|
|
||||||
.ui.checkbox input:checked:focus ~ label::after,
|
|
||||||
.ui.disabled.checkbox label,
|
|
||||||
.ui.checkbox input[disabled] ~ label {
|
|
||||||
color: var(--color-input-text);
|
color: var(--color-input-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.radio.checkbox input:focus ~ label::after,
|
|
||||||
.ui.radio.checkbox input:checked ~ label::after,
|
|
||||||
.ui.radio.checkbox input:focus:checked ~ label::after {
|
|
||||||
background: var(--color-input-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox label::before {
|
|
||||||
background: var(--color-input-toggle-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox label,
|
|
||||||
.ui.toggle.checkbox input:checked ~ label,
|
|
||||||
.ui.toggle.checkbox input:focus:checked ~ label {
|
|
||||||
color: var(--color-text) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input:checked ~ label::before,
|
|
||||||
.ui.toggle.checkbox input:focus:checked ~ label::before {
|
|
||||||
background: var(--color-primary) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* match <select> padding to <input> */
|
/* match <select> padding to <input> */
|
||||||
.ui.form select {
|
.ui.form select {
|
||||||
padding: 0.67857143em 1em;
|
padding: 0.67857143em 1em;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
@import "./modules/message.css";
|
@import "./modules/message.css";
|
||||||
@import "./modules/table.css";
|
@import "./modules/table.css";
|
||||||
@import "./modules/card.css";
|
@import "./modules/card.css";
|
||||||
|
@import "./modules/checkbox.css";
|
||||||
@import "./modules/modal.css";
|
@import "./modules/modal.css";
|
||||||
|
|
||||||
@import "./modules/select.css";
|
@import "./modules/select.css";
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
.is-loading {
|
.is-loading {
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
overflow: hidden !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-loading > * {
|
.is-loading > * {
|
||||||
|
|
120
web_src/css/modules/checkbox.css
Normal file
120
web_src/css/modules/checkbox.css
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/* based on Fomantic UI checkbox module, with just the parts extracted that we use. If you find any
|
||||||
|
unused rules here after refactoring, please remove them. */
|
||||||
|
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
width: var(--checkbox-size);
|
||||||
|
height: var(--checkbox-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.checkbox {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: baseline;
|
||||||
|
min-height: var(--checkbox-size);
|
||||||
|
line-height: var(--checkbox-size);
|
||||||
|
min-width: var(--checkbox-size);
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.checkbox input[type="checkbox"],
|
||||||
|
.ui.checkbox input[type="radio"] {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: var(--checkbox-size);
|
||||||
|
height: var(--checkbox-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.checkbox input[type="checkbox"]:enabled,
|
||||||
|
.ui.checkbox input[type="radio"]:enabled,
|
||||||
|
.ui.checkbox label:enabled {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.checkbox label {
|
||||||
|
cursor: auto;
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.checkbox label,
|
||||||
|
.ui.radio.checkbox label {
|
||||||
|
padding-left: 1.85714em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.checkbox + label {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.disabled.checkbox label,
|
||||||
|
.ui.checkbox input[disabled] ~ label {
|
||||||
|
cursor: default !important;
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.radio.checkbox {
|
||||||
|
min-height: var(--checkbox-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "switch" styled checkbox */
|
||||||
|
|
||||||
|
.ui.toggle.checkbox {
|
||||||
|
min-height: 1.5rem;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox input {
|
||||||
|
width: 3.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox label {
|
||||||
|
min-height: 1.5rem;
|
||||||
|
padding-left: 4.5rem;
|
||||||
|
padding-top: 0.15em;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox label::before {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
z-index: 1;
|
||||||
|
top: 0;
|
||||||
|
width: 3.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
border-radius: 500rem;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox label::after {
|
||||||
|
background: var(--color-white);
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 2;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
border-radius: 500rem;
|
||||||
|
transition: background 0.3s ease, left 0.3s ease;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox input ~ label::after {
|
||||||
|
left: -0.05rem;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox input:checked ~ label::after {
|
||||||
|
left: 2.15rem;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox input:focus ~ label::before,
|
||||||
|
.ui.toggle.checkbox label::before {
|
||||||
|
background: var(--color-input-toggle-background);
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox label,
|
||||||
|
.ui.toggle.checkbox input:checked ~ label,
|
||||||
|
.ui.toggle.checkbox input:focus:checked ~ label {
|
||||||
|
color: var(--color-text) !important;
|
||||||
|
}
|
||||||
|
.ui.toggle.checkbox input:checked ~ label::before,
|
||||||
|
.ui.toggle.checkbox input:focus:checked ~ label::before {
|
||||||
|
background: var(--color-primary) !important;
|
||||||
|
}
|
|
@ -69,7 +69,8 @@
|
||||||
border-radius: 0 0 0.28571429rem 0.28571429rem;
|
border-radius: 0 0 0.28571429rem 0.28571429rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.segments:not(.horizontal) > .segment:only-child {
|
.ui.segments:not(.horizontal) > .segment:only-child,
|
||||||
|
.ui.segments:not(.horizontal) > .segment:has(~ .tw-hidden) { /* workaround issue with :last-child ignoring hidden elements */
|
||||||
border-radius: 0.28571429rem;
|
border-radius: 0.28571429rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,10 +89,6 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.organization.options input {
|
|
||||||
min-width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-content.organization .org-avatar {
|
.page-content.organization .org-avatar {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
.issue-list-toolbar-left {
|
.issue-list-toolbar-left {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.issue-list-toolbar-right .filter.menu {
|
.issue-list-toolbar-right .filter.menu {
|
||||||
|
|
709
web_src/fomantic/build/semantic.css
generated
709
web_src/fomantic/build/semantic.css
generated
|
@ -2323,715 +2323,6 @@
|
||||||
Theme Overrides
|
Theme Overrides
|
||||||
*******************************/
|
*******************************/
|
||||||
|
|
||||||
/*******************************
|
|
||||||
Site Overrides
|
|
||||||
*******************************/
|
|
||||||
/*!
|
|
||||||
* # Fomantic-UI - Checkbox
|
|
||||||
* http://github.com/fomantic/Fomantic-UI/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Released under the MIT license
|
|
||||||
* http://opensource.org/licenses/MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*******************************
|
|
||||||
Checkbox
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Content
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
outline: none;
|
|
||||||
vertical-align: baseline;
|
|
||||||
font-style: normal;
|
|
||||||
min-height: 17px;
|
|
||||||
font-size: 1em;
|
|
||||||
line-height: 17px;
|
|
||||||
min-width: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HTML Checkbox */
|
|
||||||
|
|
||||||
.ui.checkbox input[type="checkbox"],
|
|
||||||
.ui.checkbox input[type="radio"] {
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
opacity: 0 !important;
|
|
||||||
outline: none;
|
|
||||||
z-index: 3;
|
|
||||||
width: 17px;
|
|
||||||
height: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox label {
|
|
||||||
cursor: auto;
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
padding-left: 1.85714em;
|
|
||||||
outline: none;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox label:before {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 17px;
|
|
||||||
height: 17px;
|
|
||||||
content: '';
|
|
||||||
background: #FFFFFF;
|
|
||||||
border-radius: 0.21428571rem;
|
|
||||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease;
|
|
||||||
border: 1px solid #D4D4D5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Checkmark
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox label:after {
|
|
||||||
position: absolute;
|
|
||||||
font-size: 14px;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 17px;
|
|
||||||
height: 17px;
|
|
||||||
text-align: center;
|
|
||||||
opacity: 0;
|
|
||||||
color: rgba(0, 0, 0, 0.87);
|
|
||||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Label
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
/* Inside */
|
|
||||||
|
|
||||||
.ui.checkbox label,
|
|
||||||
.ui.checkbox + label {
|
|
||||||
color: rgba(0, 0, 0, 0.87);
|
|
||||||
transition: color 0.1s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Outside */
|
|
||||||
|
|
||||||
.ui.checkbox + label {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************
|
|
||||||
States
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Hover
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox label:hover::before {
|
|
||||||
background: #FFFFFF;
|
|
||||||
border-color: rgba(34, 36, 38, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox label:hover,
|
|
||||||
.ui.checkbox + label:hover {
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Down
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox label:active::before {
|
|
||||||
background: #F9FAFB;
|
|
||||||
border-color: rgba(34, 36, 38, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox label:active::after {
|
|
||||||
color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox input:active ~ label {
|
|
||||||
color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Focus
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox input:focus ~ label:before {
|
|
||||||
background: #FFFFFF;
|
|
||||||
border-color: #96C8DA;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox input:focus ~ label:after {
|
|
||||||
color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox input:focus ~ label {
|
|
||||||
color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Active
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox input:checked ~ label:before {
|
|
||||||
background: #FFFFFF;
|
|
||||||
border-color: rgba(34, 36, 38, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox input:checked ~ label:after {
|
|
||||||
opacity: 1;
|
|
||||||
color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Indeterminate
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox input:not([type=radio]):indeterminate ~ label:before {
|
|
||||||
background: #FFFFFF;
|
|
||||||
border-color: rgba(34, 36, 38, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox input:not([type=radio]):indeterminate ~ label:after {
|
|
||||||
opacity: 1;
|
|
||||||
color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.indeterminate.toggle.checkbox input:not([type=radio]):indeterminate ~ label:before {
|
|
||||||
background: rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.indeterminate.toggle.checkbox input:not([type=radio]) ~ label:after {
|
|
||||||
left: 1.075rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Active Focus
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:before,
|
|
||||||
.ui.checkbox input:checked:focus ~ label:before {
|
|
||||||
background: #FFFFFF;
|
|
||||||
border-color: #96C8DA;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:after,
|
|
||||||
.ui.checkbox input:checked:focus ~ label:after {
|
|
||||||
color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Read-Only
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.read-only.checkbox,
|
|
||||||
.ui.read-only.checkbox label {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Disabled
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.disabled.checkbox label,
|
|
||||||
.ui.checkbox input[disabled] ~ label {
|
|
||||||
cursor: default !important;
|
|
||||||
opacity: 0.5;
|
|
||||||
color: #000000;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Hidden
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
/* Initialized checkbox moves input below element
|
|
||||||
to prevent manually triggering */
|
|
||||||
|
|
||||||
.ui.checkbox input.hidden {
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Selectable Label */
|
|
||||||
|
|
||||||
.ui.checkbox input.hidden + label {
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************
|
|
||||||
Types
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Radio
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.radio.checkbox {
|
|
||||||
min-height: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.radio.checkbox label {
|
|
||||||
padding-left: 1.85714em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Box */
|
|
||||||
|
|
||||||
.ui.radio.checkbox label:before {
|
|
||||||
content: '';
|
|
||||||
transform: none;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
border-radius: 500rem;
|
|
||||||
top: 1px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bullet */
|
|
||||||
|
|
||||||
.ui.radio.checkbox label:after {
|
|
||||||
border: none;
|
|
||||||
content: '' !important;
|
|
||||||
line-height: 15px;
|
|
||||||
top: 1px;
|
|
||||||
left: 0;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
border-radius: 500rem;
|
|
||||||
transform: scale(0.46666667);
|
|
||||||
background-color: rgba(0, 0, 0, 0.87);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Focus */
|
|
||||||
|
|
||||||
.ui.radio.checkbox input:focus ~ label:before {
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.radio.checkbox input:focus ~ label:after {
|
|
||||||
background-color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Indeterminate */
|
|
||||||
|
|
||||||
.ui.radio.checkbox input:indeterminate ~ label:after {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active */
|
|
||||||
|
|
||||||
.ui.radio.checkbox input:checked ~ label:before {
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.radio.checkbox input:checked ~ label:after {
|
|
||||||
background-color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active Focus */
|
|
||||||
|
|
||||||
.ui.radio.checkbox input:focus:checked ~ label:before {
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.radio.checkbox input:focus:checked ~ label:after {
|
|
||||||
background-color: rgba(0, 0, 0, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Slider
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.slider.checkbox {
|
|
||||||
min-height: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input */
|
|
||||||
|
|
||||||
.ui.slider.checkbox input {
|
|
||||||
width: 3.5rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Label */
|
|
||||||
|
|
||||||
.ui.slider.checkbox label {
|
|
||||||
padding-left: 4.5rem;
|
|
||||||
line-height: 1rem;
|
|
||||||
color: rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Line */
|
|
||||||
|
|
||||||
.ui.slider.checkbox label:before {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
content: '';
|
|
||||||
transform: none;
|
|
||||||
border: none !important;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1;
|
|
||||||
top: 0.4rem;
|
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
|
||||||
width: 3.5rem;
|
|
||||||
height: 0.21428571rem;
|
|
||||||
border-radius: 500rem;
|
|
||||||
transition: background 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle */
|
|
||||||
|
|
||||||
.ui.slider.checkbox label:after {
|
|
||||||
background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05));
|
|
||||||
position: absolute;
|
|
||||||
content: '' !important;
|
|
||||||
opacity: 1;
|
|
||||||
z-index: 2;
|
|
||||||
border: none;
|
|
||||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
|
||||||
width: 1.5rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
top: -0.25rem;
|
|
||||||
left: 0;
|
|
||||||
transform: none;
|
|
||||||
border-radius: 500rem;
|
|
||||||
transition: left 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Focus */
|
|
||||||
|
|
||||||
.ui.slider.checkbox input:focus ~ label:before {
|
|
||||||
background-color: rgba(0, 0, 0, 0.15);
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hover */
|
|
||||||
|
|
||||||
.ui.slider.checkbox label:hover {
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.slider.checkbox label:hover::before {
|
|
||||||
background: rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active */
|
|
||||||
|
|
||||||
.ui.slider.checkbox input:checked ~ label {
|
|
||||||
color: rgba(0, 0, 0, 0.95) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.slider.checkbox input:checked ~ label:before {
|
|
||||||
background-color: #545454 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.slider.checkbox input:checked ~ label:after {
|
|
||||||
left: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active Focus */
|
|
||||||
|
|
||||||
.ui.slider.checkbox input:focus:checked ~ label {
|
|
||||||
color: rgba(0, 0, 0, 0.95) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.slider.checkbox input:focus:checked ~ label:before {
|
|
||||||
background-color: #000000 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Toggle
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.toggle.checkbox {
|
|
||||||
min-height: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input {
|
|
||||||
width: 3.5rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Label */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox label {
|
|
||||||
min-height: 1.5rem;
|
|
||||||
padding-left: 4.5rem;
|
|
||||||
color: rgba(0, 0, 0, 0.87);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox label {
|
|
||||||
padding-top: 0.15em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Switch */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox label:before {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
content: '';
|
|
||||||
z-index: 1;
|
|
||||||
transform: none;
|
|
||||||
border: none;
|
|
||||||
top: 0;
|
|
||||||
background: rgba(0, 0, 0, 0.05);
|
|
||||||
box-shadow: none;
|
|
||||||
width: 3.5rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
border-radius: 500rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox label:after {
|
|
||||||
background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05));
|
|
||||||
position: absolute;
|
|
||||||
content: '' !important;
|
|
||||||
opacity: 1;
|
|
||||||
z-index: 2;
|
|
||||||
border: none;
|
|
||||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
|
||||||
width: 1.5rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
border-radius: 500rem;
|
|
||||||
transition: background 0.3s ease, left 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input ~ label:after {
|
|
||||||
left: -0.05rem;
|
|
||||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Focus */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input:focus ~ label:before {
|
|
||||||
background-color: rgba(0, 0, 0, 0.15);
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hover */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox label:hover::before {
|
|
||||||
background-color: rgba(0, 0, 0, 0.15);
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input:checked ~ label {
|
|
||||||
color: rgba(0, 0, 0, 0.95) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input:checked ~ label:before {
|
|
||||||
background-color: #2185D0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input:checked ~ label:after {
|
|
||||||
left: 2.15rem;
|
|
||||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active Focus */
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input:focus:checked ~ label {
|
|
||||||
color: rgba(0, 0, 0, 0.95) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.toggle.checkbox input:focus:checked ~ label:before {
|
|
||||||
background-color: #0d71bb !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************
|
|
||||||
Variations
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
/*--------------
|
|
||||||
Fitted
|
|
||||||
---------------*/
|
|
||||||
|
|
||||||
.ui.fitted.checkbox label {
|
|
||||||
padding-left: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.fitted.toggle.checkbox {
|
|
||||||
width: 3.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.fitted.slider.checkbox {
|
|
||||||
width: 3.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------
|
|
||||||
Size
|
|
||||||
---------------------*/
|
|
||||||
|
|
||||||
.ui.mini.checkbox {
|
|
||||||
font-size: 0.78571429em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.tiny.checkbox {
|
|
||||||
font-size: 0.85714286em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.small.checkbox {
|
|
||||||
font-size: 0.92857143em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.large.checkbox {
|
|
||||||
font-size: 1.14285714em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.large.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.large.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.large.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
|
||||||
.ui.large.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
|
||||||
transform: scale(1.14285714);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.large.form .checkbox.radio label:before,
|
|
||||||
.ui.large.checkbox.radio label:before {
|
|
||||||
transform: scale(1.14285714);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.large.form .checkbox.radio label:after,
|
|
||||||
.ui.large.checkbox.radio label:after {
|
|
||||||
transform: scale(0.57142857);
|
|
||||||
transform-origin: left;
|
|
||||||
left: 0.33571429em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.big.checkbox {
|
|
||||||
font-size: 1.28571429em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.big.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.big.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.big.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
|
||||||
.ui.big.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
|
||||||
transform: scale(1.28571429);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.big.form .checkbox.radio label:before,
|
|
||||||
.ui.big.checkbox.radio label:before {
|
|
||||||
transform: scale(1.28571429);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.big.form .checkbox.radio label:after,
|
|
||||||
.ui.big.checkbox.radio label:after {
|
|
||||||
transform: scale(0.64285714);
|
|
||||||
transform-origin: left;
|
|
||||||
left: 0.37142857em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.huge.checkbox {
|
|
||||||
font-size: 1.42857143em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.huge.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.huge.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.huge.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
|
||||||
.ui.huge.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
|
||||||
transform: scale(1.42857143);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.huge.form .checkbox.radio label:before,
|
|
||||||
.ui.huge.checkbox.radio label:before {
|
|
||||||
transform: scale(1.42857143);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.huge.form .checkbox.radio label:after,
|
|
||||||
.ui.huge.checkbox.radio label:after {
|
|
||||||
transform: scale(0.71428571);
|
|
||||||
transform-origin: left;
|
|
||||||
left: 0.40714286em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.massive.checkbox {
|
|
||||||
font-size: 1.71428571em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.massive.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.massive.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
|
||||||
.ui.massive.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
|
||||||
.ui.massive.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
|
||||||
transform: scale(1.71428571);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.massive.form .checkbox.radio label:before,
|
|
||||||
.ui.massive.checkbox.radio label:before {
|
|
||||||
transform: scale(1.71428571);
|
|
||||||
transform-origin: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.massive.form .checkbox.radio label:after,
|
|
||||||
.ui.massive.checkbox.radio label:after {
|
|
||||||
transform: scale(0.85714286);
|
|
||||||
transform-origin: left;
|
|
||||||
left: 0.47857143em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************
|
|
||||||
Theme Overrides
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Checkbox';
|
|
||||||
src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBD8AAAC8AAAAYGNtYXAYVtCJAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zn4huwUAAAF4AAABYGhlYWQGPe1ZAAAC2AAAADZoaGVhB30DyAAAAxAAAAAkaG10eBBKAEUAAAM0AAAAHGxvY2EAmgESAAADUAAAABBtYXhwAAkALwAAA2AAAAAgbmFtZSC8IugAAAOAAAABknBvc3QAAwAAAAAFFAAAACAAAwMTAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADoAgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6AL//f//AAAAAAAg6AD//f//AAH/4xgEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAEUAUQO7AvgAGgAAARQHAQYjIicBJjU0PwE2MzIfAQE2MzIfARYVA7sQ/hQQFhcQ/uMQEE4QFxcQqAF2EBcXEE4QAnMWEP4UEBABHRAXFhBOEBCoAXcQEE4QFwAAAAABAAABbgMlAkkAFAAAARUUBwYjISInJj0BNDc2MyEyFxYVAyUQEBf9SRcQEBAQFwK3FxAQAhJtFxAQEBAXbRcQEBAQFwAAAAABAAAASQMlA24ALAAAARUUBwYrARUUBwYrASInJj0BIyInJj0BNDc2OwE1NDc2OwEyFxYdATMyFxYVAyUQEBfuEBAXbhYQEO4XEBAQEBfuEBAWbhcQEO4XEBACEm0XEBDuFxAQEBAX7hAQF20XEBDuFxAQEBAX7hAQFwAAAQAAAAIAAHRSzT9fDzz1AAsEAAAAAADRsdR3AAAAANGx1HcAAAAAA7sDbgAAAAgAAgAAAAAAAAABAAADwP/AAAAEAAAAAAADuwABAAAAAAAAAAAAAAAAAAAABwQAAAAAAAAAAAAAAAIAAAAEAABFAyUAAAMlAAAAAAAAAAoAFAAeAE4AcgCwAAEAAAAHAC0AAQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAIAAAAAQAAAAAAAgAHAGkAAQAAAAAAAwAIADkAAQAAAAAABAAIAH4AAQAAAAAABQALABgAAQAAAAAABgAIAFEAAQAAAAAACgAaAJYAAwABBAkAAQAQAAgAAwABBAkAAgAOAHAAAwABBAkAAwAQAEEAAwABBAkABAAQAIYAAwABBAkABQAWACMAAwABBAkABgAQAFkAAwABBAkACgA0ALBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhWZXJzaW9uIDIuMABWAGUAcgBzAGkAbwBuACAAMgAuADBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhDaGVja2JveABDAGgAZQBjAGsAYgBvAHhSZWd1bGFyAFIAZQBnAHUAbABhAHJDaGVja2JveABDAGgAZQBjAGsAYgBvAHhGb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checkmark */
|
|
||||||
|
|
||||||
.ui.checkbox label:after,
|
|
||||||
.ui.checkbox .box:after {
|
|
||||||
font-family: 'Checkbox';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checked */
|
|
||||||
|
|
||||||
.ui.checkbox input:checked ~ .box:after,
|
|
||||||
.ui.checkbox input:checked ~ label:after {
|
|
||||||
content: '\e800';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Indeterminate */
|
|
||||||
|
|
||||||
.ui.checkbox input:indeterminate ~ .box:after,
|
|
||||||
.ui.checkbox input:indeterminate ~ label:after {
|
|
||||||
font-size: 12px;
|
|
||||||
content: '\e801';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UTF Reference
|
|
||||||
.check:before { content: '\e800'; }
|
|
||||||
.dash:before { content: '\e801'; }
|
|
||||||
.plus:before { content: '\e802'; }
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*******************************
|
/*******************************
|
||||||
Site Overrides
|
Site Overrides
|
||||||
*******************************/
|
*******************************/
|
||||||
|
|
877
web_src/fomantic/build/semantic.js
generated
877
web_src/fomantic/build/semantic.js
generated
|
@ -1184,883 +1184,6 @@ $.api.settings = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})( jQuery, window, document );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* # Fomantic-UI - Checkbox
|
|
||||||
* http://github.com/fomantic/Fomantic-UI/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Released under the MIT license
|
|
||||||
* http://opensource.org/licenses/MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
;(function ($, window, document, undefined) {
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
$.isFunction = $.isFunction || function(obj) {
|
|
||||||
return typeof obj === "function" && typeof obj.nodeType !== "number";
|
|
||||||
};
|
|
||||||
|
|
||||||
window = (typeof window != 'undefined' && window.Math == Math)
|
|
||||||
? window
|
|
||||||
: (typeof self != 'undefined' && self.Math == Math)
|
|
||||||
? self
|
|
||||||
: Function('return this')()
|
|
||||||
;
|
|
||||||
|
|
||||||
$.fn.checkbox = function(parameters) {
|
|
||||||
var
|
|
||||||
$allModules = $(this),
|
|
||||||
moduleSelector = $allModules.selector || '',
|
|
||||||
|
|
||||||
time = new Date().getTime(),
|
|
||||||
performance = [],
|
|
||||||
|
|
||||||
query = arguments[0],
|
|
||||||
methodInvoked = (typeof query == 'string'),
|
|
||||||
queryArguments = [].slice.call(arguments, 1),
|
|
||||||
returnedValue
|
|
||||||
;
|
|
||||||
|
|
||||||
$allModules
|
|
||||||
.each(function() {
|
|
||||||
var
|
|
||||||
settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
|
|
||||||
|
|
||||||
className = settings.className,
|
|
||||||
namespace = settings.namespace,
|
|
||||||
selector = settings.selector,
|
|
||||||
error = settings.error,
|
|
||||||
|
|
||||||
eventNamespace = '.' + namespace,
|
|
||||||
moduleNamespace = 'module-' + namespace,
|
|
||||||
|
|
||||||
$module = $(this),
|
|
||||||
$label = $(this).children(selector.label),
|
|
||||||
$input = $(this).children(selector.input),
|
|
||||||
input = $input[0],
|
|
||||||
|
|
||||||
initialLoad = false,
|
|
||||||
shortcutPressed = false,
|
|
||||||
instance = $module.data(moduleNamespace),
|
|
||||||
|
|
||||||
observer,
|
|
||||||
element = this,
|
|
||||||
module
|
|
||||||
;
|
|
||||||
|
|
||||||
module = {
|
|
||||||
|
|
||||||
initialize: function() {
|
|
||||||
module.verbose('Initializing checkbox', settings);
|
|
||||||
|
|
||||||
module.create.label();
|
|
||||||
module.bind.events();
|
|
||||||
|
|
||||||
module.set.tabbable();
|
|
||||||
module.hide.input();
|
|
||||||
|
|
||||||
module.observeChanges();
|
|
||||||
module.instantiate();
|
|
||||||
module.setup();
|
|
||||||
},
|
|
||||||
|
|
||||||
instantiate: function() {
|
|
||||||
module.verbose('Storing instance of module', module);
|
|
||||||
instance = module;
|
|
||||||
$module
|
|
||||||
.data(moduleNamespace, module)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function() {
|
|
||||||
module.verbose('Destroying module');
|
|
||||||
module.unbind.events();
|
|
||||||
module.show.input();
|
|
||||||
$module.removeData(moduleNamespace);
|
|
||||||
},
|
|
||||||
|
|
||||||
fix: {
|
|
||||||
reference: function() {
|
|
||||||
if( $module.is(selector.input) ) {
|
|
||||||
module.debug('Behavior called on <input> adjusting invoked element');
|
|
||||||
$module = $module.closest(selector.checkbox);
|
|
||||||
module.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup: function() {
|
|
||||||
module.set.initialLoad();
|
|
||||||
if( module.is.indeterminate() ) {
|
|
||||||
module.debug('Initial value is indeterminate');
|
|
||||||
module.indeterminate();
|
|
||||||
}
|
|
||||||
else if( module.is.checked() ) {
|
|
||||||
module.debug('Initial value is checked');
|
|
||||||
module.check();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
module.debug('Initial value is unchecked');
|
|
||||||
module.uncheck();
|
|
||||||
}
|
|
||||||
module.remove.initialLoad();
|
|
||||||
},
|
|
||||||
|
|
||||||
refresh: function() {
|
|
||||||
$label = $module.children(selector.label);
|
|
||||||
$input = $module.children(selector.input);
|
|
||||||
input = $input[0];
|
|
||||||
},
|
|
||||||
|
|
||||||
hide: {
|
|
||||||
input: function() {
|
|
||||||
module.verbose('Modifying <input> z-index to be unselectable');
|
|
||||||
$input.addClass(className.hidden);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
show: {
|
|
||||||
input: function() {
|
|
||||||
module.verbose('Modifying <input> z-index to be selectable');
|
|
||||||
$input.removeClass(className.hidden);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
observeChanges: function() {
|
|
||||||
if('MutationObserver' in window) {
|
|
||||||
observer = new MutationObserver(function(mutations) {
|
|
||||||
module.debug('DOM tree modified, updating selector cache');
|
|
||||||
module.refresh();
|
|
||||||
});
|
|
||||||
observer.observe(element, {
|
|
||||||
childList : true,
|
|
||||||
subtree : true
|
|
||||||
});
|
|
||||||
module.debug('Setting up mutation observer', observer);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
attachEvents: function(selector, event) {
|
|
||||||
var
|
|
||||||
$element = $(selector)
|
|
||||||
;
|
|
||||||
event = $.isFunction(module[event])
|
|
||||||
? module[event]
|
|
||||||
: module.toggle
|
|
||||||
;
|
|
||||||
if($element.length > 0) {
|
|
||||||
module.debug('Attaching checkbox events to element', selector, event);
|
|
||||||
$element
|
|
||||||
.on('click' + eventNamespace, event)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
module.error(error.notFound);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
preventDefaultOnInputTarget: function() {
|
|
||||||
if(typeof event !== 'undefined' && event !== null && $(event.target).is(selector.input)) {
|
|
||||||
module.verbose('Preventing default check action after manual check action');
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
event: {
|
|
||||||
change: function(event) {
|
|
||||||
if( !module.should.ignoreCallbacks() ) {
|
|
||||||
settings.onChange.call(input);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
click: function(event) {
|
|
||||||
var
|
|
||||||
$target = $(event.target)
|
|
||||||
;
|
|
||||||
if( $target.is(selector.input) ) {
|
|
||||||
module.verbose('Using default check action on initialized checkbox');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( $target.is(selector.link) ) {
|
|
||||||
module.debug('Clicking link inside checkbox, skipping toggle');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.toggle();
|
|
||||||
$input.focus();
|
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
keydown: function(event) {
|
|
||||||
var
|
|
||||||
key = event.which,
|
|
||||||
keyCode = {
|
|
||||||
enter : 13,
|
|
||||||
space : 32,
|
|
||||||
escape : 27,
|
|
||||||
left : 37,
|
|
||||||
up : 38,
|
|
||||||
right : 39,
|
|
||||||
down : 40
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
var r = module.get.radios(),
|
|
||||||
rIndex = r.index($module),
|
|
||||||
rLen = r.length,
|
|
||||||
checkIndex = false;
|
|
||||||
|
|
||||||
if(key == keyCode.left || key == keyCode.up) {
|
|
||||||
checkIndex = (rIndex === 0 ? rLen : rIndex) - 1;
|
|
||||||
} else if(key == keyCode.right || key == keyCode.down) {
|
|
||||||
checkIndex = rIndex === rLen-1 ? 0 : rIndex+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!module.should.ignoreCallbacks() && checkIndex !== false) {
|
|
||||||
if(settings.beforeUnchecked.apply(input)===false) {
|
|
||||||
module.verbose('Option not allowed to be unchecked, cancelling key navigation');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (settings.beforeChecked.apply($(r[checkIndex]).children(selector.input)[0])===false) {
|
|
||||||
module.verbose('Next option should not allow check, cancelling key navigation');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key == keyCode.escape) {
|
|
||||||
module.verbose('Escape key pressed blurring field');
|
|
||||||
$input.blur();
|
|
||||||
shortcutPressed = true;
|
|
||||||
}
|
|
||||||
else if(!event.ctrlKey && ( key == keyCode.space || (key == keyCode.enter && settings.enableEnterKey)) ) {
|
|
||||||
module.verbose('Enter/space key pressed, toggling checkbox');
|
|
||||||
module.toggle();
|
|
||||||
shortcutPressed = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
shortcutPressed = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
keyup: function(event) {
|
|
||||||
if(shortcutPressed) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
check: function() {
|
|
||||||
if( !module.should.allowCheck() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Checking checkbox', $input);
|
|
||||||
module.set.checked();
|
|
||||||
if( !module.should.ignoreCallbacks() ) {
|
|
||||||
settings.onChecked.call(input);
|
|
||||||
module.trigger.change();
|
|
||||||
}
|
|
||||||
module.preventDefaultOnInputTarget();
|
|
||||||
},
|
|
||||||
|
|
||||||
uncheck: function() {
|
|
||||||
if( !module.should.allowUncheck() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Unchecking checkbox');
|
|
||||||
module.set.unchecked();
|
|
||||||
if( !module.should.ignoreCallbacks() ) {
|
|
||||||
settings.onUnchecked.call(input);
|
|
||||||
module.trigger.change();
|
|
||||||
}
|
|
||||||
module.preventDefaultOnInputTarget();
|
|
||||||
},
|
|
||||||
|
|
||||||
indeterminate: function() {
|
|
||||||
if( module.should.allowIndeterminate() ) {
|
|
||||||
module.debug('Checkbox is already indeterminate');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Making checkbox indeterminate');
|
|
||||||
module.set.indeterminate();
|
|
||||||
if( !module.should.ignoreCallbacks() ) {
|
|
||||||
settings.onIndeterminate.call(input);
|
|
||||||
module.trigger.change();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
determinate: function() {
|
|
||||||
if( module.should.allowDeterminate() ) {
|
|
||||||
module.debug('Checkbox is already determinate');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Making checkbox determinate');
|
|
||||||
module.set.determinate();
|
|
||||||
if( !module.should.ignoreCallbacks() ) {
|
|
||||||
settings.onDeterminate.call(input);
|
|
||||||
module.trigger.change();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
if( module.is.enabled() ) {
|
|
||||||
module.debug('Checkbox is already enabled');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Enabling checkbox');
|
|
||||||
module.set.enabled();
|
|
||||||
if( !module.should.ignoreCallbacks() ) {
|
|
||||||
settings.onEnable.call(input);
|
|
||||||
// preserve legacy callbacks
|
|
||||||
settings.onEnabled.call(input);
|
|
||||||
module.trigger.change();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
if( module.is.disabled() ) {
|
|
||||||
module.debug('Checkbox is already disabled');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Disabling checkbox');
|
|
||||||
module.set.disabled();
|
|
||||||
if( !module.should.ignoreCallbacks() ) {
|
|
||||||
settings.onDisable.call(input);
|
|
||||||
// preserve legacy callbacks
|
|
||||||
settings.onDisabled.call(input);
|
|
||||||
module.trigger.change();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
get: {
|
|
||||||
radios: function() {
|
|
||||||
var
|
|
||||||
name = module.get.name()
|
|
||||||
;
|
|
||||||
return $('input[name="' + name + '"]').closest(selector.checkbox);
|
|
||||||
},
|
|
||||||
otherRadios: function() {
|
|
||||||
return module.get.radios().not($module);
|
|
||||||
},
|
|
||||||
name: function() {
|
|
||||||
return $input.attr('name');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
is: {
|
|
||||||
initialLoad: function() {
|
|
||||||
return initialLoad;
|
|
||||||
},
|
|
||||||
radio: function() {
|
|
||||||
return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
|
|
||||||
},
|
|
||||||
indeterminate: function() {
|
|
||||||
return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
|
|
||||||
},
|
|
||||||
checked: function() {
|
|
||||||
return $input.prop('checked') !== undefined && $input.prop('checked');
|
|
||||||
},
|
|
||||||
disabled: function() {
|
|
||||||
return $input.prop('disabled') !== undefined && $input.prop('disabled');
|
|
||||||
},
|
|
||||||
enabled: function() {
|
|
||||||
return !module.is.disabled();
|
|
||||||
},
|
|
||||||
determinate: function() {
|
|
||||||
return !module.is.indeterminate();
|
|
||||||
},
|
|
||||||
unchecked: function() {
|
|
||||||
return !module.is.checked();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
should: {
|
|
||||||
allowCheck: function() {
|
|
||||||
if(module.is.determinate() && module.is.checked() && !module.is.initialLoad() ) {
|
|
||||||
module.debug('Should not allow check, checkbox is already checked');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!module.should.ignoreCallbacks() && settings.beforeChecked.apply(input) === false) {
|
|
||||||
module.debug('Should not allow check, beforeChecked cancelled');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
allowUncheck: function() {
|
|
||||||
if(module.is.determinate() && module.is.unchecked() && !module.is.initialLoad() ) {
|
|
||||||
module.debug('Should not allow uncheck, checkbox is already unchecked');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!module.should.ignoreCallbacks() && settings.beforeUnchecked.apply(input) === false) {
|
|
||||||
module.debug('Should not allow uncheck, beforeUnchecked cancelled');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
allowIndeterminate: function() {
|
|
||||||
if(module.is.indeterminate() && !module.is.initialLoad() ) {
|
|
||||||
module.debug('Should not allow indeterminate, checkbox is already indeterminate');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!module.should.ignoreCallbacks() && settings.beforeIndeterminate.apply(input) === false) {
|
|
||||||
module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
allowDeterminate: function() {
|
|
||||||
if(module.is.determinate() && !module.is.initialLoad() ) {
|
|
||||||
module.debug('Should not allow determinate, checkbox is already determinate');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!module.should.ignoreCallbacks() && settings.beforeDeterminate.apply(input) === false) {
|
|
||||||
module.debug('Should not allow determinate, beforeDeterminate cancelled');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
ignoreCallbacks: function() {
|
|
||||||
return (initialLoad && !settings.fireOnInit);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
can: {
|
|
||||||
change: function() {
|
|
||||||
return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
|
|
||||||
},
|
|
||||||
uncheck: function() {
|
|
||||||
return (typeof settings.uncheckable === 'boolean')
|
|
||||||
? settings.uncheckable
|
|
||||||
: !module.is.radio()
|
|
||||||
;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
set: {
|
|
||||||
initialLoad: function() {
|
|
||||||
initialLoad = true;
|
|
||||||
},
|
|
||||||
checked: function() {
|
|
||||||
module.verbose('Setting class to checked');
|
|
||||||
$module
|
|
||||||
.removeClass(className.indeterminate)
|
|
||||||
.addClass(className.checked)
|
|
||||||
;
|
|
||||||
if( module.is.radio() ) {
|
|
||||||
module.uncheckOthers();
|
|
||||||
}
|
|
||||||
if(!module.is.indeterminate() && module.is.checked()) {
|
|
||||||
module.debug('Input is already checked, skipping input property change');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.verbose('Setting state to checked', input);
|
|
||||||
$input
|
|
||||||
.prop('indeterminate', false)
|
|
||||||
.prop('checked', true)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
unchecked: function() {
|
|
||||||
module.verbose('Removing checked class');
|
|
||||||
$module
|
|
||||||
.removeClass(className.indeterminate)
|
|
||||||
.removeClass(className.checked)
|
|
||||||
;
|
|
||||||
if(!module.is.indeterminate() && module.is.unchecked() ) {
|
|
||||||
module.debug('Input is already unchecked');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Setting state to unchecked');
|
|
||||||
$input
|
|
||||||
.prop('indeterminate', false)
|
|
||||||
.prop('checked', false)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
indeterminate: function() {
|
|
||||||
module.verbose('Setting class to indeterminate');
|
|
||||||
$module
|
|
||||||
.addClass(className.indeterminate)
|
|
||||||
;
|
|
||||||
if( module.is.indeterminate() ) {
|
|
||||||
module.debug('Input is already indeterminate, skipping input property change');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Setting state to indeterminate');
|
|
||||||
$input
|
|
||||||
.prop('indeterminate', true)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
determinate: function() {
|
|
||||||
module.verbose('Removing indeterminate class');
|
|
||||||
$module
|
|
||||||
.removeClass(className.indeterminate)
|
|
||||||
;
|
|
||||||
if( module.is.determinate() ) {
|
|
||||||
module.debug('Input is already determinate, skipping input property change');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Setting state to determinate');
|
|
||||||
$input
|
|
||||||
.prop('indeterminate', false)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
disabled: function() {
|
|
||||||
module.verbose('Setting class to disabled');
|
|
||||||
$module
|
|
||||||
.addClass(className.disabled)
|
|
||||||
;
|
|
||||||
if( module.is.disabled() ) {
|
|
||||||
module.debug('Input is already disabled, skipping input property change');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Setting state to disabled');
|
|
||||||
$input
|
|
||||||
.prop('disabled', 'disabled')
|
|
||||||
;
|
|
||||||
},
|
|
||||||
enabled: function() {
|
|
||||||
module.verbose('Removing disabled class');
|
|
||||||
$module.removeClass(className.disabled);
|
|
||||||
if( module.is.enabled() ) {
|
|
||||||
module.debug('Input is already enabled, skipping input property change');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
module.debug('Setting state to enabled');
|
|
||||||
$input
|
|
||||||
.prop('disabled', false)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
tabbable: function() {
|
|
||||||
module.verbose('Adding tabindex to checkbox');
|
|
||||||
if( $input.attr('tabindex') === undefined) {
|
|
||||||
$input.attr('tabindex', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
remove: {
|
|
||||||
initialLoad: function() {
|
|
||||||
initialLoad = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
trigger: {
|
|
||||||
change: function() {
|
|
||||||
var
|
|
||||||
inputElement = $input[0]
|
|
||||||
;
|
|
||||||
if(inputElement) {
|
|
||||||
var events = document.createEvent('HTMLEvents');
|
|
||||||
module.verbose('Triggering native change event');
|
|
||||||
events.initEvent('change', true, false);
|
|
||||||
inputElement.dispatchEvent(events);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
create: {
|
|
||||||
label: function() {
|
|
||||||
if($input.prevAll(selector.label).length > 0) {
|
|
||||||
$input.prev(selector.label).detach().insertAfter($input);
|
|
||||||
module.debug('Moving existing label', $label);
|
|
||||||
}
|
|
||||||
else if( !module.has.label() ) {
|
|
||||||
$label = $('<label>').insertAfter($input);
|
|
||||||
module.debug('Creating label', $label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
has: {
|
|
||||||
label: function() {
|
|
||||||
return ($label.length > 0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
bind: {
|
|
||||||
events: function() {
|
|
||||||
module.verbose('Attaching checkbox events');
|
|
||||||
$module
|
|
||||||
.on('click' + eventNamespace, module.event.click)
|
|
||||||
.on('change' + eventNamespace, module.event.change)
|
|
||||||
.on('keydown' + eventNamespace, selector.input, module.event.keydown)
|
|
||||||
.on('keyup' + eventNamespace, selector.input, module.event.keyup)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
unbind: {
|
|
||||||
events: function() {
|
|
||||||
module.debug('Removing events');
|
|
||||||
$module
|
|
||||||
.off(eventNamespace)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
uncheckOthers: function() {
|
|
||||||
var
|
|
||||||
$radios = module.get.otherRadios()
|
|
||||||
;
|
|
||||||
module.debug('Unchecking other radios', $radios);
|
|
||||||
$radios.removeClass(className.checked);
|
|
||||||
},
|
|
||||||
|
|
||||||
toggle: function() {
|
|
||||||
if( !module.can.change() ) {
|
|
||||||
if(!module.is.radio()) {
|
|
||||||
module.debug('Checkbox is read-only or disabled, ignoring toggle');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( module.is.indeterminate() || module.is.unchecked() ) {
|
|
||||||
module.debug('Currently unchecked');
|
|
||||||
module.check();
|
|
||||||
}
|
|
||||||
else if( module.is.checked() && module.can.uncheck() ) {
|
|
||||||
module.debug('Currently checked');
|
|
||||||
module.uncheck();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setting: function(name, value) {
|
|
||||||
module.debug('Changing setting', name, value);
|
|
||||||
if( $.isPlainObject(name) ) {
|
|
||||||
$.extend(true, settings, name);
|
|
||||||
}
|
|
||||||
else if(value !== undefined) {
|
|
||||||
if($.isPlainObject(settings[name])) {
|
|
||||||
$.extend(true, settings[name], value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
settings[name] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return settings[name];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
internal: function(name, value) {
|
|
||||||
if( $.isPlainObject(name) ) {
|
|
||||||
$.extend(true, module, name);
|
|
||||||
}
|
|
||||||
else if(value !== undefined) {
|
|
||||||
module[name] = value;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return module[name];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
debug: function() {
|
|
||||||
if(!settings.silent && settings.debug) {
|
|
||||||
if(settings.performance) {
|
|
||||||
module.performance.log(arguments);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
|
||||||
module.debug.apply(console, arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
verbose: function() {
|
|
||||||
if(!settings.silent && settings.verbose && settings.debug) {
|
|
||||||
if(settings.performance) {
|
|
||||||
module.performance.log(arguments);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
|
||||||
module.verbose.apply(console, arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
if(!settings.silent) {
|
|
||||||
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
|
|
||||||
module.error.apply(console, arguments);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
performance: {
|
|
||||||
log: function(message) {
|
|
||||||
var
|
|
||||||
currentTime,
|
|
||||||
executionTime,
|
|
||||||
previousTime
|
|
||||||
;
|
|
||||||
if(settings.performance) {
|
|
||||||
currentTime = new Date().getTime();
|
|
||||||
previousTime = time || currentTime;
|
|
||||||
executionTime = currentTime - previousTime;
|
|
||||||
time = currentTime;
|
|
||||||
performance.push({
|
|
||||||
'Name' : message[0],
|
|
||||||
'Arguments' : [].slice.call(message, 1) || '',
|
|
||||||
'Element' : element,
|
|
||||||
'Execution Time' : executionTime
|
|
||||||
});
|
|
||||||
}
|
|
||||||
clearTimeout(module.performance.timer);
|
|
||||||
module.performance.timer = setTimeout(module.performance.display, 500);
|
|
||||||
},
|
|
||||||
display: function() {
|
|
||||||
var
|
|
||||||
title = settings.name + ':',
|
|
||||||
totalTime = 0
|
|
||||||
;
|
|
||||||
time = false;
|
|
||||||
clearTimeout(module.performance.timer);
|
|
||||||
$.each(performance, function(index, data) {
|
|
||||||
totalTime += data['Execution Time'];
|
|
||||||
});
|
|
||||||
title += ' ' + totalTime + 'ms';
|
|
||||||
if(moduleSelector) {
|
|
||||||
title += ' \'' + moduleSelector + '\'';
|
|
||||||
}
|
|
||||||
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
|
|
||||||
console.groupCollapsed(title);
|
|
||||||
if(console.table) {
|
|
||||||
console.table(performance);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$.each(performance, function(index, data) {
|
|
||||||
console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
performance = [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
invoke: function(query, passedArguments, context) {
|
|
||||||
var
|
|
||||||
object = instance,
|
|
||||||
maxDepth,
|
|
||||||
found,
|
|
||||||
response
|
|
||||||
;
|
|
||||||
passedArguments = passedArguments || queryArguments;
|
|
||||||
context = element || context;
|
|
||||||
if(typeof query == 'string' && object !== undefined) {
|
|
||||||
query = query.split(/[\. ]/);
|
|
||||||
maxDepth = query.length - 1;
|
|
||||||
$.each(query, function(depth, value) {
|
|
||||||
var camelCaseValue = (depth != maxDepth)
|
|
||||||
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
|
|
||||||
: query
|
|
||||||
;
|
|
||||||
if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
|
|
||||||
object = object[camelCaseValue];
|
|
||||||
}
|
|
||||||
else if( object[camelCaseValue] !== undefined ) {
|
|
||||||
found = object[camelCaseValue];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
|
|
||||||
object = object[value];
|
|
||||||
}
|
|
||||||
else if( object[value] !== undefined ) {
|
|
||||||
found = object[value];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
module.error(error.method, query);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if ( $.isFunction( found ) ) {
|
|
||||||
response = found.apply(context, passedArguments);
|
|
||||||
}
|
|
||||||
else if(found !== undefined) {
|
|
||||||
response = found;
|
|
||||||
}
|
|
||||||
if(Array.isArray(returnedValue)) {
|
|
||||||
returnedValue.push(response);
|
|
||||||
}
|
|
||||||
else if(returnedValue !== undefined) {
|
|
||||||
returnedValue = [returnedValue, response];
|
|
||||||
}
|
|
||||||
else if(response !== undefined) {
|
|
||||||
returnedValue = response;
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(methodInvoked) {
|
|
||||||
if(instance === undefined) {
|
|
||||||
module.initialize();
|
|
||||||
}
|
|
||||||
module.invoke(query);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(instance !== undefined) {
|
|
||||||
instance.invoke('destroy');
|
|
||||||
}
|
|
||||||
module.initialize();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
;
|
|
||||||
|
|
||||||
return (returnedValue !== undefined)
|
|
||||||
? returnedValue
|
|
||||||
: this
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.checkbox.settings = {
|
|
||||||
|
|
||||||
name : 'Checkbox',
|
|
||||||
namespace : 'checkbox',
|
|
||||||
|
|
||||||
silent : false,
|
|
||||||
debug : false,
|
|
||||||
verbose : true,
|
|
||||||
performance : true,
|
|
||||||
|
|
||||||
// delegated event context
|
|
||||||
uncheckable : 'auto',
|
|
||||||
fireOnInit : false,
|
|
||||||
enableEnterKey : true,
|
|
||||||
|
|
||||||
onChange : function(){},
|
|
||||||
|
|
||||||
beforeChecked : function(){},
|
|
||||||
beforeUnchecked : function(){},
|
|
||||||
beforeDeterminate : function(){},
|
|
||||||
beforeIndeterminate : function(){},
|
|
||||||
|
|
||||||
onChecked : function(){},
|
|
||||||
onUnchecked : function(){},
|
|
||||||
|
|
||||||
onDeterminate : function() {},
|
|
||||||
onIndeterminate : function() {},
|
|
||||||
|
|
||||||
onEnable : function(){},
|
|
||||||
onDisable : function(){},
|
|
||||||
|
|
||||||
// preserve misspelled callbacks (will be removed in 3.0)
|
|
||||||
onEnabled : function(){},
|
|
||||||
onDisabled : function(){},
|
|
||||||
|
|
||||||
className : {
|
|
||||||
checked : 'checked',
|
|
||||||
indeterminate : 'indeterminate',
|
|
||||||
disabled : 'disabled',
|
|
||||||
hidden : 'hidden',
|
|
||||||
radio : 'radio',
|
|
||||||
readOnly : 'read-only'
|
|
||||||
},
|
|
||||||
|
|
||||||
error : {
|
|
||||||
method : 'The method you called is not defined'
|
|
||||||
},
|
|
||||||
|
|
||||||
selector : {
|
|
||||||
checkbox : '.ui.checkbox',
|
|
||||||
label : 'label, .box',
|
|
||||||
input : 'input[type="checkbox"], input[type="radio"]',
|
|
||||||
link : 'a[href]'
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
})( jQuery, window, document );
|
})( jQuery, window, document );
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
"components": [
|
"components": [
|
||||||
"api",
|
"api",
|
||||||
"button",
|
"button",
|
||||||
"checkbox",
|
|
||||||
"dimmer",
|
"dimmer",
|
||||||
"dropdown",
|
"dropdown",
|
||||||
"form",
|
"form",
|
||||||
|
|
|
@ -218,17 +218,24 @@ export function initAdminCommon() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Select actions
|
// Select actions
|
||||||
const $checkboxes = $('.select.table .ui.checkbox');
|
const checkboxes = document.querySelectorAll('.select.table .ui.checkbox input');
|
||||||
|
|
||||||
$('.select.action').on('click', function () {
|
$('.select.action').on('click', function () {
|
||||||
switch ($(this).data('action')) {
|
switch ($(this).data('action')) {
|
||||||
case 'select-all':
|
case 'select-all':
|
||||||
$checkboxes.checkbox('check');
|
for (const checkbox of checkboxes) {
|
||||||
|
checkbox.checked = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'deselect-all':
|
case 'deselect-all':
|
||||||
$checkboxes.checkbox('uncheck');
|
for (const checkbox of checkboxes) {
|
||||||
|
checkbox.checked = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'inverse':
|
case 'inverse':
|
||||||
$checkboxes.checkbox('toggle');
|
for (const checkbox of checkboxes) {
|
||||||
|
checkbox.checked = !checkbox.checked;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -236,11 +243,11 @@ export function initAdminCommon() {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.classList.add('is-loading', 'disabled');
|
this.classList.add('is-loading', 'disabled');
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
$checkboxes.each(function () {
|
for (const checkbox of checkboxes) {
|
||||||
if ($(this).checkbox('is checked')) {
|
if (checkbox.checked) {
|
||||||
data.append('ids[]', this.getAttribute('data-id'));
|
data.append('ids[]', checkbox.closest('.ui.checkbox').getAttribute('data-id'));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
await POST(this.getAttribute('data-link'), {data});
|
await POST(this.getAttribute('data-link'), {data});
|
||||||
window.location.href = this.getAttribute('data-redirect');
|
window.location.href = this.getAttribute('data-redirect');
|
||||||
});
|
});
|
||||||
|
|
|
@ -195,8 +195,6 @@ export function initGlobalCommon() {
|
||||||
$uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward');
|
$uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward');
|
||||||
$uiDropdowns.filter('.downward').dropdown('setting', 'direction', 'downward');
|
$uiDropdowns.filter('.downward').dropdown('setting', 'direction', 'downward');
|
||||||
|
|
||||||
$('.ui.checkbox').checkbox();
|
|
||||||
|
|
||||||
$('.tabular.menu .item').tab();
|
$('.tabular.menu .item').tab();
|
||||||
|
|
||||||
initSubmitEventPolyfill();
|
initSubmitEventPolyfill();
|
||||||
|
|
|
@ -110,15 +110,15 @@ export function initImageDiff() {
|
||||||
const $imagesAfter = imageInfos[0].$images;
|
const $imagesAfter = imageInfos[0].$images;
|
||||||
const $imagesBefore = imageInfos[1].$images;
|
const $imagesBefore = imageInfos[1].$images;
|
||||||
|
|
||||||
initSideBySide(createContext($imagesAfter[0], $imagesBefore[0]));
|
initSideBySide(this, createContext($imagesAfter[0], $imagesBefore[0]));
|
||||||
if ($imagesAfter.length > 0 && $imagesBefore.length > 0) {
|
if ($imagesAfter.length > 0 && $imagesBefore.length > 0) {
|
||||||
initSwipe(createContext($imagesAfter[1], $imagesBefore[1]));
|
initSwipe(createContext($imagesAfter[1], $imagesBefore[1]));
|
||||||
initOverlay(createContext($imagesAfter[2], $imagesBefore[2]));
|
initOverlay(createContext($imagesAfter[2], $imagesBefore[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
$container.find('> .image-diff-tabs').removeClass('is-loading');
|
this.querySelector(':scope > .image-diff-tabs')?.classList.remove('is-loading');
|
||||||
|
|
||||||
function initSideBySide(sizes) {
|
function initSideBySide(container, sizes) {
|
||||||
let factor = 1;
|
let factor = 1;
|
||||||
if (sizes.max.width > (diffContainerWidth - 24) / 2) {
|
if (sizes.max.width > (diffContainerWidth - 24) / 2) {
|
||||||
factor = (diffContainerWidth - 24) / 2 / sizes.max.width;
|
factor = (diffContainerWidth - 24) / 2 / sizes.max.width;
|
||||||
|
@ -126,13 +126,24 @@ export function initImageDiff() {
|
||||||
|
|
||||||
const widthChanged = sizes.$image1.length !== 0 && sizes.$image2.length !== 0 && sizes.$image1[0].naturalWidth !== sizes.$image2[0].naturalWidth;
|
const widthChanged = sizes.$image1.length !== 0 && sizes.$image2.length !== 0 && sizes.$image1[0].naturalWidth !== sizes.$image2[0].naturalWidth;
|
||||||
const heightChanged = sizes.$image1.length !== 0 && sizes.$image2.length !== 0 && sizes.$image1[0].naturalHeight !== sizes.$image2[0].naturalHeight;
|
const heightChanged = sizes.$image1.length !== 0 && sizes.$image2.length !== 0 && sizes.$image1[0].naturalHeight !== sizes.$image2[0].naturalHeight;
|
||||||
if (sizes.$image1.length !== 0) {
|
if (sizes.$image1?.length) {
|
||||||
$container.find('.bounds-info-after .bounds-info-width').text(`${sizes.$image1[0].naturalWidth}px`).addClass(widthChanged ? 'green' : '');
|
const boundsInfoAfterWidth = container.querySelector('.bounds-info-after .bounds-info-width');
|
||||||
$container.find('.bounds-info-after .bounds-info-height').text(`${sizes.$image1[0].naturalHeight}px`).addClass(heightChanged ? 'green' : '');
|
boundsInfoAfterWidth.textContent = `${sizes.$image1[0].naturalWidth}px`;
|
||||||
|
if (widthChanged) boundsInfoAfterWidth.classList.add('green');
|
||||||
|
|
||||||
|
const boundsInfoAfterHeight = container.querySelector('.bounds-info-after .bounds-info-height');
|
||||||
|
boundsInfoAfterHeight.textContent = `${sizes.$image1[0].naturalHeight}px`;
|
||||||
|
if (heightChanged) boundsInfoAfterHeight.classList.add('green');
|
||||||
}
|
}
|
||||||
if (sizes.$image2.length !== 0) {
|
|
||||||
$container.find('.bounds-info-before .bounds-info-width').text(`${sizes.$image2[0].naturalWidth}px`).addClass(widthChanged ? 'red' : '');
|
if (sizes.$image2?.length) {
|
||||||
$container.find('.bounds-info-before .bounds-info-height').text(`${sizes.$image2[0].naturalHeight}px`).addClass(heightChanged ? 'red' : '');
|
const boundsInfoBeforeWidth = container.querySelector('.bounds-info-before .bounds-info-width');
|
||||||
|
boundsInfoBeforeWidth.textContent = `${sizes.$image2[0].naturalWidth}px`;
|
||||||
|
if (widthChanged) boundsInfoBeforeWidth.classList.add('red');
|
||||||
|
|
||||||
|
const boundsInfoBeforeHeight = container.querySelector('.bounds-info-before .bounds-info-height');
|
||||||
|
boundsInfoBeforeHeight.textContent = `${sizes.$image2[0].naturalHeight}px`;
|
||||||
|
if (heightChanged) boundsInfoBeforeHeight.classList.add('red');
|
||||||
}
|
}
|
||||||
|
|
||||||
const image1 = sizes.$image1[0];
|
const image1 = sizes.$image1[0];
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import {GET} from '../modules/fetch.js';
|
import {GET} from '../modules/fetch.js';
|
||||||
|
import {toggleElem} from '../utils/dom.js';
|
||||||
|
|
||||||
const {appSubUrl, notificationSettings, assetVersionEncoded} = window.config;
|
const {appSubUrl, notificationSettings, assetVersionEncoded} = window.config;
|
||||||
let notificationSequenceNumber = 0;
|
let notificationSequenceNumber = 0;
|
||||||
|
@ -177,14 +178,11 @@ async function updateNotificationCount() {
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
const $notificationCount = $('.notification_count');
|
toggleElem('.notification_count', data.new !== 0);
|
||||||
if (data.new === 0) {
|
|
||||||
$notificationCount.addClass('tw-hidden');
|
|
||||||
} else {
|
|
||||||
$notificationCount.removeClass('tw-hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
$notificationCount.text(`${data.new}`);
|
for (const el of document.getElementsByClassName('notification_count')) {
|
||||||
|
el.textContent = `${data.new}`;
|
||||||
|
}
|
||||||
|
|
||||||
return `${data.new}`;
|
return `${data.new}`;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -25,7 +25,9 @@ function getLineEls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectRange($linesEls, $selectionEndEl, $selectionStartEls) {
|
function selectRange($linesEls, $selectionEndEl, $selectionStartEls) {
|
||||||
$linesEls.closest('tr').removeClass('active');
|
for (const el of $linesEls) {
|
||||||
|
el.closest('tr').classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
// add hashchange to permalink
|
// add hashchange to permalink
|
||||||
const refInNewIssue = document.querySelector('a.ref-in-new-issue');
|
const refInNewIssue = document.querySelector('a.ref-in-new-issue');
|
||||||
|
@ -72,7 +74,7 @@ function selectRange($linesEls, $selectionEndEl, $selectionStartEls) {
|
||||||
classes.push(`[rel=L${i}]`);
|
classes.push(`[rel=L${i}]`);
|
||||||
}
|
}
|
||||||
$linesEls.filter(classes.join(',')).each(function () {
|
$linesEls.filter(classes.join(',')).each(function () {
|
||||||
$(this).closest('tr').addClass('active');
|
this.closest('tr').classList.add('active');
|
||||||
});
|
});
|
||||||
changeHash(`#L${a}-L${b}`);
|
changeHash(`#L${a}-L${b}`);
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@ function selectRange($linesEls, $selectionEndEl, $selectionStartEls) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$selectionEndEl.closest('tr').addClass('active');
|
$selectionEndEl[0].closest('tr').classList.add('active');
|
||||||
changeHash(`#${$selectionEndEl[0].getAttribute('rel')}`);
|
changeHash(`#${$selectionEndEl[0].getAttribute('rel')}`);
|
||||||
|
|
||||||
updateIssueHref($selectionEndEl[0].getAttribute('rel'));
|
updateIssueHref($selectionEndEl[0].getAttribute('rel'));
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {validateTextareaNonEmpty} from './comp/ComboMarkdownEditor.js';
|
||||||
import {initViewedCheckboxListenerFor, countAndUpdateViewedFiles, initExpandAndCollapseFilesButton} from './pull-view-file.js';
|
import {initViewedCheckboxListenerFor, countAndUpdateViewedFiles, initExpandAndCollapseFilesButton} from './pull-view-file.js';
|
||||||
import {initImageDiff} from './imagediff.js';
|
import {initImageDiff} from './imagediff.js';
|
||||||
import {showErrorToast} from '../modules/toast.js';
|
import {showErrorToast} from '../modules/toast.js';
|
||||||
import {submitEventSubmitter} from '../utils/dom.js';
|
import {submitEventSubmitter, queryElemSiblings, hideElem, showElem} from '../utils/dom.js';
|
||||||
import {POST, GET} from '../modules/fetch.js';
|
import {POST, GET} from '../modules/fetch.js';
|
||||||
|
|
||||||
const {pageData, i18n} = window.config;
|
const {pageData, i18n} = window.config;
|
||||||
|
@ -16,7 +16,6 @@ function initRepoDiffReviewButton() {
|
||||||
const reviewBox = document.getElementById('review-box');
|
const reviewBox = document.getElementById('review-box');
|
||||||
if (!reviewBox) return;
|
if (!reviewBox) return;
|
||||||
|
|
||||||
const $reviewBox = $(reviewBox);
|
|
||||||
const counter = reviewBox.querySelector('.review-comments-counter');
|
const counter = reviewBox.querySelector('.review-comments-counter');
|
||||||
if (!counter) return;
|
if (!counter) return;
|
||||||
|
|
||||||
|
@ -27,23 +26,27 @@ function initRepoDiffReviewButton() {
|
||||||
const num = parseInt(counter.getAttribute('data-pending-comment-number')) + 1 || 1;
|
const num = parseInt(counter.getAttribute('data-pending-comment-number')) + 1 || 1;
|
||||||
counter.setAttribute('data-pending-comment-number', num);
|
counter.setAttribute('data-pending-comment-number', num);
|
||||||
counter.textContent = num;
|
counter.textContent = num;
|
||||||
// Force the browser to reflow the DOM. This is to ensure that the browser replay the animation
|
|
||||||
$reviewBox.removeClass('pulse');
|
reviewBox.classList.remove('pulse');
|
||||||
$reviewBox.width();
|
requestAnimationFrame(() => {
|
||||||
$reviewBox.addClass('pulse');
|
reviewBox.classList.add('pulse');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function initRepoDiffFileViewToggle() {
|
function initRepoDiffFileViewToggle() {
|
||||||
$('.file-view-toggle').on('click', function () {
|
$('.file-view-toggle').on('click', function () {
|
||||||
const $this = $(this);
|
for (const el of queryElemSiblings(this)) {
|
||||||
$this.parent().children().removeClass('active');
|
el.classList.remove('active');
|
||||||
$this.addClass('active');
|
}
|
||||||
|
this.classList.add('active');
|
||||||
|
|
||||||
const $target = $($this.data('toggle-selector'));
|
const target = document.querySelector(this.getAttribute('data-toggle-selector'));
|
||||||
$target.parent().children().addClass('tw-hidden');
|
if (!target) return;
|
||||||
$target.removeClass('tw-hidden');
|
|
||||||
|
hideElem(queryElemSiblings(target));
|
||||||
|
showElem(target);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +60,9 @@ function initRepoDiffConversationForm() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($form.hasClass('is-loading')) return;
|
if (e.target.classList.contains('is-loading')) return;
|
||||||
try {
|
try {
|
||||||
$form.addClass('is-loading');
|
e.target.classList.add('is-loading');
|
||||||
const formData = new FormData($form[0]);
|
const formData = new FormData($form[0]);
|
||||||
|
|
||||||
// if the form is submitted by a button, append the button's name and value to the form data
|
// if the form is submitted by a button, append the button's name and value to the form data
|
||||||
|
@ -74,10 +77,14 @@ function initRepoDiffConversationForm() {
|
||||||
const {path, side, idx} = $newConversationHolder.data();
|
const {path, side, idx} = $newConversationHolder.data();
|
||||||
|
|
||||||
$form.closest('.conversation-holder').replaceWith($newConversationHolder);
|
$form.closest('.conversation-holder').replaceWith($newConversationHolder);
|
||||||
|
let selector;
|
||||||
if ($form.closest('tr').data('line-type') === 'same') {
|
if ($form.closest('tr').data('line-type') === 'same') {
|
||||||
$(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).addClass('tw-invisible');
|
selector = `[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`;
|
||||||
} else {
|
} else {
|
||||||
$(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).addClass('tw-invisible');
|
selector = `[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`;
|
||||||
|
}
|
||||||
|
for (const el of document.querySelectorAll(selector)) {
|
||||||
|
el.classList.add('tw-invisible');
|
||||||
}
|
}
|
||||||
$newConversationHolder.find('.dropdown').dropdown();
|
$newConversationHolder.find('.dropdown').dropdown();
|
||||||
initCompReactionSelector($newConversationHolder);
|
initCompReactionSelector($newConversationHolder);
|
||||||
|
@ -85,7 +92,7 @@ function initRepoDiffConversationForm() {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
showErrorToast(i18n.network_error);
|
showErrorToast(i18n.network_error);
|
||||||
} finally {
|
} finally {
|
||||||
$form.removeClass('is-loading');
|
e.target.classList.remove('is-loading');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -145,13 +152,13 @@ function onShowMoreFiles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadMoreFiles(url) {
|
export async function loadMoreFiles(url) {
|
||||||
const $target = $('a#diff-show-more-files');
|
const target = document.querySelector('a#diff-show-more-files');
|
||||||
if ($target.hasClass('disabled') || pageData.diffFileInfo.isLoadingNewData) {
|
if (target?.classList.contains('disabled') || pageData.diffFileInfo.isLoadingNewData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pageData.diffFileInfo.isLoadingNewData = true;
|
pageData.diffFileInfo.isLoadingNewData = true;
|
||||||
$target.addClass('disabled');
|
target?.classList.add('disabled');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await GET(url);
|
const response = await GET(url);
|
||||||
|
@ -168,7 +175,7 @@ export async function loadMoreFiles(url) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
showErrorToast('An error occurred while loading more files.');
|
showErrorToast('An error occurred while loading more files.');
|
||||||
} finally {
|
} finally {
|
||||||
$target.removeClass('disabled');
|
target?.classList.remove('disabled');
|
||||||
pageData.diffFileInfo.isLoadingNewData = false;
|
pageData.diffFileInfo.isLoadingNewData = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,11 +192,11 @@ function initRepoDiffShowMore() {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const $target = $(e.target);
|
const $target = $(e.target);
|
||||||
|
|
||||||
if ($target.hasClass('disabled')) {
|
if (e.target.classList.contains('disabled')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$target.addClass('disabled');
|
e.target.classList.add('disabled');
|
||||||
|
|
||||||
const url = $target.data('href');
|
const url = $target.data('href');
|
||||||
|
|
||||||
|
@ -205,7 +212,7 @@ function initRepoDiffShowMore() {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
} finally {
|
} finally {
|
||||||
$target.removeClass('disabled');
|
e.target.classList.remove('disabled');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,8 +147,8 @@ export function initRepoEditor() {
|
||||||
silent: true,
|
silent: true,
|
||||||
dirtyClass: dirtyFileClass,
|
dirtyClass: dirtyFileClass,
|
||||||
fieldSelector: ':input:not(.commit-form-wrapper :input)',
|
fieldSelector: ':input:not(.commit-form-wrapper :input)',
|
||||||
change() {
|
change($form) {
|
||||||
const dirty = $(this).hasClass(dirtyFileClass);
|
const dirty = $form[0]?.classList.contains(dirtyFileClass);
|
||||||
commitButton.disabled = !dirty;
|
commitButton.disabled = !dirty;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -282,32 +282,26 @@ export function initRepoPullRequestMergeInstruction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initRepoPullRequestAllowMaintainerEdit() {
|
export function initRepoPullRequestAllowMaintainerEdit() {
|
||||||
const checkbox = document.getElementById('allow-edits-from-maintainers');
|
const wrapper = document.getElementById('allow-edits-from-maintainers');
|
||||||
if (!checkbox) return;
|
if (!wrapper) return;
|
||||||
|
|
||||||
const $checkbox = $(checkbox);
|
wrapper.querySelector('input[type="checkbox"]')?.addEventListener('change', async (e) => {
|
||||||
|
const checked = e.target.checked;
|
||||||
const promptError = checkbox.getAttribute('data-prompt-error');
|
const url = `${wrapper.getAttribute('data-url')}/set_allow_maintainer_edit`;
|
||||||
$checkbox.checkbox({
|
wrapper.classList.add('is-loading');
|
||||||
'onChange': async () => {
|
e.target.disabled = true;
|
||||||
const checked = $checkbox.checkbox('is checked');
|
try {
|
||||||
let url = checkbox.getAttribute('data-url');
|
const response = await POST(url, {data: {allow_maintainer_edit: checked}});
|
||||||
url += '/set_allow_maintainer_edit';
|
if (!response.ok) {
|
||||||
$checkbox.checkbox('set disabled');
|
throw new Error('Failed to update maintainer edit permission');
|
||||||
try {
|
|
||||||
const response = await POST(url, {
|
|
||||||
data: {allow_maintainer_edit: checked},
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Failed to update maintainer edit permission');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
showTemporaryTooltip(checkbox, promptError);
|
|
||||||
} finally {
|
|
||||||
$checkbox.checkbox('set enabled');
|
|
||||||
}
|
}
|
||||||
},
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
showTemporaryTooltip(wrapper, wrapper.getAttribute('data-prompt-error'));
|
||||||
|
} finally {
|
||||||
|
wrapper.classList.remove('is-loading');
|
||||||
|
e.target.disabled = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ export const fomanticMobileScreen = window.matchMedia('only screen and (max-widt
|
||||||
export function initGiteaFomantic() {
|
export function initGiteaFomantic() {
|
||||||
// Silence fomantic's error logging when tabs are used without a target content element
|
// Silence fomantic's error logging when tabs are used without a target content element
|
||||||
$.fn.tab.settings.silent = true;
|
$.fn.tab.settings.silent = true;
|
||||||
// Disable the behavior of fomantic to toggle the checkbox when you press enter on a checkbox element.
|
|
||||||
$.fn.checkbox.settings.enableEnterKey = false;
|
|
||||||
|
|
||||||
// By default, use "exact match" for full text search
|
// By default, use "exact match" for full text search
|
||||||
$.fn.dropdown.settings.fullTextSearch = 'exact';
|
$.fn.dropdown.settings.fullTextSearch = 'exact';
|
||||||
|
|
|
@ -41,24 +41,19 @@ The ideal checkboxes should be:
|
||||||
<label><input type="checkbox"> ... </label>
|
<label><input type="checkbox"> ... </label>
|
||||||
```
|
```
|
||||||
|
|
||||||
However, related CSS styles aren't supported (not implemented) yet, so at the moment,
|
However, the templates still have the Fomantic-style HTML layout:
|
||||||
almost all the checkboxes are still using Fomantic UI checkbox.
|
|
||||||
|
|
||||||
## Fomantic UI Checkbox
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox"> <!-- class "hidden" will be added by $.checkbox() -->
|
<input type="checkbox">
|
||||||
<label>...</label>
|
<label>...</label>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
Then the JS `$.checkbox()` should be called to make it work with keyboard and label-clicking,
|
We call `initAriaCheckboxPatch` to link the `input` and `label` which makes clicking the
|
||||||
then it works like the ideal checkboxes.
|
label etc. work. There is still a problem: These checkboxes are not friendly to screen readers,
|
||||||
|
so we add IDs to all the Fomantic UI checkboxes automatically by JS. If the `label` part is empty,
|
||||||
There is still a problem: Fomantic UI checkbox is not friendly to screen readers,
|
then the checkbox needs to get the `aria-label` attribute manually.
|
||||||
so we add IDs to all the Fomantic UI checkboxes automatically by JS.
|
|
||||||
If the `label` part is empty, then the checkbox needs to get the `aria-label` attribute manually.
|
|
||||||
|
|
||||||
# Fomantic Dropdown
|
# Fomantic Dropdown
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,15 @@
|
||||||
import $ from 'jquery';
|
|
||||||
import {generateAriaId} from './base.js';
|
import {generateAriaId} from './base.js';
|
||||||
|
|
||||||
const ariaPatchKey = '_giteaAriaPatchCheckbox';
|
|
||||||
const fomanticCheckboxFn = $.fn.checkbox;
|
|
||||||
|
|
||||||
// use our own `$.fn.checkbox` to patch Fomantic's checkbox module
|
|
||||||
export function initAriaCheckboxPatch() {
|
export function initAriaCheckboxPatch() {
|
||||||
if ($.fn.checkbox === ariaCheckboxFn) throw new Error('initAriaCheckboxPatch could only be called once');
|
// link the label and the input element so it's clickable and accessible
|
||||||
$.fn.checkbox = ariaCheckboxFn;
|
for (const el of document.querySelectorAll('.ui.checkbox')) {
|
||||||
ariaCheckboxFn.settings = fomanticCheckboxFn.settings;
|
if (el.hasAttribute('data-checkbox-patched')) continue;
|
||||||
}
|
const label = el.querySelector('label');
|
||||||
|
const input = el.querySelector('input');
|
||||||
// the patched `$.fn.checkbox` checkbox function
|
if (!label || !input || input.getAttribute('id') || label.getAttribute('for')) continue;
|
||||||
// * it does the one-time attaching on the first call
|
const id = generateAriaId();
|
||||||
function ariaCheckboxFn(...args) {
|
input.setAttribute('id', id);
|
||||||
const ret = fomanticCheckboxFn.apply(this, args);
|
label.setAttribute('for', id);
|
||||||
for (const el of this) {
|
el.setAttribute('data-checkbox-patched', 'true');
|
||||||
if (el[ariaPatchKey]) continue;
|
|
||||||
attachInit(el);
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachInit(el) {
|
|
||||||
// Fomantic UI checkbox needs to be something like: <div class="ui checkbox"><label /><input /></div>
|
|
||||||
// It doesn't work well with <label><input />...</label>
|
|
||||||
// To make it work with aria, the "id"/"for" attributes are necessary, so add them automatically if missing.
|
|
||||||
// In the future, refactor to use native checkbox directly, then this patch could be removed.
|
|
||||||
el[ariaPatchKey] = {}; // record that this element has been patched
|
|
||||||
const label = el.querySelector('label');
|
|
||||||
const input = el.querySelector('input');
|
|
||||||
if (!label || !input || input.getAttribute('id')) return;
|
|
||||||
|
|
||||||
const id = generateAriaId();
|
|
||||||
input.setAttribute('id', id);
|
|
||||||
label.setAttribute('for', id);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ export function isElemHidden(el) {
|
||||||
return res[0];
|
return res[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryElemSiblings(el, selector) {
|
export function queryElemSiblings(el, selector = '*') {
|
||||||
return Array.from(el.parentNode.children).filter((child) => child !== el && child.matches(selector));
|
return Array.from(el.parentNode.children).filter((child) => child !== el && child.matches(selector));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue