Merge branch 'main' into lunny/issue_dev

This commit is contained in:
Lunny Xiao 2024-12-09 18:43:43 -08:00
commit 2d49aec197
46 changed files with 1566 additions and 295 deletions

View File

@ -818,7 +818,7 @@ rules:
unicorn/consistent-destructuring: [2]
unicorn/consistent-empty-array-spread: [2]
unicorn/consistent-existence-index-check: [0]
unicorn/consistent-function-scoping: [2]
unicorn/consistent-function-scoping: [0]
unicorn/custom-error-definition: [0]
unicorn/empty-brace-spaces: [2]
unicorn/error-message: [0]

View File

@ -42,6 +42,7 @@ func NewFuncMap() template.FuncMap {
"HTMLFormat": htmlutil.HTMLFormat,
"HTMLEscape": htmlEscape,
"QueryEscape": queryEscape,
"QueryBuild": queryBuild,
"JSEscape": jsEscapeSafe,
"SanitizeHTML": SanitizeHTML,
"URLJoin": util.URLJoin,
@ -293,6 +294,69 @@ func timeEstimateString(timeSec any) string {
return util.TimeEstimateString(v)
}
func queryBuild(a ...any) template.URL {
var s string
if len(a)%2 == 1 {
if v, ok := a[0].(string); ok {
if v == "" || (v[0] != '?' && v[0] != '&') {
panic("queryBuild: invalid argument")
}
s = v
} else if v, ok := a[0].(template.URL); ok {
s = string(v)
} else {
panic("queryBuild: invalid argument")
}
}
for i := len(a) % 2; i < len(a); i += 2 {
k, ok := a[i].(string)
if !ok {
panic("queryBuild: invalid argument")
}
var v string
if va, ok := a[i+1].(string); ok {
v = va
} else if a[i+1] != nil {
v = fmt.Sprint(a[i+1])
}
// pos1 to pos2 is the "k=v&" part, "&" is optional
pos1 := strings.Index(s, "&"+k+"=")
if pos1 != -1 {
pos1++
} else {
pos1 = strings.Index(s, "?"+k+"=")
if pos1 != -1 {
pos1++
} else if strings.HasPrefix(s, k+"=") {
pos1 = 0
}
}
pos2 := len(s)
if pos1 == -1 {
pos1 = len(s)
} else {
pos2 = pos1 + 1
for pos2 < len(s) && s[pos2-1] != '&' {
pos2++
}
}
if v != "" {
sep := ""
hasPrefixSep := pos1 == 0 || (pos1 <= len(s) && (s[pos1-1] == '?' || s[pos1-1] == '&'))
if !hasPrefixSep {
sep = "&"
}
s = s[:pos1] + sep + k + "=" + url.QueryEscape(v) + "&" + s[pos2:]
} else {
s = s[:pos1] + s[pos2:]
}
}
if s != "" && s != "&" && s[len(s)-1] == '&' {
s = s[:len(s)-1]
}
return template.URL(s)
}
func panicIfDevOrTesting() {
if !setting.IsProd || setting.IsInTesting {
panic("legacy template functions are for backward compatibility only, do not use them in new code")

View File

@ -29,7 +29,7 @@ CASS.ini
*.gzlc
## gitignore reference sites
# https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#Ignoring-Files
# https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#_ignoring
# https://git-scm.com/docs/gitignore
# https://help.github.com/articles/ignoring-files/

View File

@ -0,0 +1,62 @@
# gitignore template for ECU-TEST workspaces - by TraceTronic https://tracetronic.com
# website: https://www.ecu-test.com
# * all directories are related to the default directories, please adapt the .gitignore if you use customized
# directories
# Dynamic workspace settings
# * We don't recommend to ignore the .workspace directory, because of important project specific settings
# local user settings
.workspace/ETdrive.xml
.workspace/favorites.xml
.workspace/filters.xml
.workspace/generators.xml
.workspace/history.xml
.workspace/parallelExecution.xml
.workspace/signalviewer.xml
.workspace/signalViewerHistory.json
.workspace/signalviewer2layout.xml
.workspace/testeditor.xml
.workspace/tooladapter.xml
.workspace/view.xml
# optional, if your process depends on this file remove exclusion
.workspace/interactiveexecution.xml
.workspace/pythonlibrary.xml
# deprecated, support for older versions
.workspace/traceexplorer.xml
# Custom file formats and test dependencies
# * you can manage your artifacts also with TEST-GUIDE (https://www.test-guide.info) and reference them via Playbooks
*.arxml
*.a2l
*.dbc
*.hex
*.s19
[tT]estdata
[tT]estdaten
# Test results and test execution related content
# * Git is not intended to store and provide test results for all iterations
# * We recommend to use TEST-GUIDE (https://www.test-guide.info) for the test report management
TestReports
# Report generators and templates
# * if you want to provide (f.e.) your own report generators exclude the directory here and ignore only the
# unnecessary subdirectories
Templates
# Exclude large binary artifacts
# * you can manage your artifacts also with TEST-GUIDE (https://www.test-guide.info) and reference them via Playbooks
Offline-FIUs
Offline-Models
Offline-SGBDs
*.exe
*.msi
*.zip
*.7z
# Exclude default and custom temporary directories
Backup_*
# Python bytecode and cache files
__pycache__/
*.py[cod]

View File

@ -22,3 +22,6 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
# Kotlin Gradle plugin data, see https://kotlinlang.org/docs/whatsnew20.html#new-directory-for-kotlin-data-in-gradle-projects
.kotlin/

View File

@ -21,3 +21,10 @@ Homestead.yaml
Homestead.json
/.vagrant
.phpunit.result.cache
/public/build
/storage/pail
.env.backup
.env.production
.phpactor.json
auth.json

6
options/gitignore/Move Normal file
View File

@ -0,0 +1,6 @@
# Generated by Move
# will have compiled files
build/
# Remove possibly saving credentials to the git repository
.aptos/

View File

@ -0,0 +1,42 @@
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
crash.*.log
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
*.tfvars.json
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tofu
override.tf.json
override.tofu.json
*_override.tf
*_override.tofu
*_override.tf.json
*_override.tofu.json
# Ignore transient lock info files created by tofu apply
.terraform.tfstate.lock.info
# Include override files you do wish to add to version control using negated pattern
# !example_override.tf
# !example_override.tofu
# Include tfplan files to ignore the plan output of command: tofu plan -out=tfplan
# example: *tfplan*
# Ignore CLI configuration files
.terraformrc
terraform.rc

View File

@ -94,6 +94,12 @@ ipython_config.py
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more

View File

@ -59,6 +59,7 @@ sysinfo.txt
*.apk
*.aab
*.unitypackage
*.unitypackage.meta
*.app
# Crashlytics generated file

View File

@ -82,6 +82,8 @@ StyleCopReport.xml
*.pgc
*.pgd
*.rsp
# but not Directory.Build.rsp, as it configures directory-level build defaults
!Directory.Build.rsp
*.sbr
*.tlb
*.tli

View File

@ -0,0 +1,27 @@
No Copyright
This work has been identified as being free of known restrictions under
copyright law, including all related and neighboring rights.
You can copy, modify, distribute and perform the work, even for commercial
purposes, all without asking permission. See Other Information below.
Other Information
The work may not be free of known copyright restrictions in all jurisdictions .
Persons may have other rights in or related to the work, such as patent or
trademark rights, and others may have rights in how the work is used, such as
publicity or privacy rights.
In some jurisdictions moral rights of the author may persist beyond the term of
copyright. These rights may include the right to be identified as the author
and the right to object to derogatory treatments.
Unless expressly stated otherwise, the person who identified the work makes no
warranties about the work, and disclaims liability for all uses of the work, to
the fullest extent permitted by applicable law.
When using or citing the work, you should not imply endorsement by the author
or the person who identified the work.

198
options/license/CC-SA-1.0 Normal file
View File

@ -0,0 +1,198 @@
Creative Commons Legal Code
ShareAlike 1.0
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL
SERVICES. DISTRIBUTION OF THIS DRAFT LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT
RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS.
CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND
DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE
BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.
1. Definitions
a. "Collective Work" means a work, such as a periodical issue, anthology or
encyclopedia, in which the Work in its entirety in unmodified form, along
with a number of other contributions, constituting separate and independent
works in themselves, are assembled into a collective whole. A work that
constitutes a Collective Work will not be considered a Derivative Work (as
defined below) for the purposes of this License.
b. "Derivative Work" means a work based upon the Work or upon the Work and
other pre-existing works, such as a translation, musical arrangement,
dramatization, fictionalization, motion picture version, sound recording,
art reproduction, abridgment, condensation, or any other form in which the
Work may be recast, transformed, or adapted, except that a work that
constitutes a Collective Work will not be considered a Derivative Work for
the purpose of this License.
c. "Licensor" means the individual or entity that offers the Work under the
terms of this License.
d. "Original Author" means the individual or entity who created the Work.
e. "Work" means the copyrightable work of authorship offered under the terms
of this License.
f. "You" means an individual or entity exercising rights under this License
who has not previously violated the terms of this License with respect to
the Work, or who has received express permission from the Licensor to
exercise rights under this License despite a previous violation.
2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or
restrict any rights arising from fair use, first sale or other limitations on
the exclusive rights of the copyright owner under copyright law or other
applicable laws.
3. License Grant. Subject to the terms and conditions of this License, Licensor
hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the
duration of the applicable copyright) license to exercise the rights in the
Work as stated below:
a. to reproduce the Work, to incorporate the Work into one or more Collective
Works, and to reproduce the Work as incorporated in the Collective Works;
b. to create and reproduce Derivative Works;
c. to distribute copies or phonorecords of, display publicly, perform
publicly, and perform publicly by means of a digital audio transmission the
Work including as incorporated in Collective Works;
d. to distribute copies or phonorecords of, display publicly, perform
publicly, and perform publicly by means of a digital audio transmission
Derivative Works;
The above rights may be exercised in all media and formats whether now known or
hereafter devised. The above rights include the right to make such
modifications as are technically necessary to exercise the rights in other
media and formats. All rights not expressly granted by Licensor are hereby
reserved.
4. Restrictions. The license granted in Section 3 above is expressly made
subject to and limited by the following restrictions:
a. You may distribute, publicly display, publicly perform, or publicly
digitally perform the Work only under the terms of this License, and You
must include a copy of, or the Uniform Resource Identifier for, this
License with every copy or phonorecord of the Work You distribute, publicly
display, publicly perform, or publicly digitally perform. You may not offer
or impose any terms on the Work that alter or restrict the terms of this
License or the recipients' exercise of the rights granted hereunder. You
may not sublicense the Work. You must keep intact all notices that refer to
this License and to the disclaimer of warranties. You may not distribute,
publicly display, publicly perform, or publicly digitally perform the Work
with any technological measures that control access or use of the Work in a
manner inconsistent with the terms of this License Agreement. The above
applies to the Work as incorporated in a Collective Work, but this does not
require the Collective Work apart from the Work itself to be made subject
to the terms of this License. If You create a Collective Work, upon notice
from any Licensor You must, to the extent practicable, remove from the
Collective Work any reference to such Licensor or the Original Author, as
requested. If You create a Derivative Work, upon notice from any Licensor
You must, to the extent practicable, remove from the Derivative Work any
reference to such Licensor or the Original Author, as requested.
b. You may distribute, publicly display, publicly perform, or publicly
digitally perform a Derivative Work only under the terms of this License,
and You must include a copy of, or the Uniform Resource Identifier for,
this License with every copy or phonorecord of each Derivative Work You
distribute, publicly display, publicly perform, or publicly digitally
perform. You may not offer or impose any terms on the Derivative Works that
alter or restrict the terms of this License or the recipients' exercise of
the rights granted hereunder, and You must keep intact all notices that
refer to this License and to the disclaimer of warranties. You may not
distribute, publicly display, publicly perform, or publicly digitally
perform the Derivative Work with any technological measures that control
access or use of the Work in a manner inconsistent with the terms of this
License Agreement. The above applies to the Derivative Work as incorporated
in a Collective Work, but this does not require the Collective Work apart
from the Derivative Work itself to be made subject to the terms of this
License.
5. Representations, Warranties and Disclaimer
a. By offering the Work for public release under this License, Licensor
represents and warrants that, to the best of Licensor's knowledge after
reasonable inquiry:
i. Licensor has secured all rights in the Work necessary to grant the
license rights hereunder and to permit the lawful exercise of the
rights granted hereunder without You having any obligation to pay any
royalties, compulsory license fees, residuals or any other payments;
ii. The Work does not infringe the copyright, trademark, publicity rights,
common law rights or any other right of any third party or constitute
defamation, invasion of privacy or other tortious injury to any third
party.
b. EXCEPT AS EXPRESSLY STATED IN THIS LICENSE OR OTHERWISE AGREED IN WRITING
OR REQUIRED BY APPLICABLE LAW, THE WORK IS LICENSED ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
WITHOUT LIMITATION, ANY WARRANTIES REGARDING THE CONTENTS OR ACCURACY OF
THE WORK.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW,
AND EXCEPT FOR DAMAGES ARISING FROM LIABILITY TO A THIRD PARTY RESULTING FROM
BREACH OF THE WARRANTIES IN SECTION 5, IN NO EVENT WILL LICENSOR BE LIABLE TO
YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR
EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF
LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
a. This License and the rights granted hereunder will terminate automatically
upon any breach by You of the terms of this License. Individuals or
entities who have received Derivative Works or Collective Works from You
under this License, however, will not have their licenses terminated
provided such individuals or entities remain in full compliance with those
licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of
this License.
b. Subject to the above terms and conditions, the license granted here is
perpetual (for the duration of the applicable copyright in the Work).
Notwithstanding the above, Licensor reserves the right to release the Work
under different license terms or to stop distributing the Work at any time;
provided, however that any such election will not serve to withdraw this
License (or any other license that has been, or is required to be, granted
under the terms of this License), and this License will continue in full
force and effect unless terminated as stated above.
8. Miscellaneous
a. Each time You distribute or publicly digitally perform the Work or a
Collective Work, the Licensor offers to the recipient a license to the Work
on the same terms and conditions as the license granted to You under this
License.
b. Each time You distribute or publicly digitally perform a Derivative Work,
Licensor offers to the recipient a license to the original Work on the same
terms and conditions as the license granted to You under this License.
c. If any provision of this License is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of the
remainder of the terms of this License, and without further action by the
parties to this agreement, such provision shall be reformed to the minimum
extent necessary to make such provision valid and enforceable.
d. No term or provision of this License shall be deemed waived and no breach
consented to unless such waiver or consent shall be in writing and signed
by the party to be charged with such waiver or consent.
e. This License constitutes the entire agreement between the parties with
respect to the Work licensed here. There are no understandings, agreements
or representations with respect to the Work not specified here. Licensor
shall not be bound by any additional provisions that may appear in any
communication from You. This License may not be modified without the mutual
written agreement of the Licensor and You.
Creative Commons is not a party to this License, and makes no warranty
whatsoever in connection with the Work. Creative Commons will not be liable to
You or any party on any legal theory for any damages whatsoever, including
without limitation any general, special, incidental or consequential damages
arising in connection to this license. Notwithstanding the foregoing two (2)
sentences, if Creative Commons has expressly identified itself as the Licensor
hereunder, it shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the Work is
licensed under the CCPL, neither party will use the trademark "Creative
Commons" or any related trademark or logo of Creative Commons without the prior
written consent of Creative Commons. Any permitted use will be in compliance
with Creative Commons' then-current trademark usage guidelines, as may be
published on its website or otherwise made available upon request from time to
time.
Creative Commons may be contacted at http://creativecommons.org/.

View File

@ -0,0 +1,4 @@
As a special exception, you have permission to link this library
with the CGAL library (http://www.cgal.org) and distribute executables,
as long as you follow the requirements of the GNU GPL in regard to
all of the software in the executable aside from CGAL.

View File

@ -0,0 +1,18 @@
This is the file COPYING.FPC, it applies to the Free Pascal Run-Time Library
(RTL) and packages (packages) distributed by members of the Free Pascal
Development Team.
The source code of the Free Pascal Runtime Libraries and packages are
distributed under the Library GNU General Public License
(see the file COPYING) with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,
and to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a module
which is not derived from or based on this library. If you modify this
library, you may extend this exception to your version of the library, but you are
not obligated to do so. If you do not wish to do so, delete this exception
statement from your version.

27
options/license/InnoSetup Normal file
View File

@ -0,0 +1,27 @@
Inno Setup License
==================
Except where otherwise noted, all of the documentation and software included in the Inno Setup
package is copyrighted by Jordan Russell.
Copyright (C) 1997-2024 Jordan Russell. All rights reserved.
Portions Copyright (C) 2000-2024 Martijn Laan. All rights reserved.
This software is provided "as-is," without any express or implied warranty. In no event shall the
author be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial
applications, and to alter and redistribute it, provided that the following conditions are met:
1. All redistributions of source code files must retain all copyright notices that are currently in
place, and this list of conditions without modification.
2. All redistributions in binary form must retain all occurrences of the above copyright notice and
web site addresses that are currently in place (for example, in the About boxes).
3. The origin of this software must not be misrepresented; you must not claim that you wrote the
original software. If you use this software to distribute a product, an acknowledgment in the
product documentation would be appreciated but is not required.
4. Modified versions in source or binary form must be plainly marked as such, and must not be
misrepresented as being the original software.

View File

@ -1,110 +1,372 @@
MOTOSOTO OPEN SOURCE LICENSE - Version 0.9.1
This Motosoto Open Source License (the "License") applies to "Community Portal Server" and related software products as well as any updatesor maintenance releases of that software ("Motosoto Products") that are distributed by Motosoto.Com B.V. ("Licensor"). Any Motosoto Product licensed pursuant to this License is a "Licensed Product." Licensed Product, in its entirety, is protected by Dutch copyright law. This License identifies the terms under which you may use, copy, distribute or modify Licensed Product and has been submitted to the Open Software Initiative (OSI) for approval.
This Motosoto Open Source License (the "License") applies to "Community Portal Server" and related
software products as well as any updatesor maintenance releases of that software ("Motosoto
Products") that are distributed by Motosoto.Com B.V. ("Licensor"). Any Motosoto Product licensed
pursuant to this License is a "Licensed Product." Licensed Product, in its entirety, is protected
by Dutch copyright law. This License identifies the terms under which you may use, copy, distribute
or modify Licensed Product and has been submitted to the Open Software Initiative (OSI) for
approval.
Preamble
This Preamble is intended to describe, in plain English, the nature and scope of this License. However, this Preamble is not a part of this license. The legal effect of this License is dependent only upon the terms of the License and not this Preamble. This License complies with the Open Source Definition and has been approved by Open Source Initiative. Software distributed under this License may be marked as "OSI Certified Open Source Software."
This Preamble is intended to describe, in plain English, the nature and scope of this License.
However, this Preamble is not a part of this license. The legal effect of this License is dependent
only upon the terms of the License and not this Preamble. This License complies with the Open
Source Definition and has been approved by Open Source Initiative. Software distributed under this
License may be marked as "OSI Certified Open Source Software."
This License provides that:
1. You may use, sell or give away the Licensed Product, alone or as a component of an aggregate software distribution containing programs from several different sources. No royalty or other fee is required.
1. You may use, sell or give away the Licensed Product, alone or as a component of an aggregate
software distribution containing programs from several different sources. No royalty or other fee
is required.
2. Both Source Code and executable versions of the Licensed Product, including Modifications made by previous Contributors, are available for your use. (The terms "Licensed Product," "Modifications," "Contributors" and "Source Code" are defined in the License.)
2. Both Source Code and executable versions of the Licensed Product, including Modifications made
by previous Contributors, are available for your use. (The terms "Licensed Product,"
"Modifications," "Contributors" and "Source Code" are defined in the License.)
3. You are allowed to make Modifications to the Licensed Product, and you can create Derivative Works from it. (The term "Derivative Works" is defined in the License.)
3. You are allowed to make Modifications to the Licensed Product, and you can create Derivative
Works from it. (The term "Derivative Works" is defined in the License.)
4. By accepting the Licensed Product under the provisions of this License, you agree that any Modifications you make to the Licensed Product and then distribute are governed by the provisions of this License. In particular, you must make the Source Code of your Modifications available to others.
4. By accepting the Licensed Product under the provisions of this License, you agree that any
Modifications you make to the Licensed Product and then distribute are governed by the provisions
of this License. In particular, you must make the Source Code of your Modifications available to
others.
5. You may use the Licensed Product for any purpose, but the Licensor is not providing you any warranty whatsoever, nor is the Licensor accepting any liability in the event that the Licensed Product doesn't work properly or causes you any injury or damages.
5. You may use the Licensed Product for any purpose, but the Licensor is not providing you any
warranty whatsoever, nor is the Licensor accepting any liability in the event that the Licensed
Product doesn't work properly or causes you any injury or damages.
6. If you sublicense the Licensed Product or Derivative Works, you may charge fees for warranty or support, or for accepting indemnity or liability obligations to your customers. You cannot charge for the Source Code.
6. If you sublicense the Licensed Product or Derivative Works, you may charge fees for warranty or
support, or for accepting indemnity or liability obligations to your customers. You cannot charge
for the Source Code.
7. If you assert any patent claims against the Licensor relating to the Licensed Product, or if you breach any terms of the License, your rights to the Licensed Product under this License automatically terminate.
7. If you assert any patent claims against the Licensor relating to the Licensed Product, or if you
breach any terms of the License, your rights to the Licensed Product under this License
automatically terminate.
You may use this License to distribute your own Derivative Works, in which case the provisions of this License will apply to your Derivative Works just as they do to the original Licensed Product.
You may use this License to distribute your own Derivative Works, in which case the provisions of
this License will apply to your Derivative Works just as they do to the original Licensed Product.
Alternatively, you may distribute your Derivative Works under any other OSI-approved Open Source license, or under a proprietary license of your choice. If you use any license other than this License, however, you must continue to fulfill the requirements of this License (including the provisions relating to publishing the Source Code) for those portions of your Derivative Works that consist of the Licensed Product, including the files containing Modifications.
Alternatively, you may distribute your Derivative Works under any other OSI-approved Open Source
license, or under a proprietary license of your choice. If you use any license other than this
License, however, you must continue to fulfill the requirements of this License (including the
provisions relating to publishing the Source Code) for those portions of your Derivative Works that
consist of the Licensed Product, including the files containing Modifications.
New versions of this License may be published from time to time. You may choose to continue to use the license terms in this version of the License or those from the new version. However, only the Licensor has the right to change the License terms as they apply to the Licensed Product. This License relies on precise definitions for certain terms. Those terms are defined when they are first used, and the definitions are repeated for your convenience in a Glossary at the end of the License.
New versions of this License may be published from time to time. You may choose to continue to use
the license terms in this version of the License or those from the new version. However, only the
Licensor has the right to change the License terms as they apply to the Licensed Product. This
License relies on precise definitions for certain terms. Those terms are defined when they are
first used, and the definitions are repeated for your convenience in a Glossary at the end of the
License.
License Terms
1. Grant of License From Licensor.
Licensor hereby grants you a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims, to do the following:
Licensor hereby grants you a world-wide, royalty-free, non-exclusive license, subject to third
party intellectual property claims, to do the following:
a. Use, reproduce, modify, display, perform, sublicense and distribute Licensed Product or portions thereof (including Modifications as hereinafter defined), in both Source Code or as an executable program. "Source Code" means the preferred form for making modifications to the Licensed Product, including all modules contained therein, plus any associated interface definition files, scripts used to control compilation and installation of an executable program, or a list of differential comparisons against the Source Code of the Licensed Product.
a. Use, reproduce, modify, display, perform, sublicense and distribute Licensed Product or
portions thereof (including Modifications as hereinafter defined), in both Source Code or as an
executable program. "Source Code" means the preferred form for making modifications to the Licensed
Product, including all modules contained therein, plus any associated interface definition files,
scripts used to control compilation and installation of an executable program, or a list of
differential comparisons against the Source Code of the Licensed Product.
b. Create Derivative Works (as that term is defined under Dutch copyright law) of Licensed Product by adding to or deleting from the substance or structure of said Licensed Product.
b. Create Derivative Works (as that term is defined under Dutch copyright law) of Licensed
Product by adding to or deleting from the substance or structure of said Licensed Product.
c. Under claims of patents now or hereafter owned or controlled by Licensor, to make, use, sell, offer for sale, have made, and/or otherwise dispose of Licensed Product or portions thereof, but solely to the extent that any such claim is necessary to enable you to make, use, sell, offer for sale, have made, and/or otherwise dispose of Licensed Product or portions thereof or Derivative Works thereof.
c. Under claims of patents now or hereafter owned or controlled by Licensor, to make, use,
sell, offer for sale, have made, and/or otherwise dispose of Licensed Product or portions thereof,
but solely to the extent that any such claim is necessary to enable you to make, use, sell, offer
for sale, have made, and/or otherwise dispose of Licensed Product or portions thereof or Derivative
Works thereof.
2. Grant of License to Modifications From Contributor.
"Modifications" means any additions to or deletions from the substance or structure of (i) a file containing Licensed Product, or (ii) any new file that contains any part of Licensed Product. Hereinafter in this License, the term "Licensed Product" shall include all previous Modifications that you receive from any Contributor. By application of the provisions in Section 4(a) below, each person or entity who created or contributed to the creation of, and distributed, a Modification (a "Contributor") hereby grants you a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims, to do the following:
"Modifications" means any additions to or deletions from the substance or structure of (i) a file
containing Licensed Product, or (ii) any new file that contains any part of Licensed Product.
Hereinafter in this License, the term "Licensed Product" shall include all previous Modifications
that you receive from any Contributor. By application of the provisions in Section 4(a) below, each
person or entity who created or contributed to the creation of, and distributed, a Modification (a
"Contributor") hereby grants you a world-wide, royalty-free, non-exclusive license, subject to
third party intellectual property claims, to do the following:
a. Use, reproduce, modify, display, perform, sublicense and distribute any Modifications created by such Contributor or portions thereof, in both Source Code or as an executable program, either on an unmodified basis or as part of Derivative Works.
a. Use, reproduce, modify, display, perform, sublicense and distribute any Modifications
created by such Contributor or portions thereof, in both Source Code or as an executable program,
either on an unmodified basis or as part of Derivative Works.
b. Under claims of patents now or hereafter owned or controlled by Contributor, to make, use, sell, offer for sale, have made, and/or otherwise dispose of Modifications or portions thereof, but solely to the extent that any such claim is necessary to enable you to make, use, sell, offer for sale, have made, and/or otherwise dispose of Modifications or portions thereof or Derivative Works thereof.
b. Under claims of patents now or hereafter owned or controlled by Contributor, to make, use,
sell, offer for sale, have made, and/or otherwise dispose of Modifications or portions thereof, but
solely to the extent that any such claim is necessary to enable you to make, use, sell, offer for
sale, have made, and/or otherwise dispose of Modifications or portions thereof or Derivative Works
thereof.
3. Exclusions From License Grant.
Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor or any Contributor except as expressly stated herein. No patent license is granted separate from the Licensed Product, for code that you delete from the Licensed Product, or for combinations of the Licensed Product with other software or hardware. No right is granted to the trademarks of Licensor or any Contributor even if such marks are included in the Licensed Product. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any code that Licensor otherwise would have a right to license.
Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents,
trade secrets or any other intellectual property of Licensor or any Contributor except as expressly
stated herein. No patent license is granted separate from the Licensed Product, for code that you
delete from the Licensed Product, or for combinations of the Licensed Product with other software
or hardware. No right is granted to the trademarks of Licensor or any Contributor even if such
marks are included in the Licensed Product. Nothing in this License shall be interpreted to
prohibit Licensor from licensing under different terms from this License any code that Licensor
otherwise would have a right to license.
4. Your Obligations Regarding Distribution.
a. Application of This License to Your Modifications. As an express condition for your use of the Licensed Product, you hereby agree that any Modifications that you create or to which you contribute, and which you distribute, are governed by the terms of this License including, without limitation, Section 2. Any Modifications that you create or to which you contribute may be distributed only under the terms of this License or a future version of this License released under Section 7. You must include a copy of this License with every copy of the Modifications you distribute. You agree not to offer or impose any terms on any Source Code or executable version of the Licensed Product or Modifications that alter or restrict the applicable version of this License or the recipients' rights hereunder. However, you may include an additional document offering the additional rights described in Section 4(e).
a. Application of This License to Your Modifications. As an express condition for your use of
the Licensed Product, you hereby agree that any Modifications that you create or to which you
contribute, and which you distribute, are governed by the terms of this License including, without
limitation, Section 2. Any Modifications that you create or to which you contribute may be
distributed only under the terms of this License or a future version of this License released under
Section 7. You must include a copy of this License with every copy of the Modifications you
distribute. You agree not to offer or impose any terms on any Source Code or executable version of
the Licensed Product or Modifications that alter or restrict the applicable version of this License
or the recipients' rights hereunder. However, you may include an additional document offering the
additional rights described in Section 4(e).
b. Availability of Source Code. You must make available, under the terms of this License, the Source Code of the Licensed Product and any Modifications that you distribute, either on the same media as you distribute any executable or other form of the Licensed Product, or via a mechanism generally accepted in the software development community for the electronic transfer of data (an "Electronic Distribution Mechanism"). The Source Code for any version of Licensed Product or Modifications that you distribute must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of said Licensed Product or Modifications has been made available. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party.
b. Availability of Source Code. You must make available, under the terms of this License, the
Source Code of the Licensed Product and any Modifications that you distribute, either on the same
media as you distribute any executable or other form of the Licensed Product, or via a mechanism
generally accepted in the software development community for the electronic transfer of data (an
"Electronic Distribution Mechanism"). The Source Code for any version of Licensed Product or
Modifications that you distribute must remain available for at least twelve (12) months after the
date it initially became available, or at least six (6) months after a subsequent version of said
Licensed Product or Modifications has been made available. You are responsible for ensuring that
the Source Code version remains available even if the Electronic Distribution Mechanism is
maintained by a third party.
c. Description of Modifications. You must cause any Modifications that you create or to which you contribute, and which you distribute, to contain a file documenting the additions, changes or deletions you made to create or contribute to those Modifications, and the dates of any such additions, changes or deletions. You must include a prominent statement that the Modifications are derived, directly or indirectly, from the Licensed Product and include the names of the Licensor and any Contributor to the Licensed Product in (i) the Source Code and (ii) in any notice displayed by a version of the Licensed Product you distribute or in related documentation in which you describe the origin or ownership of the Licensed Product. You may not modify or delete any preexisting copyright notices in the Licensed Product.
c. Description of Modifications. You must cause any Modifications that you create or to which
you contribute, and which you distribute, to contain a file documenting the additions, changes or
deletions you made to create or contribute to those Modifications, and the dates of any such
additions, changes or deletions. You must include a prominent statement that the Modifications are
derived, directly or indirectly, from the Licensed Product and include the names of the Licensor
and any Contributor to the Licensed Product in (i) the Source Code and (ii) in any notice displayed
by a version of the Licensed Product you distribute or in related documentation in which you
describe the origin or ownership of the Licensed Product. You may not modify or delete any
preexisting copyright notices in the Licensed Product.
d. Intellectual Property Matters.
i. Third Party Claims. If you have knowledge that a license to a third party's intellectual property right is required to exercise the rights granted by this License, you must include a text file with the Source Code distribution titled "LEGAL" that describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after you make any Modifications available as described in Section 4(b), you shall promptly modify the LEGAL file in all copies you make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Licensed Product from you that new knowledge has been obtained.
i. Third Party Claims. If you have knowledge that a license to a third party's
intellectual property right is required to exercise the rights granted by this License, you must
include a text file with the Source Code distribution titled "LEGAL" that describes the claim and
the party making the claim in sufficient detail that a recipient will know whom to contact. If you
obtain such knowledge after you make any Modifications available as described in Section 4(b), you
shall promptly modify the LEGAL file in all copies you make available thereafter and shall take
other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to
inform those who received the Licensed Product from you that new knowledge has been obtained.
ii. Contributor APIs. If your Modifications include an application programming interface ("API") and you have knowledge of patent licenses that are reasonably necessary to implement that API, you must also include this information in the LEGAL file.
ii. Contributor APIs. If your Modifications include an application programming interface
("API") and you have knowledge of patent licenses that are reasonably necessary to implement that
API, you must also include this information in the LEGAL file.
iii. Representations. You represent that, except as disclosed pursuant to 4(d)(i) above, you believe that any Modifications you distribute are your original creations and that you have sufficient rights to grant the rights conveyed by this License.
iii. Representations. You represent that, except as disclosed pursuant to 4(d)(i) above,
you believe that any Modifications you distribute are your original creations and that you have
sufficient rights to grant the rights conveyed by this License.
e. Required Notices. You must duplicate this License in any documentation you provide along with the Source Code of any Modifications you create or to which you contribute, and which you distribute, wherever you describe recipients' rights relating to Licensed Product. You must duplicate the notice contained in Exhibit A (the "Notice") in each file of the Source Code of any copy you distribute of the Licensed Product. If you created a Modification, you may add your name as a Contributor to the Notice. If it is not possible to put the Notice in a particular Source Code file due to its structure, then you must include such Notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Licensed Product. However, you may do so only on your own behalf, and not on behalf of the Licensor or any Contributor. You must make it clear that any such warranty, support, indemnity or liability obligation is offered by you alone, and you hereby agree to indemnify the Licensor and every Contributor for any liability incurred by the Licensor or such Contributor as a result of warranty, support, indemnity or liability terms you offer.
e. Required Notices. You must duplicate this License in any documentation you provide along
with the Source Code of any Modifications you create or to which you contribute, and which you
distribute, wherever you describe recipients' rights relating to Licensed Product. You must
duplicate the notice contained in Exhibit A (the "Notice") in each file of the Source Code of any
copy you distribute of the Licensed Product. If you created a Modification, you may add your name
as a Contributor to the Notice. If it is not possible to put the Notice in a particular Source Code
file due to its structure, then you must include such Notice in a location (such as a relevant
directory file) where a user would be likely to look for such a notice. You may choose to offer,
and charge a fee for, warranty, support, indemnity or liability obligations to one or more
recipients of Licensed Product. However, you may do so only on your own behalf, and not on behalf
of the Licensor or any Contributor. You must make it clear that any such warranty, support,
indemnity or liability obligation is offered by you alone, and you hereby agree to indemnify the
Licensor and every Contributor for any liability incurred by the Licensor or such Contributor as a
result of warranty, support, indemnity or liability terms you offer.
f. Distribution of Executable Versions. You may distribute Licensed Product as an executable program under a license of your choice that may contain terms different from this License provided (i) you have satisfied the requirements of Sections 4(a) through 4(e) for that distribution, (ii) you include a conspicuous notice in the executable version, related documentation and collateral materials stating that the Source Code version of the Licensed Product is available under the terms of this License, including a description of how and where you have fulfilled the obligations of Section 4(b), (iii) you retain all existing copyright notices in the Licensed Product, and (iv) you make it clear that any terms that differ from this License are offered by you alone, not by Licensor or any Contributor. You hereby agree to indemnify the Licensor and every Contributor for any liability incurred by Licensor or such Contributor as a result of any terms you offer.
f. Distribution of Executable Versions. You may distribute Licensed Product as an executable
program under a license of your choice that may contain terms different from this License provided
(i) you have satisfied the requirements of Sections 4(a) through 4(e) for that distribution, (ii)
you include a conspicuous notice in the executable version, related documentation and collateral
materials stating that the Source Code version of the Licensed Product is available under the terms
of this License, including a description of how and where you have fulfilled the obligations of
Section 4(b), (iii) you retain all existing copyright notices in the Licensed Product, and (iv) you
make it clear that any terms that differ from this License are offered by you alone, not by
Licensor or any Contributor. You hereby agree to indemnify the Licensor and every Contributor for
any liability incurred by Licensor or such Contributor as a result of any terms you offer.
g. Distribution of Derivative Works. You may create Derivative Works (e.g., combinations of some or all of the Licensed Product with other code) and distribute the Derivative Works as products under any other license you select, with the proviso that the requirements of this License are fulfilled for those portions of the Derivative Works that consist of the Licensed Product or any Modifications thereto.
g. Distribution of Derivative Works. You may create Derivative Works (e.g., combinations of
some or all of the Licensed Product with other code) and distribute the Derivative Works as
products under any other license you select, with the proviso that the requirements of this License
are fulfilled for those portions of the Derivative Works that consist of the Licensed Product or
any Modifications thereto.
5. Inability to Comply Due to Statute or Regulation.
If it is impossible for you to comply with any of the terms of this License with respect to some or all of the Licensed Product due to statute, judicial order, or regulation, then you must (i) comply with the terms of this License to the maximum extent possible, (ii) cite the statute or regulation that prohibits you from adhering to the License, and (iii) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 4(d), and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill at computer programming to be able to understand it.
If it is impossible for you to comply with any of the terms of this License with respect to some or
all of the Licensed Product due to statute, judicial order, or regulation, then you must (i) comply
with the terms of this License to the maximum extent possible, (ii) cite the statute or regulation
that prohibits you from adhering to the License, and (iii) describe the limitations and the code
they affect. Such description must be included in the LEGAL file described in Section 4(d), and
must be included with all distributions of the Source Code. Except to the extent prohibited by
statute or regulation, such description must be sufficiently detailed for a recipient of ordinary
skill at computer programming to be able to understand it.
6. Application of This License.
This License applies to code to which Licensor or Contributor has attached the Notice in Exhibit A, which is incorporated herein by this reference.
This License applies to code to which Licensor or Contributor has attached the Notice in Exhibit A,
which is incorporated herein by this reference.
7. Versions of This License.
a. Version. The Motosoto Open Source License is derived from the Jabber Open Source License. All changes are related to applicable law and the location of court.
a. Version. The Motosoto Open Source License is derived from the Jabber Open Source License.
All changes are related to applicable law and the location of court.
b. New Versions. Licensor may publish from time to time revised and/or new versions of the License.
b. New Versions. Licensor may publish from time to time revised and/or new versions of the
License.
c. Effect of New Versions. Once Licensed Product has been published under a particular version of the License, you may always continue to use it under the terms of that version. You may also choose to use such Licensed Product under the terms of any subsequent version of the License published by Licensor. No one other than Lic ensor has the right to modify the terms applicable to Licensed Product created under this License.
c. Effect of New Versions. Once Licensed Product has been published under a particular version
of the License, you may always continue to use it under the terms of that version. You may also
choose to use such Licensed Product under the terms of any subsequent version of the License
published by Licensor. No one other than Lic ensor has the right to modify the terms applicable to
Licensed Product created under this License.
d. Derivative Works of this License. If you create or use a modified version of this License, which you may do only in order to apply it to software that is not already a Licensed Product under this License, you must rename your license so that it is not confusingly similar to this License, and must make it clear that your license contains terms that differ from this License. In so naming your license, you may not use any trademark of Licensor or any Contributor.
d. Derivative Works of this License. If you create or use a modified version of this License,
which you may do only in order to apply it to software that is not already a Licensed Product under
this License, you must rename your license so that it is not confusingly similar to this License,
and must make it clear that your license contains terms that differ from this License. In so naming
your license, you may not use any trademark of Licensor or any Contributor.
8. Disclaimer of Warranty.
LICENSED PRODUCT IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE LICENSED PRODUCT IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LICENSED PRODUCT IS WITH YOU. SHOULD LICENSED PRODUCT PROVE DEFECTIVE IN ANY RESPECT, YOU (AND NOT THE LICENSOR OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF LICENSED PRODUCT IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
LICENSED PRODUCT IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE LICENSED PRODUCT IS
FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE LICENSED PRODUCT IS WITH YOU. SHOULD LICENSED PRODUCT PROVE
DEFECTIVE IN ANY RESPECT, YOU (AND NOT THE LICENSOR OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF
ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
PART OF THIS LICENSE. NO USE OF LICENSED PRODUCT IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
DISCLAIMER.
9. Termination.
a. Automatic Termination Upon Breach. This license and the rights granted hereunder will terminate automatically if you fail to comply with the terms herein and fail to cure such breach within thirty (30) days of becoming aware of the breach. All sublicenses to the Licensed Product that are properly granted shall survive any termination of this license. Provisions that, by their nature, must remain in effect beyond the termination of this License, shall survive.
a. Automatic Termination Upon Breach. This license and the rights granted hereunder will
terminate automatically if you fail to comply with the terms herein and fail to cure such breach
within thirty (30) days of becoming aware of the breach. All sublicenses to the Licensed Product
that are properly granted shall survive any termination of this license. Provisions that, by their
nature, must remain in effect beyond the termination of this License, shall survive.
b. Termination Upon Assertion of Patent Infringement. If you initiate litigation by asserting a patent infringement claim (excluding declaratory judgment actions) against Licensor or a Contributor (Licensor or Contributor against whom you file such an action is referred to herein as "Respondent") alleging that Licensed Product directly or indirectly infringes any patent, then any and all rights granted by such Respondent to you under Sections 1 or 2 of this License shall terminate prospectively upon sixty (60) days notice from Respondent (the "Notice Period") unless within that Notice Period you either agree in writing (i) to pay Respondent a mutually agreeable reasonably royalty for your past or future use of Licensed Product made by such Respondent, or (ii) withdraw your litigation claim with respect to Licensed Product against such Respondent. If within said Notice Period a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Licensor to you under Sections 1 and 2 automatically terminate at the expiration of said Notice Period.
b. Termination Upon Assertion of Patent Infringement. If you initiate litigation by asserting
a patent infringement claim (excluding declaratory judgment actions) against Licensor or a
Contributor (Licensor or Contributor against whom you file such an action is referred to herein as
"Respondent") alleging that Licensed Product directly or indirectly infringes any patent, then any
and all rights granted by such Respondent to you under Sections 1 or 2 of this License shall
terminate prospectively upon sixty (60) days notice from Respondent (the "Notice Period") unless
within that Notice Period you either agree in writing (i) to pay Respondent a mutually agreeable
reasonably royalty for your past or future use of Licensed Product made by such Respondent, or (ii)
withdraw your litigation claim with respect to Licensed Product against such Respondent. If within
said Notice Period a reasonable royalty and payment arrangement are not mutually agreed upon in
writing by the parties or the litigation claim is not withdrawn, the rights granted by Licensor to
you under Sections 1 and 2 automatically terminate at the expiration of said Notice Period.
c. Reasonable Value of This License. If you assert a patent infringement claim against Respondent alleging that Licensed Product directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by said Respondent under Sections 1 and 2 shall be taken into account in determining the amount or value of any payment or license.
c. Reasonable Value of This License. If you assert a patent infringement claim against
Respondent alleging that Licensed Product directly or indirectly infringes any patent where such
claim is resolved (such as by license or settlement) prior to the initiation of patent infringement
litigation, then the reasonable value of the licenses granted by said Respondent under Sections 1
and 2 shall be taken into account in determining the amount or value of any payment or license.
d. No Retroactive Effect of Termination. In the event of termination under Sections 9(a) or 9(b) above, all end user license agreements (excluding licenses to distributors and reselle rs) that have been validly granted by you or any distributor hereunder prior to termination shall survive termination.
d. No Retroactive Effect of Termination. In the event of termination under Sections 9(a) or
9(b) above, all end user license agreements (excluding licenses to distributors and reselle rs)
that have been validly granted by you or any distributor hereunder prior to termination shall
survive termination.
10. Limitation of Liability.
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE LICENSOR, ANY CONTRIBUTOR, OR ANY DISTRIBUTOR OF LICENSED PRODUCT, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR
OTHERWISE, SHALL THE LICENSOR, ANY CONTRIBUTOR, OR ANY DISTRIBUTOR OF LICENSED PRODUCT, OR ANY
SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES,
EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY's
NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE 
EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY 
NOT APPLY TO YOU.
11. Responsibility for Claims. 
As between Licensor and Contributors, each party is responsible for claims and damages arising, 
directly or indirectly, out of its utilization of rights under this License. You agree to work with 
Licensor and Contributors to distribute such responsibility on an equitable basis. Nothing herein is 
intended or shall be deemed to constitute any admission of liability.
12. U.S. Government End Users. 
The Licensed Product is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), 
consisting of "commercial computer software" and "commercial computer software documentation," 
as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 
48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire 
Licensed Product with only those rights set forth herein.
13. Miscellaneous. 
This License represents the complete agreement concerning the subject matter hereof. If any 
provision of this License is held to be unenforceable, such provision shall be reformed only 
to the extent necessary to make it enforceable. This License shall be governed by Dutch law 
provisions. The application of the United Nations Convention on Contracts for the International 
Sale of Goods is expressly excluded. You and Licensor expressly waive any rights to a jury trial 
in any litigation concerning Licensed Product or this License. Any law or regulation that provides 
that the language of a contract shall be construed against the drafter shall not apply to this License.
14. Definition of "You" in This License. 
"You" throughout this License, whether in upper or lower case, means an individual or a legal entity 
exercising rights under, and complying with all of the terms of, this License or a future version of 
this License issued under Section 7. For legal entities, "you" includes any entity that controls, is 
controlled by, or is under common control with you. For purposes of this definition, "control" means 
(i) the power, direct or indirect, to cause the direction or management of such entity, whether by 
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, 
or (iii) beneficial ownership of such entity.
15. Glossary.
All defined terms in this License that are used in more than one Section of this License are 
repeated here, in alphabetical order, for the convenience of the reader. The Section of this 
License in which each defined term is first used is shown in parentheses. 
Contributor: Each person or entity who created or contributed to the creation of, and distributed, a Modification. (See Section 2)
Derivative Works: That term as used in this License is defined under Dutch copyright law. (See Section 1(b))
License: This Motosoto Open Source License. (See first paragraph of License)
Licensed Product: Any Motosoto Product licensed pursuant to this License. The term
"Licensed Product" includes all previous Modifications from any Contributor that you receive. 
(See first paragraph of License and Section 2)
Licensor: Motosoto.Com B.V.. (See first paragraph of License)
Modifications: Any additions to or deletions from the substance or structure of (i) a file 
containing Licensed Product, or (ii) any new file that contains any part of Licensed Product. (See Section 2)
Notice: The notice contained in Exhibit A. (See Section 4(e))
Source Code: The preferred form for making modifications to the Licensed Product, including 
all modules contained therein, plus any associated interface definition files, scripts used 
to control compilation and installation of an executable program, or a list of differential 
comparisons against the Source Code of the Licensed Product. (See Section 1(a))
You: This term is defined in Section 14 of this License.
 
EXHIBIT A
The Notice below must appear in each file of the Source Code of any copy you distribute of the Licensed Product or any Modifications thereto. Contributors to any Modifications may add their own copyright notices to identify their own contributions.
License:
The contents of this file are subject to the Motosoto Open Source License Version 0.9 (the "License"). You may not copy or use this file, in either source code or executable form, except in compliance with the License. You may obtain a copy of the License at http://www.motosoto.com/license/ or at http://www.opensource.org/.
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License.
Copyrights:
Portions created by or assigned to Motosoto.com B.V. are Copyright (c) 2000-2001 Motosoto.com B.V.
All Rights Reserved. Contact information for Motosoto.com B.V. is available at http://www.motosoto.com/.
Acknowledgements
Special thanks to the Motosoto Open Source Contributors for their suggestions and support of Motosoto.
Modifications:

144
options/license/SMAIL-GPL Normal file
View File

@ -0,0 +1,144 @@
SMAIL GENERAL PUBLIC LICENSE
(Clarified 11 Feb 1988)
Copyright (C) 1988 Landon Curt Noll & Ronald S. Karr
Copyright (C) 1992 Ronald S. Karr
Copyleft (GNU) 1988 Landon Curt Noll & Ronald S. Karr
Everyone is permitted to copy and distribute verbatim copies
of this license, but changing it is not allowed. You can also
use this wording to make the terms for other programs.
The license agreements of most software companies keep you at the
mercy of those companies. By contrast, our general public license is
intended to give everyone the right to share SMAIL. To make sure that
you get the rights we want you to have, we need to make restrictions
that forbid anyone to deny you these rights or to ask you to surrender
the rights. Hence this license agreement.
Specifically, we want to make sure that you have the right to give
away copies of SMAIL, that you receive source code or else can get it
if you want it, that you can change SMAIL or use pieces of it in new
free programs, and that you know you can do these things.
To make sure that everyone has such rights, we have to forbid you to
deprive anyone else of these rights. For example, if you distribute
copies of SMAIL, you must give the recipients all the rights that you
have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
Also, for our own protection, we must make certain that everyone
finds out that there is no warranty for SMAIL. If SMAIL is modified by
someone else and passed on, we want its recipients to know that what
they have is not what we distributed, so that any problems introduced
by others will not reflect on our reputation.
Therefore we (Landon Curt Noll and Ronald S. Karr) make the following
terms which say what you must do to be allowed to distribute or change
SMAIL.
COPYING POLICIES
1. You may copy and distribute verbatim copies of SMAIL source code
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1988 Landon Curt Noll & Ronald S. Karr" (or with whatever year is
appropriate); keep intact the notices on all files that refer to this
License Agreement and to the absence of any warranty; and give any
other recipients of the SMAIL program a copy of this License
Agreement along with the program. You may charge a distribution fee
for the physical act of transferring a copy.
2. You may modify your copy or copies of SMAIL or any portion of it,
and copy and distribute such modifications under the terms of
Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of SMAIL or
any part thereof, to be licensed at no charge to all third
parties on terms identical to those contained in this License
Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
3. You may copy and distribute SMAIL (or a portion or derivative of it,
under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for non-commercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer SMAIL
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer SMAIL is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.
5. If you wish to incorporate parts of SMAIL into other free
programs whose distribution conditions are different, write to Landon
Curt Noll & Ronald S. Karr via the Free Software Foundation at 51
Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. We have not yet
worked out a simple rule that can be stated here, but we will often
permit this. We will be guided by the two goals of preserving the
free status of all derivatives of our free software and of promoting
the sharing and reuse of software.
Your comments and suggestions about our licensing policies and our
software are welcome! This contract was based on the contract made by
the Free Software Foundation. Please contact the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
USA, or call (617) 542-5942 for details on copylefted material in
general.
NO WARRANTY
BECAUSE SMAIL IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO
WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING, LANDON CURT NOLL & RONALD S. KARR AND/OR
OTHER PARTIES PROVIDE SMAIL "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF SMAIL IS WITH
YOU. SHOULD SMAIL PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL LANDON CURT NOLL &
RONALD S. KARR AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
SMAIL AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) SMAIL, EVEN IF YOU HAVE
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY
ANY OTHER PARTY.

View File

@ -0,0 +1,11 @@
This software may be redistributed under the terms of the GPL, LGPL,
modified BSD, or Artistic license, or any of the other OSI approved
licenses listed at http://www.opensource.org/licenses/alphabetical.
Distribution is allowed under all of these licenses, or any smaller
subset of multiple or just one of these licenses.
When using a packaged version, please refer to the package metadata to see
under which license terms it was distributed. Alternatively, a distributor
may choose to replace the LICENSE section of the documentation and/or
include a LICENSE file to reflect the license(s) they chose to redistribute
under.

View File

@ -0,0 +1,17 @@
Copyright (C) 2008, Damien Miller
Copyright (C) 2011, Alex Hornung
Permission to use, copy, and modify this software with or without fee
is hereby granted, provided that this entire notice is included in
all copies of any software which is or includes a copy or
modification of this software.
You may use this code under the GNU public license if you so wish. Please
contribute changes back to the authors under this freer than GPL license
so that we may further the use of strong encryption without limitations to
all.
THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
PURPOSE.

View File

@ -0,0 +1,16 @@
Mini-XML
Copyright © 2003-2024 by Michael R Sweet
(Optional) Exceptions to the Apache 2.0 License:
================================================
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 or LGPLv2 (“Combined Software”) and if
a court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2 or LGPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of the
License, but only in their entirety and only with respect to the Combined
Software.

5
options/license/wwl Normal file
View File

@ -0,0 +1,5 @@
db@FreeBSD.ORG wrote this file. As long as you retain this notice you
can do whatever you want with this code, except you may not
license it under any form of the GPL.
A postcard or QSL card showing me you appreciate
this code would be nice. Diane Bruce va3db

View File

@ -145,6 +145,7 @@ confirm_delete_selected=Êtes-vous sûr de vouloir supprimer tous les éléments
name=Nom
value=Valeur
readme=Lisez-moi
filter=Filtrer
filter.clear=Effacer le filtre
@ -1032,6 +1033,8 @@ fork_to_different_account=Créer une bifurcation vers un autre compte
fork_visibility_helper=La visibilité d'un dépôt bifurqué ne peut pas être modifiée.
fork_branch=Branche à cloner sur la bifurcation
all_branches=Toutes les branches
view_all_branches=Voir toutes les branches
view_all_tags=Voir toutes les étiquettes
fork_no_valid_owners=Ce dépôt ne peut pas être bifurqué car il na pas de propriétaire valide.
fork.blocked_user=Impossible de bifurquer le dépôt car vous êtes bloqué par son propriétaire.
use_template=Utiliser ce modèle
@ -1043,6 +1046,8 @@ generate_repo=Générer un dépôt
generate_from=Générer depuis
repo_desc=Description
repo_desc_helper=Décrire brièvement votre dépôt
repo_no_desc=Aucune description fournie
repo_lang=Langue
repo_gitignore_helper=Sélectionner quelques .gitignore prédéfinies
repo_gitignore_helper_desc=De nombreux outils et compilateurs génèrent des fichiers résiduels qui n'ont pas besoin d'être supervisés par git. Composez un .gitignore à laide de cette liste des languages de programmation courants.
issue_labels=Jeu de labels pour les tickets
@ -1668,12 +1673,26 @@ issues.delete.title=Supprimer ce ticket ?
issues.delete.text=Voulez-vous vraiment supprimer ce ticket ? (Cette opération supprimera définitivement tout le contenu. Envisagez plutôt de le fermer si vous avez l'intention de l'archiver)
issues.tracker=Minuteur
issues.timetracker_timer_start=Démarrer le minuteur
issues.timetracker_timer_stop=Arrêter le minuteur
issues.timetracker_timer_discard=Annuler le minuteur
issues.timetracker_timer_manually_add=Pointer du temps
issues.time_estimate_placeholder=1h 2m
issues.time_estimate_set=Définir le temps estimé
issues.time_estimate_display=Estimation : %s
issues.change_time_estimate_at=a changé le temps estimé à <b>%s</b> %s
issues.remove_time_estimate_at=a supprimé le temps estimé %s
issues.time_estimate_invalid=Le format du temps estimé est invalide
issues.start_tracking_history=`a commencé son travail %s.`
issues.tracker_auto_close=Le minuteur sera automatiquement arrêté quand le ticket sera fermé.
issues.tracking_already_started=`Vous avez déjà un minuteur en cours sur <a href="%s">un autre ticket</a> !`
issues.stop_tracking_history=`a fini de travailler sur <b>%s</b> %s.`
issues.cancel_tracking_history=`a abandonné son minuteur %s.`
issues.del_time=Supprimer ce minuteur du journal
issues.add_time_history=`a pointé du temps de travail %s.`
issues.del_time_history=`a supprimé son temps de travail %s.`
issues.add_time_manually=Temps pointé manuellement
issues.add_time_hours=Heures
issues.add_time_minutes=Minutes
issues.add_time_sum_to_small=Aucun minuteur n'a été saisi.
@ -1926,6 +1945,10 @@ pulls.delete.title=Supprimer cette demande d'ajout ?
pulls.delete.text=Voulez-vous vraiment supprimer cet demande d'ajout ? (Cela supprimera définitivement tout le contenu. Envisagez de le fermer à la place, si vous avez l'intention de le garder archivé)
pulls.recently_pushed_new_branches=Vous avez soumis sur la branche <strong>%[1]s</strong> %[2]s
pulls.upstream_diverging_prompt_behind_1=Cette branche est en retard de %d révision sur %s
pulls.upstream_diverging_prompt_behind_n=Cette branche est en retard de %d révisions sur %s
pulls.upstream_diverging_prompt_base_newer=La branche de base %s a de nouveaux changements
pulls.upstream_diverging_merge=Synchroniser la bifurcation
pull.deleted_branch=(supprimé) : %s
pull.agit_documentation=Voir la documentation sur AGit
@ -3513,6 +3536,8 @@ alpine.repository=Informations sur le Dépôt
alpine.repository.branches=Branches
alpine.repository.repositories=Dépôts
alpine.repository.architectures=Architectures
arch.registry=Ajouter un serveur avec un dépôt et une architecture liés dans <code>/etc/pacman.conf</code> :
arch.install=Synchroniser le paquet avec pacman :
arch.repository=Informations sur le Dépôt
arch.repository.repositories=Dépôts
arch.repository.architectures=Architectures

View File

@ -145,6 +145,7 @@ confirm_delete_selected=Deimhnigh chun gach earra roghnaithe a scriosadh?
name=Ainm
value=Luach
readme=Readme
filter=Scagaire
filter.clear=Scagaire Soiléir
@ -1032,6 +1033,8 @@ fork_to_different_account=Forc chuig cuntas difriúil
fork_visibility_helper=Ní féidir infheictheacht stór forcailte a athrú.
fork_branch=Brainse le clónú chuig an bhforc
all_branches=Gach brainse
view_all_branches=Féach ar gach brainse
view_all_tags=Féach ar gach clib
fork_no_valid_owners=Ní féidir an stór seo a fhorcáil toisc nach bhfuil úinéirí bailí ann.
fork.blocked_user=Ní féidir an stór a fhorcáil toisc go bhfuil úinéir an stórais bac ort.
use_template=Úsáid an teimpléad seo
@ -1043,6 +1046,8 @@ generate_repo=Cruthaigh Stóras
generate_from=Gin Ó
repo_desc=Cur síos
repo_desc_helper=Cuir isteach tuairisc ghearr (roghnach)
repo_no_desc=Níor tugadh tuairisc
repo_lang=Teangacha
repo_gitignore_helper=Roghnaigh teimpléid .gitignore.
repo_gitignore_helper_desc=Roghnaigh na comhaid nach bhfuil le rianú ó liosta teimpléid do theangacha coitianta. Cuirtear déantáin tipiciúla a ghineann uirlisí tógála gach teanga san áireamh ar.gitignore de réir réamhshocraithe.
issue_labels=Lipéid Eisiúna
@ -1668,12 +1673,26 @@ issues.delete.title=Scrios an t-eagrán seo?
issues.delete.text=An bhfuil tú cinnte gur mhaith leat an cheist seo a scriosadh? (Bainfidh sé seo an t-inneachar go léir go buan. Smaoinigh ar é a dhúnadh ina ionad sin, má tá sé i gceist agat é a choinneáil i gcartlann)
issues.tracker=Rianaitheoir Ama
issues.timetracker_timer_start=Amadóir tosaithe
issues.timetracker_timer_stop=Stop an t-amadóir
issues.timetracker_timer_discard=Déan an t-amadóir a scriosadh
issues.timetracker_timer_manually_add=Cuir Am leis
issues.time_estimate_placeholder=1u 2n
issues.time_estimate_set=Socraigh am measta
issues.time_estimate_display=Meastachán: %s
issues.change_time_estimate_at=d'athraigh an meastachán ama go <b>%s</b> %s
issues.remove_time_estimate_at=baineadh meastachán ama %s
issues.time_estimate_invalid=Tá formáid meastachán ama neamhbhailí
issues.start_tracking_history=thosaigh ag obair %s
issues.tracker_auto_close=Stopfar ama go huathoibríoch nuair a dhúnfar an tsaincheist seo
issues.tracking_already_started=`Tá tús curtha agat cheana féin ag rianú ama ar <a href="%s">eagrán eile</a>!`
issues.stop_tracking_history=d'oibrigh do <b>%s</b> %s
issues.cancel_tracking_history=`rianú ama curtha ar ceal %s`
issues.del_time=Scrios an log ama seo
issues.add_time_history=cuireadh am caite <b>%s</b> %s leis
issues.del_time_history=`an t-am caite scriosta %s`
issues.add_time_manually=Cuir Am leis de Láimh
issues.add_time_hours=Uaireanta
issues.add_time_minutes=Miontuairi
issues.add_time_sum_to_small=Níor iontráilíodh aon am.
@ -1926,6 +1945,10 @@ pulls.delete.title=Scrios an t-iarratas tarraingthe seo?
pulls.delete.text=An bhfuil tú cinnte gur mhaith leat an t-iarratas tarraingthe seo a scriosadh? (Bainfidh sé seo an t-inneachar go léir go buan. Smaoinigh ar é a dhúnadh ina ionad sin, má tá sé i gceist agat é a choinneáil i gcartlann)
pulls.recently_pushed_new_branches=Bhrúigh tú ar bhrainse <strong>%[1]s</strong> %[2]s
pulls.upstream_diverging_prompt_behind_1=Tá an brainse seo %d tiomantas taobh thiar de %s
pulls.upstream_diverging_prompt_behind_n=Tá an brainse seo %d geallta taobh thiar de %s
pulls.upstream_diverging_prompt_base_newer=Tá athruithe nua ar an mbunbhrainse %s
pulls.upstream_diverging_merge=Forc sionc
pull.deleted_branch=(scriosta): %s
pull.agit_documentation=Déan athbhreithniú ar dhoiciméid faoi AGit
@ -3513,6 +3536,8 @@ alpine.repository=Eolas Stórais
alpine.repository.branches=Brainsí
alpine.repository.repositories=Stórais
alpine.repository.architectures=Ailtireachtaí
arch.registry=Cuir freastalaí leis an stór agus an ailtireacht ghaolmhar le <code>/etc/pacman.conf</code>:
arch.install=Sioncronaigh pacáiste le pacman:
arch.repository=Eolas Stórais
arch.repository.repositories=Stórais
arch.repository.architectures=Ailtireachtaí

View File

@ -76,29 +76,79 @@ loading=Memuat…
archived=Diarsipkan
concept_code_repository=Repositori
show_full_screen=Tampilkan layar penuh
download_logs=Unduh Logs
confirm_delete_selected=Konfirmasi untuk menghapus semua item yang dipilih?
name=Nama
value=Nilai
readme=Baca saya
filter=Saring
filter.clear=Hapus Filter
filter.is_archived=Diarsipkan
filter.not_archived=Tidak Diarsipkan
filter.is_template=Contoh
filter.public=Publik
filter.private=Pribadi
no_results_found=Hasil tidak ditemukan.
[search]
search=Cari...
type_tooltip=Tipe pencarian
fuzzy_tooltip=Termasuk juga hasil yang mendekati kata pencarian
exact_tooltip=Hanya menampilkan hasil yang cocok dengan istilah pencarian
repo_kind=Cari repo...
user_kind=Telusuri pengguna...
org_kind=Cari organisasi...
team_kind=Cari tim...
code_kind=Cari kode...
code_search_unavailable=Pencarian kode saat ini tidak tersedia. Silahkan hubungi administrator.
branch_kind=Cari cabang...
[aria]
navbar=Bar Navigasi
footer=Footer
footer.software=Tentang Software
footer.links=Tautan
[heatmap]
number_of_contributions_in_the_last_12_months=%s Kontribusi pada 12 bulan terakhir
no_contributions=Belum ada kontribusi
less=Lebih sedikit
more=Lebih banyak
[editor]
buttons.heading.tooltip=Tambahkan heading
buttons.bold.tooltip=Tambahkan teks Tebal
buttons.italic.tooltip=Tambahkan teks Miring
buttons.quote.tooltip=Kutip teks
buttons.code.tooltip=Tambah Kode
buttons.link.tooltip=Tambahkan tautan
buttons.list.unordered.tooltip=Tambah daftar titik
buttons.list.ordered.tooltip=Tambah daftar angka
buttons.list.task.tooltip=Tambahkan daftar tugas
buttons.table.add.insert=Tambah
buttons.mention.tooltip=Tandai pengguna atau tim
buttons.ref.tooltip=Merujuk pada isu atau permintaan tarik
buttons.switch_to_legacy.tooltip=Gunakan editor versi lama
buttons.enable_monospace_font=Aktifkan font monospace
buttons.disable_monospace_font=Non-Aktifkan font monospace
[filter]
string.asc=A - Z
string.desc=Z - A
[error]
occurred=Terjadi kesalahan
report_message=Jika Anda yakin ini adalah bug Gitea, silakan cari isu di <a href="%s" target="_blank">GitHub</a> atau buka isu baru jika diperlukan.
not_found=Target tidak dapat ditemukan.
[startpage]
app_desc=Sebuah layanan hosting Git sendiri yang tanpa kesulitan
@ -118,8 +168,10 @@ path=Jalur
repo_path=Jalur akar repositori
email_title=Pengaturan email
smtp_addr=Host SMTP
smtp_port=Port SMTP
smtp_from=Kirim Email Sebagai
register_confirm=Perlu Konfirmasi Email Saat Pendaftaran
mail_notify=Aktifkan Notifikasi Email
disable_gravatar=Menonaktifkan Gravatar
@ -140,6 +192,7 @@ my_orgs=Organisasi Saya
my_mirrors=Duplikat Saya
view_home=Lihat %s
show_archived=Diarsipkan
show_private=Pribadi
@ -481,6 +534,7 @@ email_notifications.enable=Aktifkan Pemberitahuan Surel
email_notifications.disable=Nonaktifkan Email Notifikasi
email_notifications.submit=Pasang Pengaturan Email
visibility.public=Publik
visibility.private=Pribadi
[repo]
@ -522,7 +576,9 @@ delete_preexisting_label=Hapus
desc.private=Pribadi
desc.public=Publik
desc.template=Contoh
desc.archived=Diarsipkan
template.webhooks=Webhooks
template.topics=Topik
@ -947,6 +1003,7 @@ settings=Pengaturan
settings.full_name=Nama Lengkap
settings.website=Situs web
settings.location=Lokasi
settings.visibility.public=Publik
settings.visibility.private_shortname=Pribadi
settings.update_settings=Perbarui Setelan
@ -1033,6 +1090,7 @@ users.created=Dibuat
users.edit=Edit
users.auth_source=Sumber Otentikasi
users.local=Lokal
users.list_status_filter.menu_text=Saring
users.list_status_filter.is_admin=Pengelola
emails.activated=Diaktifkan

View File

@ -26,9 +26,9 @@ func generateMockStepsLog(logCur actions.LogCursor) (stepsLog []*actions.ViewSte
"::endgroup::",
"message for: step={step}, cursor={cursor}",
"message for: step={step}, cursor={cursor}",
"message for: step={step}, cursor={cursor}",
"message for: step={step}, cursor={cursor}",
"message for: step={step}, cursor={cursor}",
"##[group]test group for: step={step}, cursor={cursor}",
"in group msg for: step={step}, cursor={cursor}",
"##[endgroup]",
}
cur := logCur.Cursor // usually the cursor is the "file offset", but here we abuse it as "line number" to make the mock easier, intentionally
for i := 0; i < util.Iif(logCur.Step == 0, 3, 1); i++ {
@ -52,6 +52,10 @@ func MockActionsRunsJobs(ctx *context.Context) {
req := web.GetForm(ctx).(*actions.ViewRequest)
resp := &actions.ViewResponse{}
resp.State.Run.TitleHTML = `mock run title <a href="/">link</a>`
resp.State.Run.Status = actions_model.StatusRunning.String()
resp.State.Run.CanCancel = true
resp.State.Run.CanDeleteArtifact = true
resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
Name: "artifact-a",
Size: 100 * 1024,

View File

@ -504,19 +504,16 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
if !util.SliceContainsString(types, viewType, true) {
viewType = "all"
}
var (
assigneeID = ctx.FormInt64("assignee")
posterID = ctx.FormInt64("poster")
mentionedID int64
reviewRequestedID int64
reviewedID int64
)
// TODO: "assignee" should also use GetFilterUserIDByName in the future to support usernames directly
assigneeID := ctx.FormInt64("assignee")
posterUsername := ctx.FormString("poster")
posterUserID := shared_user.GetFilterUserIDByName(ctx, posterUsername)
var mentionedID, reviewRequestedID, reviewedID int64
if ctx.IsSigned {
switch viewType {
case "created_by":
posterID = ctx.Doer.ID
posterUserID = ctx.Doer.ID
case "mentioned":
mentionedID = ctx.Doer.ID
case "assigned":
@ -564,7 +561,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
ProjectID: projectID,
AssigneeID: assigneeID,
MentionedID: mentionedID,
PosterID: posterID,
PosterID: posterUserID,
ReviewRequestedID: reviewRequestedID,
ReviewedID: reviewedID,
IsPull: isPullOption,
@ -646,7 +643,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
},
RepoIDs: []int64{repo.ID},
AssigneeID: assigneeID,
PosterID: posterID,
PosterID: posterUserID,
MentionedID: mentionedID,
ReviewRequestedID: reviewRequestedID,
ReviewedID: reviewedID,
@ -800,16 +797,16 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
ctx.Data["IssueStats"] = issueStats
ctx.Data["OpenCount"] = issueStats.OpenCount
ctx.Data["ClosedCount"] = issueStats.ClosedCount
linkStr := "%s?q=%s&type=%s&sort=%s&state=%s&labels=%s&milestone=%d&project=%d&assignee=%d&poster=%d&archived=%t"
linkStr := "%s?q=%s&type=%s&sort=%s&state=%s&labels=%s&milestone=%d&project=%d&assignee=%d&poster=%v&archived=%t"
ctx.Data["AllStatesLink"] = fmt.Sprintf(linkStr, ctx.Link,
url.QueryEscape(keyword), url.QueryEscape(viewType), url.QueryEscape(sortType), "all", url.QueryEscape(selectLabels),
milestoneID, projectID, assigneeID, posterID, archived)
milestoneID, projectID, assigneeID, url.QueryEscape(posterUsername), archived)
ctx.Data["OpenLink"] = fmt.Sprintf(linkStr, ctx.Link,
url.QueryEscape(keyword), url.QueryEscape(viewType), url.QueryEscape(sortType), "open", url.QueryEscape(selectLabels),
milestoneID, projectID, assigneeID, posterID, archived)
milestoneID, projectID, assigneeID, url.QueryEscape(posterUsername), archived)
ctx.Data["ClosedLink"] = fmt.Sprintf(linkStr, ctx.Link,
url.QueryEscape(keyword), url.QueryEscape(viewType), url.QueryEscape(sortType), "closed", url.QueryEscape(selectLabels),
milestoneID, projectID, assigneeID, posterID, archived)
milestoneID, projectID, assigneeID, url.QueryEscape(posterUsername), archived)
ctx.Data["SelLabelIDs"] = labelIDs
ctx.Data["SelectLabels"] = selectLabels
ctx.Data["ViewType"] = viewType
@ -817,7 +814,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
ctx.Data["MilestoneID"] = milestoneID
ctx.Data["ProjectID"] = projectID
ctx.Data["AssigneeID"] = assigneeID
ctx.Data["PosterID"] = posterID
ctx.Data["PosterUsername"] = posterUsername
ctx.Data["Keyword"] = keyword
ctx.Data["IsShowClosed"] = isShowClosed
switch {
@ -838,7 +835,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
pager.AddParamString("milestone", fmt.Sprint(milestoneID))
pager.AddParamString("project", fmt.Sprint(projectID))
pager.AddParamString("assignee", fmt.Sprint(assigneeID))
pager.AddParamString("poster", fmt.Sprint(posterID))
pager.AddParamString("poster", posterUsername)
pager.AddParamString("archived", fmt.Sprint(archived))
ctx.Data["Page"] = pager

View File

@ -195,7 +195,9 @@ func (d *IssuePageMetaData) retrieveReviewersData(ctx *context.Context) {
var reviews issues_model.ReviewList
if d.Issue == nil {
if ctx.Doer != nil {
posterID = ctx.Doer.ID
}
} else {
posterID = d.Issue.PosterID
if d.Issue.OriginalAuthorID > 0 {

View File

@ -4,7 +4,9 @@
package user
import (
"context"
"slices"
"strconv"
"code.gitea.io/gitea/models/user"
)
@ -24,3 +26,22 @@ func MakeSelfOnTop(doer *user.User, users []*user.User) []*user.User {
}
return users
}
// GetFilterUserIDByName tries to get the user ID from the given username.
// Before, the "issue filter" passes user ID to query the list, but in many cases, it's impossible to pre-fetch the full user list.
// So it's better to make it work like GitHub: users could input username directly.
// Since it only converts the username to ID directly and is only used internally (to search issues), so no permission check is needed.
// Old usage: poster=123, new usage: poster=the-username (at the moment, non-existing username is treated as poster=0, not ideal but acceptable)
func GetFilterUserIDByName(ctx context.Context, name string) int64 {
if name == "" {
return 0
}
u, err := user.GetUserByName(ctx, name)
if err != nil {
if id, err := strconv.ParseInt(name, 10, 64); err == nil {
return id
}
return 0
}
return u.ID
}

View File

@ -31,7 +31,9 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
"code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
feed_service "code.gitea.io/gitea/services/feed"
issue_service "code.gitea.io/gitea/services/issue"
@ -375,16 +377,8 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
return
}
var (
viewType string
sortType = ctx.FormString("sort")
filterMode int
)
// Default to recently updated, unlike repository issues list
if sortType == "" {
sortType = "recentupdate"
}
sortType := util.IfZero(ctx.FormString("sort"), "recentupdate")
// --------------------------------------------------------------------------------
// Distinguish User from Organization.
@ -399,7 +393,8 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
// TODO: distinguish during routing
viewType = ctx.FormString("type")
viewType := ctx.FormString("type")
var filterMode int
switch viewType {
case "assigned":
filterMode = issues_model.FilterModeAssign
@ -443,6 +438,14 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
Team: team,
User: ctx.Doer,
}
// Get filter by author id & assignee id
// FIXME: this feature doesn't work at the moment, because frontend can't use a "user-remote-search" dropdown directly
// the existing "/posters" handlers doesn't work for this case, it is unable to list the related users correctly.
// In the future, we need something like github: "author:user1" to accept usernames directly.
posterUsername := ctx.FormString("poster")
opts.PosterID = user.GetFilterUserIDByName(ctx, posterUsername)
// TODO: "assignee" should also use GetFilterUserIDByName in the future to support usernames directly
opts.AssigneeID, _ = strconv.ParseInt(ctx.FormString("assignee"), 10, 64)
isFuzzy := ctx.FormBool("fuzzy")
@ -573,8 +576,22 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
// -------------------------------
// Fill stats to post to ctx.Data.
// -------------------------------
issueStats, err := getUserIssueStats(ctx, ctxUser, filterMode, issue_indexer.ToSearchOptions(keyword, opts).Copy(
func(o *issue_indexer.SearchOptions) { o.IsFuzzyKeyword = isFuzzy },
issueStats, err := getUserIssueStats(ctx, filterMode, issue_indexer.ToSearchOptions(keyword, opts).Copy(
func(o *issue_indexer.SearchOptions) {
o.IsFuzzyKeyword = isFuzzy
// If the doer is the same as the context user, which means the doer is viewing his own dashboard,
// it's not enough to show the repos that the doer owns or has been explicitly granted access to,
// because the doer may create issues or be mentioned in any public repo.
// So we need search issues in all public repos.
o.AllPublic = ctx.Doer.ID == ctxUser.ID
// TODO: to make it work with poster/assignee filter, then these IDs should be kept
o.AssigneeID = nil
o.PosterID = nil
o.MentionID = nil
o.ReviewRequestedID = nil
o.ReviewedID = nil
},
))
if err != nil {
ctx.ServerError("getUserIssueStats", err)
@ -630,6 +647,8 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
ctx.Data["IsShowClosed"] = isShowClosed
ctx.Data["SelectLabels"] = selectedLabels
ctx.Data["IsFuzzy"] = isFuzzy
ctx.Data["SearchFilterPosterID"] = util.Iif[any](opts.PosterID != 0, opts.PosterID, nil)
ctx.Data["SearchFilterAssigneeID"] = util.Iif[any](opts.AssigneeID != 0, opts.AssigneeID, nil)
if isShowClosed {
ctx.Data["State"] = "closed"
@ -643,7 +662,11 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
pager.AddParamString("sort", sortType)
pager.AddParamString("state", fmt.Sprint(ctx.Data["State"]))
pager.AddParamString("labels", selectedLabels)
pager.AddParamString("fuzzy", fmt.Sprintf("%v", isFuzzy))
pager.AddParamString("fuzzy", fmt.Sprint(isFuzzy))
pager.AddParamString("poster", posterUsername)
if opts.AssigneeID != 0 {
pager.AddParamString("assignee", fmt.Sprint(opts.AssigneeID))
}
ctx.Data["Page"] = pager
ctx.HTML(http.StatusOK, tplIssues)
@ -768,26 +791,9 @@ func UsernameSubRoute(ctx *context.Context) {
}
}
func getUserIssueStats(ctx *context.Context, ctxUser *user_model.User, filterMode int, opts *issue_indexer.SearchOptions) (*issues_model.IssueStats, error) {
doerID := ctx.Doer.ID
opts = opts.Copy(func(o *issue_indexer.SearchOptions) {
// If the doer is the same as the context user, which means the doer is viewing his own dashboard,
// it's not enough to show the repos that the doer owns or has been explicitly granted access to,
// because the doer may create issues or be mentioned in any public repo.
// So we need search issues in all public repos.
o.AllPublic = doerID == ctxUser.ID
o.AssigneeID = nil
o.PosterID = nil
o.MentionID = nil
o.ReviewRequestedID = nil
o.ReviewedID = nil
})
var (
err error
func getUserIssueStats(ctx *context.Context, filterMode int, opts *issue_indexer.SearchOptions) (ret *issues_model.IssueStats, err error) {
ret = &issues_model.IssueStats{}
)
doerID := ctx.Doer.ID
{
openClosedOpts := opts.Copy()

View File

@ -36,10 +36,11 @@
{{range .Labels}}
{{$exclusiveScope := .ExclusiveScope}}
{{if and (ne $previousExclusiveScope $exclusiveScope)}}
<div class="divider"></div>
<div class="divider" data-scope="{{.ExclusiveScope}}"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
<a class="item label-filter-item tw-flex tw-items-center" {{if .IsArchived}}data-is-archived{{end}} href="?labels={{.QueryString}}&assignee={{$.AssigneeID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}" data-label-id="{{.ID}}">
<a class="item label-filter-item tw-flex tw-items-center" data-label-id="{{.ID}}" data-scope="{{.ExclusiveScope}}" {{if .IsArchived}}data-is-archived{{end}}
href="?labels={{.QueryString}}&assignee={{$.AssigneeID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">
{{if .IsExcluded}}
{{svg "octicon-circle-slash"}}
{{else if .IsSelected}}

View File

@ -102,7 +102,8 @@
{{end}}
</div>
<div class="repo-button-row-right">
{{/* by default, the row-right flex grows, but on non-root tree path, it should not because the row-left might contain a long path */}}
<div class="repo-button-row-right {{if not $isTreePathRoot}}tw-flex-grow-0{{end}}">
<!-- Only show clone panel in repository home page -->
{{if $isTreePathRoot}}
<div class="clone-panel ui action tiny input">
@ -122,7 +123,6 @@
</button>
{{template "repo/clone_script" .}}{{/* the script will update `.js-clone-url` and related elements */}}
</div>
{{template "repo/cite/cite_modal" .}}
{{end}}
{{if and (not $isTreePathRoot) (not .IsViewFile) (not .IsBlame)}}{{/* IsViewDirectory (not home), TODO: split the templates, avoid using "if" tricks */}}
<a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">

View File

@ -43,22 +43,23 @@
{{end}}
{{if .ReadmeExist}}
<div class="flex-item-body tw-mt-2">
<a class="tw-flex tw-items-center tw-gap-2 muted" href="{{.TreeLink}}/{{.FileName}}">
{{svg "octicon-book"}}{{ctx.Locale.Tr "readme"}}
<a class="flex-text-block muted" href="{{.TreeLink}}/{{.FileName}}">
{{svg "octicon-book"}} {{ctx.Locale.Tr "readme"}}
</a>
</div>
{{end}}
{{if .DetectedRepoLicenses}}
<div class="flex-item-body">
<a class="tw-flex tw-items-center tw-gap-2 muted" href="{{.RepoLink}}/src/{{.Repository.DefaultBranch}}/{{PathEscapeSegments .LicenseFileName}}" title="{{StringUtils.Join .DetectedRepoLicenses ", "}}">
{{svg "octicon-law"}}{{if eq (len .DetectedRepoLicenses) 1}}{{index .DetectedRepoLicenses 0}}{{else}}{{ctx.Locale.Tr "repo.multiple_licenses"}}{{end}}
<a class="flex-text-block muted" href="{{.RepoLink}}/src/{{.Repository.DefaultBranch}}/{{PathEscapeSegments .LicenseFileName}}" title="{{StringUtils.Join .DetectedRepoLicenses ", "}}">
{{svg "octicon-law"}} {{if eq (len .DetectedRepoLicenses) 1}}{{index .DetectedRepoLicenses 0}}{{else}}{{ctx.Locale.Tr "repo.multiple_licenses"}}{{end}}
</a>
</div>
{{end}}
{{if .CitiationExist}}
<div class="flex-item-body">
<a class="tw-flex tw-items-center tw-gap-2 muted" id="cite-repo-button">
{{svg "octicon-cross-reference"}}{{ctx.Locale.Tr "repo.cite_this_repo"}}
{{template "repo/cite/cite_modal" .}}
<a class="flex-text-block muted" id="cite-repo-button">
{{svg "octicon-cross-reference"}} {{ctx.Locale.Tr "repo.cite_this_repo"}}
</a>
</div>
{{end}}

View File

@ -1,3 +1,4 @@
{{$queryLink := QueryBuild "?" "q" $.Keyword "type" $.ViewType "sort" $.SortType "state" $.State "labels" $.SelectLabels "milestone" $.MilestoneID "project" $.ProjectID "assignee" $.AssigneeID "poster" $.PosterUsername "archived" (Iif $.ShowArchivedLabels NIL)}}
<!-- Label -->
<div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item label-filter">
<span class="text">
@ -23,16 +24,17 @@
</div>
<span class="info">{{ctx.Locale.Tr "repo.issues.filter_label_exclude"}}</span>
<div class="divider"></div>
<a class="{{if .AllLabels}}active selected {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_label_no_select"}}</a>
<a class="{{if .NoLabel}}active selected {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels=0&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_label_select_no_label"}}</a>
<a class="{{if .AllLabels}}active selected {{end}}item" href="{{QueryBuild $queryLink "labels" NIL}}">{{ctx.Locale.Tr "repo.issues.filter_label_no_select"}}</a>
<a class="{{if .NoLabel}}active selected {{end}}item" href="{{QueryBuild $queryLink "labels" 0}}">{{ctx.Locale.Tr "repo.issues.filter_label_select_no_label"}}</a>
{{$previousExclusiveScope := "_no_scope"}}
{{range .Labels}}
{{$exclusiveScope := .ExclusiveScope}}
{{if and (ne $previousExclusiveScope $exclusiveScope)}}
<div class="divider"></div>
<div class="divider" data-scope="{{.ExclusiveScope}}"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
<a class="item label-filter-item tw-flex tw-items-center" {{if .IsArchived}}data-is-archived{{end}} href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.QueryString}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}" data-label-id="{{.ID}}">
<a class="item label-filter-item tw-flex tw-items-center" data-label-id="{{.ID}}" data-scope="{{.ExclusiveScope}}" {{if .IsArchived}}data-is-archived{{end}}
href="{{QueryBuild $queryLink "labels" .QueryString}}">
{{if .IsExcluded}}
{{svg "octicon-circle-slash"}}
{{else if .IsSelected}}
@ -62,13 +64,13 @@
<input type="text" placeholder="{{ctx.Locale.Tr "repo.issues.filter_milestone"}}">
</div>
<div class="divider"></div>
<a class="{{if not $.MilestoneID}}active selected {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone=0&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_milestone_all"}}</a>
<a class="{{if $.MilestoneID}}{{if eq $.MilestoneID -1}}active selected {{end}}{{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone=-1&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_milestone_none"}}</a>
<a class="{{if not $.MilestoneID}}active selected {{end}}item" href="{{QueryBuild $queryLink "milestone" 0}}">{{ctx.Locale.Tr "repo.issues.filter_milestone_all"}}</a>
<a class="{{if $.MilestoneID}}{{if eq $.MilestoneID -1}}active selected {{end}}{{end}}item" href="{{QueryBuild $queryLink "milestone" -1}}">{{ctx.Locale.Tr "repo.issues.filter_milestone_none"}}</a>
{{if .OpenMilestones}}
<div class="divider"></div>
<div class="header">{{ctx.Locale.Tr "repo.issues.filter_milestone_open"}}</div>
{{range .OpenMilestones}}
<a class="{{if $.MilestoneID}}{{if eq $.MilestoneID .ID}}active selected {{end}}{{end}}item" href="?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.ID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">
<a class="{{if $.MilestoneID}}{{if eq $.MilestoneID .ID}}active selected {{end}}{{end}}item" href="{{QueryBuild $queryLink "milestone" .ID}}">
{{svg "octicon-milestone" 16 "mr-2"}}
{{.Name}}
</a>
@ -78,7 +80,7 @@
<div class="divider"></div>
<div class="header">{{ctx.Locale.Tr "repo.issues.filter_milestone_closed"}}</div>
{{range .ClosedMilestones}}
<a class="{{if $.MilestoneID}}{{if eq $.MilestoneID .ID}}active selected {{end}}{{end}}item" href="?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.ID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">
<a class="{{if $.MilestoneID}}{{if eq $.MilestoneID .ID}}active selected {{end}}{{end}}item" href="{{QueryBuild $queryLink "milestone" .ID}}">
{{svg "octicon-milestone" 16 "mr-2"}}
{{.Name}}
</a>
@ -99,15 +101,15 @@
<i class="icon">{{svg "octicon-search" 16}}</i>
<input type="text" placeholder="{{ctx.Locale.Tr "repo.issues.filter_project"}}">
</div>
<a class="{{if not .ProjectID}}active selected {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_project_all"}}</a>
<a class="{{if eq .ProjectID -1}}active selected {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&project=-1&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_project_none"}}</a>
<a class="{{if not .ProjectID}}active selected {{end}}item" href="{{QueryBuild $queryLink "project" NIL}}">{{ctx.Locale.Tr "repo.issues.filter_project_all"}}</a>
<a class="{{if eq .ProjectID -1}}active selected {{end}}item" href="{{QueryBuild $queryLink "project" -1}}">{{ctx.Locale.Tr "repo.issues.filter_project_none"}}</a>
{{if .OpenProjects}}
<div class="divider"></div>
<div class="header">
{{ctx.Locale.Tr "repo.issues.new.open_projects"}}
</div>
{{range .OpenProjects}}
<a class="{{if $.ProjectID}}{{if eq $.ProjectID .ID}}active selected{{end}}{{end}} item tw-flex" href="?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&project={{.ID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">
<a class="{{if $.ProjectID}}{{if eq $.ProjectID .ID}}active selected{{end}}{{end}} item tw-flex" href="{{QueryBuild $queryLink "project" .ID}}">
{{svg .IconName 18 "tw-mr-2 tw-shrink-0"}}<span class="gt-ellipsis">{{.Title}}</span>
</a>
{{end}}
@ -118,7 +120,7 @@
{{ctx.Locale.Tr "repo.issues.new.closed_projects"}}
</div>
{{range .ClosedProjects}}
<a class="{{if $.ProjectID}}{{if eq $.ProjectID .ID}}active selected{{end}}{{end}} item" href="?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&project={{.ID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">
<a class="{{if $.ProjectID}}{{if eq $.ProjectID .ID}}active selected{{end}}{{end}} item" href="{{QueryBuild $queryLink "project" .ID}}">
{{svg .IconName 18 "tw-mr-2"}}{{.Title}}
</a>
{{end}}
@ -130,7 +132,7 @@
<div class="ui dropdown jump item user-remote-search" data-tooltip-content="{{ctx.Locale.Tr "repo.author_search_tooltip"}}"
data-search-url="{{if .Milestone}}{{$.RepoLink}}/issues/posters{{else}}{{$.Link}}/posters{{end}}"
data-selected-user-id="{{$.PosterID}}"
data-action-jump-url="?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={user_id}{{if $.ShowArchivedLabels}}&archived=true{{end}}"
data-action-jump-url="{{QueryBuild $queryLink "poster" NIL}}&poster={username}"
>
<span class="text">
{{ctx.Locale.Tr "repo.issues.filter_poster"}}
@ -156,11 +158,11 @@
<i class="icon">{{svg "octicon-search" 16}}</i>
<input type="text" placeholder="{{ctx.Locale.Tr "repo.issues.filter_assignee"}}">
</div>
<a class="{{if not .AssigneeID}}active selected {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_assginee_no_select"}}</a>
<a class="{{if eq .AssigneeID -1}}active selected {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee=-1&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_assginee_no_assignee"}}</a>
<a class="{{if not .AssigneeID}}active selected {{end}}item" href="{{QueryBuild $queryLink "assignee" NIL}}">{{ctx.Locale.Tr "repo.issues.filter_assginee_no_select"}}</a>
<a class="{{if eq .AssigneeID -1}}active selected {{end}}item" href="{{QueryBuild $queryLink "assignee" -1}}">{{ctx.Locale.Tr "repo.issues.filter_assginee_no_assignee"}}</a>
<div class="divider"></div>
{{range .Assignees}}
<a class="{{if eq $.AssigneeID .ID}}active selected{{end}} item tw-flex" href="?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{.ID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">
<a class="{{if eq $.AssigneeID .ID}}active selected{{end}} item tw-flex" href="{{QueryBuild $queryLink "assignee" .ID}}">
{{ctx.AvatarUtils.Avatar . 20}}{{template "repo/search_name" .}}
</a>
{{end}}
@ -175,14 +177,14 @@
</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<a class="{{if eq .ViewType "all"}}active {{end}}item" href="?q={{$.Keyword}}&type=all&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_type.all_issues"}}</a>
<a class="{{if eq .ViewType "assigned"}}active {{end}}item" href="?q={{$.Keyword}}&type=assigned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_type.assigned_to_you"}}</a>
<a class="{{if eq .ViewType "created_by"}}active {{end}}item" href="?q={{$.Keyword}}&type=created_by&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_type.created_by_you"}}</a>
<a class="{{if eq .ViewType "all"}}active {{end}}item" href="{{QueryBuild $queryLink "type" "all"}}">{{ctx.Locale.Tr "repo.issues.filter_type.all_issues"}}</a>
<a class="{{if eq .ViewType "assigned"}}active {{end}}item" href="{{QueryBuild $queryLink "type" "assigned"}}">{{ctx.Locale.Tr "repo.issues.filter_type.assigned_to_you"}}</a>
<a class="{{if eq .ViewType "created_by"}}active {{end}}item" href="{{QueryBuild $queryLink "type" "created_by"}}">{{ctx.Locale.Tr "repo.issues.filter_type.created_by_you"}}</a>
{{if .PageIsPullList}}
<a class="{{if eq .ViewType "review_requested"}}active {{end}}item" href="?q={{$.Keyword}}&type=review_requested&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_type.review_requested"}}</a>
<a class="{{if eq .ViewType "reviewed_by"}}active {{end}}item" href="?q={{$.Keyword}}&type=reviewed_by&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_type.reviewed_by_you"}}</a>
<a class="{{if eq .ViewType "review_requested"}}active {{end}}item" href="{{QueryBuild $queryLink "type" "review_requested"}}">{{ctx.Locale.Tr "repo.issues.filter_type.review_requested"}}</a>
<a class="{{if eq .ViewType "reviewed_by"}}active {{end}}item" href="{{QueryBuild $queryLink "type" "reviewed_by"}}">{{ctx.Locale.Tr "repo.issues.filter_type.reviewed_by_you"}}</a>
{{end}}
<a class="{{if eq .ViewType "mentioned"}}active {{end}}item" href="?q={{$.Keyword}}&type=mentioned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_type.mentioning_you"}}</a>
<a class="{{if eq .ViewType "mentioned"}}active {{end}}item" href="{{QueryBuild $queryLink "type" "mentioned"}}">{{ctx.Locale.Tr "repo.issues.filter_type.mentioning_you"}}</a>
</div>
</div>
{{end}}
@ -194,13 +196,13 @@
</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=latest&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=oldest&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=nearduedate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="?q={{$.Keyword}}&type={{$.ViewType}}&sort=farduedate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "latest"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "oldest"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "recentupdate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "leastupdate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "mostcomment"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "leastcomment"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "nearduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "farduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
</div>
</div>

View File

@ -7,7 +7,7 @@
<input type="hidden" name="milestone" value="{{$.MilestoneID}}">
<input type="hidden" name="project" value="{{$.ProjectID}}">
<input type="hidden" name="assignee" value="{{$.AssigneeID}}">
<input type="hidden" name="poster" value="{{$.PosterID}}">
<input type="hidden" name="poster" value="{{$.PosterUsername}}">
{{end}}
{{template "shared/search/input" dict "Value" .Keyword}}
{{if .PageIsIssueList}}

View File

@ -22,7 +22,7 @@
{{range $data.RepoLabels}}
{{$exclusiveScope := .ExclusiveScope}}
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
<div class="divider"></div>
<div class="divider" data-scope="{{.ExclusiveScope}}"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
{{template "repo/issue/sidebar/label_list_item" dict "Label" .}}
@ -32,7 +32,7 @@
{{range $data.OrgLabels}}
{{$exclusiveScope := .ExclusiveScope}}
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
<div class="divider"></div>
<div class="divider" data-scope="{{.ExclusiveScope}}"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
{{template "repo/issue/sidebar/label_list_item" dict "Label" .}}

View File

@ -4,45 +4,48 @@
<div class="ui container">
{{template "base/alert" .}}
<div class="flex-container">
{{$queryLink := QueryBuild "?" "type" $.ViewType "sort" $.SortType "state" $.State "q" $.Keyword "fuzzy" $.IsFuzzy}}
<div class="flex-container-nav">
<div class="ui secondary vertical filter menu tw-bg-transparent">
<a class="{{if eq .ViewType "your_repositories"}}active{{end}} item" href="?type=your_repositories&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
<a class="{{if eq .ViewType "your_repositories"}}active{{end}} item" href="{{QueryBuild $queryLink "type" "your_repositories"}}">
{{ctx.Locale.Tr "home.issues.in_your_repos"}}
<strong>{{CountFmt .IssueStats.YourRepositoriesCount}}</strong>
</a>
<a class="{{if eq .ViewType "assigned"}}active{{end}} item" href="?type=assigned&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
<a class="{{if eq .ViewType "assigned"}}active{{end}} item" href="{{QueryBuild $queryLink "type" "assigned"}}">
{{ctx.Locale.Tr "repo.issues.filter_type.assigned_to_you"}}
<strong>{{CountFmt .IssueStats.AssignCount}}</strong>
</a>
<a class="{{if eq .ViewType "created_by"}}active{{end}} item" href="?type=created_by&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
<a class="{{if eq .ViewType "created_by"}}active{{end}} item" href="{{QueryBuild $queryLink "type" "created_by"}}">
{{ctx.Locale.Tr "repo.issues.filter_type.created_by_you"}}
<strong>{{CountFmt .IssueStats.CreateCount}}</strong>
</a>
{{if .PageIsPulls}}
<a class="{{if eq .ViewType "review_requested"}}active{{end}} item" href="?type=review_requested&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
<a class="{{if eq .ViewType "review_requested"}}active{{end}} item" href="{{QueryBuild $queryLink "type" "review_requested"}}">
{{ctx.Locale.Tr "repo.issues.filter_type.review_requested"}}
<strong>{{CountFmt .IssueStats.ReviewRequestedCount}}</strong>
</a>
<a class="{{if eq .ViewType "reviewed_by"}}active{{end}} item" href="?type=reviewed_by&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
<a class="{{if eq .ViewType "reviewed_by"}}active{{end}} item" href="{{QueryBuild $queryLink "type" "reviewed_by"}}">
{{ctx.Locale.Tr "repo.issues.filter_type.reviewed_by_you"}}
<strong>{{CountFmt .IssueStats.ReviewedCount}}</strong>
</a>
{{end}}
<a class="{{if eq .ViewType "mentioned"}}active{{end}} item" href="?type=mentioned&sort={{$.SortType}}&state={{.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
<a class="{{if eq .ViewType "mentioned"}}active{{end}} item" href="{{QueryBuild $queryLink "type" "mentioned"}}">
{{ctx.Locale.Tr "repo.issues.filter_type.mentioning_you"}}
<strong>{{CountFmt .IssueStats.MentionCount}}</strong>
</a>
</div>
</div>
{{$queryLinkWithFilter := QueryBuild $queryLink "poster" $.SearchFilterPosterUsername "assignee" $.SearchFilterAssigneeID}}
<div class="flex-container-main content">
<div class="list-header">
<div class="small-menu-items ui compact tiny menu list-header-toggle">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=open&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
{{svg "octicon-issue-opened" 16 "tw-mr-2"}}
<div class="small-menu-items ui compact tiny menu list-header-toggle flex-items-block">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{QueryBuild $queryLink "state" "open"}}">
{{svg "octicon-issue-opened"}}
{{ctx.Locale.PrettyNumber .IssueStats.OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=closed&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">
{{svg "octicon-issue-closed" 16 "tw-mr-2"}}
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{QueryBuild $queryLink "state" "closed"}}">
{{svg "octicon-issue-closed"}}
{{ctx.Locale.PrettyNumber .IssueStats.ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a>
</div>
@ -61,14 +64,14 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span>
<div class="menu">
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active {{end}}item" href="?type={{$.ViewType}}&sort=latest&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="?type={{$.ViewType}}&sort=oldest&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="?type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="?type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=nearduedate&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="?type={{$.ViewType}}&sort=farduedate&state={{$.State}}&q={{$.Keyword}}&fuzzy={{.IsFuzzy}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "recentupdate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "leastupdate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "latest"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "latest"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "oldest"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "mostcomment"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "leastcomment"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "nearduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="{{QueryBuild $queryLinkWithFilter "sort" "farduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
</div>
</div>
</div>

View File

@ -20,7 +20,7 @@
grid-row: 2;
padding-left: 1em;
}
.repo-home-sidebar-bottom > :first-child {
.repo-home-sidebar-bottom .flex-list > :first-child {
border-top: 1px solid var(--color-secondary); /* same to .flex-list > .flex-item + .flex-item */
}
@ -43,7 +43,7 @@
grid-row: 3;
padding-left: 0;
}
.repo-home-sidebar-bottom > :first-child {
.repo-home-sidebar-bottom .flex-list > :first-child {
border-top: 0;
}
}

View File

@ -16,8 +16,27 @@ type LogLine = {
message: string;
};
const LogLinePrefixGroup = '::group::';
const LogLinePrefixEndGroup = '::endgroup::';
const LogLinePrefixesGroup = ['::group::', '##[group]'];
const LogLinePrefixesEndGroup = ['::endgroup::', '##[endgroup]'];
type LogLineCommand = {
name: 'group' | 'endgroup',
prefix: string,
}
function parseLineCommand(line: LogLine): LogLineCommand | null {
for (const prefix of LogLinePrefixesGroup) {
if (line.message.startsWith(prefix)) {
return {name: 'group', prefix};
}
}
for (const prefix of LogLinePrefixesEndGroup) {
if (line.message.startsWith(prefix)) {
return {name: 'endgroup', prefix};
}
}
return null;
}
const sfc = {
name: 'RepoActionView',
@ -129,13 +148,13 @@ const sfc = {
return el._stepLogsActiveContainer ?? el;
},
// begin a log group
beginLogGroup(stepIndex: number, startTime: number, line: LogLine) {
beginLogGroup(stepIndex: number, startTime: number, line: LogLine, cmd: LogLineCommand) {
const el = this.$refs.logs[stepIndex];
const elJobLogGroupSummary = createElementFromAttrs('summary', {class: 'job-log-group-summary'},
this.createLogLine(stepIndex, startTime, {
index: line.index,
timestamp: line.timestamp,
message: line.message.substring(LogLinePrefixGroup.length),
message: line.message.substring(cmd.prefix.length),
}),
);
const elJobLogList = createElementFromAttrs('div', {class: 'job-log-list'});
@ -147,13 +166,13 @@ const sfc = {
el._stepLogsActiveContainer = elJobLogList;
},
// end a log group
endLogGroup(stepIndex: number, startTime: number, line: LogLine) {
endLogGroup(stepIndex: number, startTime: number, line: LogLine, cmd: LogLineCommand) {
const el = this.$refs.logs[stepIndex];
el._stepLogsActiveContainer = null;
el.append(this.createLogLine(stepIndex, startTime, {
index: line.index,
timestamp: line.timestamp,
message: line.message.substring(LogLinePrefixEndGroup.length),
message: line.message.substring(cmd.prefix.length),
}));
},
@ -201,11 +220,12 @@ const sfc = {
appendLogs(stepIndex: number, startTime: number, logLines: LogLine[]) {
for (const line of logLines) {
const el = this.getLogsContainer(stepIndex);
if (line.message.startsWith(LogLinePrefixGroup)) {
this.beginLogGroup(stepIndex, startTime, line);
const cmd = parseLineCommand(line);
if (cmd?.name === 'group') {
this.beginLogGroup(stepIndex, startTime, line, cmd);
continue;
} else if (line.message.startsWith(LogLinePrefixEndGroup)) {
this.endLogGroup(stepIndex, startTime, line);
} else if (cmd?.name === 'endgroup') {
this.endLogGroup(stepIndex, startTime, line, cmd);
continue;
}
el.append(this.createLogLine(stepIndex, startTime, line));
@ -393,7 +413,7 @@ export function initRepositoryActionView() {
<button class="ui basic small compact button red" @click="cancelRun()" v-else-if="run.canCancel">
{{ locale.cancel }}
</button>
<button class="ui basic small compact button tw-mr-0 tw-whitespace-nowrap link-action" :data-url="`${run.link}/rerun`" v-else-if="run.canRerun">
<button class="ui basic small compact button link-action" :data-url="`${run.link}/rerun`" v-else-if="run.canRerun">
{{ locale.rerun_all }}
</button>
</div>
@ -539,6 +559,11 @@ export function initRepositoryActionView() {
overflow-wrap: anywhere;
}
.action-info-summary .ui.button {
margin: 0;
white-space: nowrap;
}
.action-commit-summary {
display: flex;
flex-wrap: wrap;

View File

@ -1,11 +1,30 @@
import tinycolor from 'tinycolor2';
import {basename, extname, isObject, isDarkTheme} from '../utils.ts';
import {onInputDebounce} from '../utils/dom.ts';
import type MonacoNamespace from 'monaco-editor';
const languagesByFilename = {};
const languagesByExt = {};
type Monaco = typeof MonacoNamespace;
type IStandaloneCodeEditor = MonacoNamespace.editor.IStandaloneCodeEditor;
type IEditorOptions = MonacoNamespace.editor.IEditorOptions;
type IGlobalEditorOptions = MonacoNamespace.editor.IGlobalEditorOptions;
type ITextModelUpdateOptions = MonacoNamespace.editor.ITextModelUpdateOptions;
type MonacoOpts = IEditorOptions & IGlobalEditorOptions & ITextModelUpdateOptions;
const baseOptions = {
type EditorConfig = {
indent_style?: 'tab' | 'space',
indent_size?: string | number, // backend emits this as string
tab_width?: string | number, // backend emits this as string
end_of_line?: 'lf' | 'cr' | 'crlf',
charset?: 'latin1' | 'utf-8' | 'utf-8-bom' | 'utf-16be' | 'utf-16le',
trim_trailing_whitespace?: boolean,
insert_final_newline?: boolean,
root?: boolean,
}
const languagesByFilename: Record<string, string> = {};
const languagesByExt: Record<string, string> = {};
const baseOptions: MonacoOpts = {
fontFamily: 'var(--fonts-monospace)',
fontSize: 14, // https://github.com/microsoft/monaco-editor/issues/2242
guides: {bracketPairs: false, indentation: false},
@ -15,21 +34,23 @@ const baseOptions = {
overviewRulerLanes: 0,
renderLineHighlight: 'all',
renderLineHighlightOnlyWhenFocus: true,
rulers: false,
rulers: [],
scrollbar: {horizontalScrollbarSize: 6, verticalScrollbarSize: 6},
scrollBeyondLastLine: false,
automaticLayout: true,
};
function getEditorconfig(input: HTMLInputElement) {
function getEditorconfig(input: HTMLInputElement): EditorConfig | null {
const json = input.getAttribute('data-editorconfig');
if (!json) return null;
try {
return JSON.parse(input.getAttribute('data-editorconfig'));
return JSON.parse(json);
} catch {
return null;
}
}
function initLanguages(monaco) {
function initLanguages(monaco: Monaco): void {
for (const {filenames, extensions, id} of monaco.languages.getLanguages()) {
for (const filename of filenames || []) {
languagesByFilename[filename] = id;
@ -40,35 +61,26 @@ function initLanguages(monaco) {
}
}
function getLanguage(filename) {
function getLanguage(filename: string): string {
return languagesByFilename[filename] || languagesByExt[extname(filename)] || 'plaintext';
}
function updateEditor(monaco, editor, filename, lineWrapExts) {
function updateEditor(monaco: Monaco, editor: IStandaloneCodeEditor, filename: string, lineWrapExts: string[]): void {
editor.updateOptions(getFileBasedOptions(filename, lineWrapExts));
const model = editor.getModel();
if (!model) return;
const language = model.getLanguageId();
const newLanguage = getLanguage(filename);
if (language !== newLanguage) monaco.editor.setModelLanguage(model, newLanguage);
}
// export editor for customization - https://github.com/go-gitea/gitea/issues/10409
function exportEditor(editor) {
function exportEditor(editor: IStandaloneCodeEditor): void {
if (!window.codeEditors) window.codeEditors = [];
if (!window.codeEditors.includes(editor)) window.codeEditors.push(editor);
}
export async function createMonaco(textarea: HTMLTextAreaElement, filename: string, editorOpts: Record<string, any>) {
const monaco = await import(/* webpackChunkName: "monaco" */'monaco-editor');
initLanguages(monaco);
let {language, ...other} = editorOpts;
if (!language) language = getLanguage(filename);
const container = document.createElement('div');
container.className = 'monaco-editor-container';
textarea.parentNode.append(container);
function updateTheme(monaco: Monaco): void {
// https://github.com/microsoft/monaco-editor/issues/2427
// also, monaco can only parse 6-digit hex colors, so we convert the colors to that format
const styles = window.getComputedStyle(document.documentElement);
@ -80,6 +92,7 @@ export async function createMonaco(textarea: HTMLTextAreaElement, filename: stri
rules: [
{
background: getColor('--color-code-bg'),
token: '',
},
],
colors: {
@ -101,6 +114,26 @@ export async function createMonaco(textarea: HTMLTextAreaElement, filename: stri
'focusBorder': '#0000', // prevent blue border
},
});
}
type CreateMonacoOpts = MonacoOpts & {language?: string};
export async function createMonaco(textarea: HTMLTextAreaElement, filename: string, opts: CreateMonacoOpts): Promise<{monaco: Monaco, editor: IStandaloneCodeEditor}> {
const monaco = await import(/* webpackChunkName: "monaco" */'monaco-editor');
initLanguages(monaco);
let {language, ...other} = opts;
if (!language) language = getLanguage(filename);
const container = document.createElement('div');
container.className = 'monaco-editor-container';
if (!textarea.parentNode) throw new Error('Parent node absent');
textarea.parentNode.append(container);
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
updateTheme(monaco);
});
updateTheme(monaco);
const editor = monaco.editor.create(container, {
value: textarea.value,
@ -114,8 +147,12 @@ export async function createMonaco(textarea: HTMLTextAreaElement, filename: stri
]);
const model = editor.getModel();
if (!model) throw new Error('Unable to get editor model');
model.onDidChangeContent(() => {
textarea.value = editor.getValue({preserveBOM: true});
textarea.value = editor.getValue({
preserveBOM: true,
lineEnding: '',
});
textarea.dispatchEvent(new Event('change')); // seems to be needed for jquery-are-you-sure
});
@ -127,13 +164,13 @@ export async function createMonaco(textarea: HTMLTextAreaElement, filename: stri
return {monaco, editor};
}
function getFileBasedOptions(filename: string, lineWrapExts: string[]) {
function getFileBasedOptions(filename: string, lineWrapExts: string[]): MonacoOpts {
return {
wordWrap: (lineWrapExts || []).includes(extname(filename)) ? 'on' : 'off',
};
}
function togglePreviewDisplay(previewable: boolean) {
function togglePreviewDisplay(previewable: boolean): void {
const previewTab = document.querySelector<HTMLElement>('a[data-tab="preview"]');
if (!previewTab) return;
@ -145,19 +182,19 @@ function togglePreviewDisplay(previewable: boolean) {
// then the "preview" tab becomes inactive (hidden), so the "write" tab should become active
if (previewTab.classList.contains('active')) {
const writeTab = document.querySelector<HTMLElement>('a[data-tab="write"]');
writeTab.click();
writeTab?.click();
}
}
}
export async function createCodeEditor(textarea: HTMLTextAreaElement, filenameInput: HTMLInputElement) {
export async function createCodeEditor(textarea: HTMLTextAreaElement, filenameInput: HTMLInputElement): Promise<IStandaloneCodeEditor> {
const filename = basename(filenameInput.value);
const previewableExts = new Set((textarea.getAttribute('data-previewable-extensions') || '').split(','));
const lineWrapExts = (textarea.getAttribute('data-line-wrap-extensions') || '').split(',');
const previewable = previewableExts.has(extname(filename));
const isPreviewable = previewableExts.has(extname(filename));
const editorConfig = getEditorconfig(filenameInput);
togglePreviewDisplay(previewable);
togglePreviewDisplay(isPreviewable);
const {monaco, editor} = await createMonaco(textarea, filename, {
...baseOptions,
@ -175,14 +212,22 @@ export async function createCodeEditor(textarea: HTMLTextAreaElement, filenameIn
return editor;
}
function getEditorConfigOptions(ec: Record<string, any>): Record<string, any> {
if (!isObject(ec)) return {};
function getEditorConfigOptions(ec: EditorConfig | null): MonacoOpts {
if (!ec || !isObject(ec)) return {};
const opts: Record<string, any> = {};
const opts: MonacoOpts = {};
opts.detectIndentation = !('indent_style' in ec) || !('indent_size' in ec);
if ('indent_size' in ec) opts.indentSize = Number(ec.indent_size);
if ('tab_width' in ec) opts.tabSize = Number(ec.tab_width) || opts.indentSize;
if ('max_line_length' in ec) opts.rulers = [Number(ec.max_line_length)];
if ('indent_size' in ec) {
opts.indentSize = Number(ec.indent_size);
}
if ('tab_width' in ec) {
opts.tabSize = Number(ec.tab_width) || Number(ec.indent_size);
}
if ('max_line_length' in ec) {
opts.rulers = [Number(ec.max_line_length)];
}
opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true;
opts.insertSpaces = ec.indent_style === 'space';
opts.useTabStops = ec.indent_style === 'tab';

View File

@ -1,17 +1,17 @@
import $ from 'jquery';
import {updateIssuesMeta} from './repo-common.ts';
import {toggleElem, hideElem, isElemHidden} from '../utils/dom.ts';
import {toggleElem, hideElem, isElemHidden, queryElems} from '../utils/dom.ts';
import {htmlEscape} from 'escape-goat';
import {confirmModal} from './comp/ConfirmModal.ts';
import {showErrorToast} from '../modules/toast.ts';
import {createSortable} from '../modules/sortable.ts';
import {DELETE, POST} from '../modules/fetch.ts';
import {parseDom} from '../utils.ts';
import {fomanticQuery} from '../modules/fomantic/base.ts';
function initRepoIssueListCheckboxes() {
const issueSelectAll = document.querySelector('.issue-checkbox-all');
const issueSelectAll = document.querySelector<HTMLInputElement>('.issue-checkbox-all');
if (!issueSelectAll) return; // logged out state
const issueCheckboxes = document.querySelectorAll('.issue-checkbox');
const issueCheckboxes = document.querySelectorAll<HTMLInputElement>('.issue-checkbox');
const syncIssueSelectionState = () => {
const checkedCheckboxes = Array.from(issueCheckboxes).filter((el) => el.checked);
@ -29,8 +29,8 @@ function initRepoIssueListCheckboxes() {
issueSelectAll.indeterminate = false;
}
// if any issue is selected, show the action panel, otherwise show the filter panel
toggleElem($('#issue-filters'), !anyChecked);
toggleElem($('#issue-actions'), anyChecked);
toggleElem('#issue-filters', !anyChecked);
toggleElem('#issue-actions', anyChecked);
// there are two panels but only one select-all checkbox, so move the checkbox to the visible panel
const panels = document.querySelectorAll('#issue-filters, #issue-actions');
const visiblePanel = Array.from(panels).find((el) => !isElemHidden(el));
@ -49,17 +49,18 @@ function initRepoIssueListCheckboxes() {
syncIssueSelectionState();
});
$('.issue-action').on('click', async function (e) {
queryElems(document, '.issue-action', (el) => el.addEventListener('click',
async (e: MouseEvent) => {
e.preventDefault();
const url = this.getAttribute('data-url');
let action = this.getAttribute('data-action');
let elementId = this.getAttribute('data-element-id');
let issueIDs = [];
const url = el.getAttribute('data-url');
let action = el.getAttribute('data-action');
let elementId = el.getAttribute('data-element-id');
const issueIDList: string[] = [];
for (const el of document.querySelectorAll('.issue-checkbox:checked')) {
issueIDs.push(el.getAttribute('data-issue-id'));
issueIDList.push(el.getAttribute('data-issue-id'));
}
issueIDs = issueIDs.join(',');
const issueIDs = issueIDList.join(',');
if (!issueIDs) return;
// for assignee
@ -75,7 +76,7 @@ function initRepoIssueListCheckboxes() {
// for delete
if (action === 'delete') {
const confirmText = e.target.getAttribute('data-action-delete-confirm');
const confirmText = el.getAttribute('data-action-delete-confirm');
if (!await confirmModal({content: confirmText, confirmButtonColor: 'red'})) {
return;
}
@ -87,18 +88,16 @@ function initRepoIssueListCheckboxes() {
} catch (err) {
showErrorToast(err.responseJSON?.error ?? err.message);
}
});
},
));
}
function initRepoIssueListAuthorDropdown() {
const $searchDropdown = $('.user-remote-search');
if (!$searchDropdown.length) return;
let searchUrl = $searchDropdown[0].getAttribute('data-search-url');
const actionJumpUrl = $searchDropdown[0].getAttribute('data-action-jump-url');
const selectedUserId = $searchDropdown[0].getAttribute('data-selected-user-id');
function initDropdownUserRemoteSearch(el: Element) {
let searchUrl = el.getAttribute('data-search-url');
const actionJumpUrl = el.getAttribute('data-action-jump-url');
const selectedUserId = el.getAttribute('data-selected-user-id');
if (!searchUrl.includes('?')) searchUrl += '?';
const $searchDropdown = fomanticQuery(el);
$searchDropdown.dropdown('setting', {
fullTextSearch: true,
selectOnKeydown: false,
@ -111,14 +110,14 @@ function initRepoIssueListAuthorDropdown() {
for (const item of resp.results) {
let html = `<img class="ui avatar tw-align-middle" src="${htmlEscape(item.avatar_link)}" aria-hidden="true" alt="" width="20" height="20"><span class="gt-ellipsis">${htmlEscape(item.username)}</span>`;
if (item.full_name) html += `<span class="search-fullname tw-ml-2">${htmlEscape(item.full_name)}</span>`;
processedResults.push({value: item.user_id, name: html});
processedResults.push({value: item.username, name: html});
}
resp.results = processedResults;
return resp;
},
},
action: (_text, value) => {
window.location.href = actionJumpUrl.replace('{user_id}', encodeURIComponent(value));
window.location.href = actionJumpUrl.replace('{username}', encodeURIComponent(value));
},
onShow: () => {
$searchDropdown.dropdown('filter', ' '); // trigger a search on first show
@ -160,7 +159,7 @@ function initRepoIssueListAuthorDropdown() {
function initPinRemoveButton() {
for (const button of document.querySelectorAll('.issue-card-unpin')) {
button.addEventListener('click', async (event) => {
const el = event.currentTarget;
const el = event.currentTarget as HTMLElement;
const id = Number(el.getAttribute('data-issue-id'));
// Send the unpin request
@ -205,10 +204,8 @@ async function initIssuePinSort() {
}
function initArchivedLabelFilter() {
const archivedLabelEl = document.querySelector('#archived-filter-checkbox');
if (!archivedLabelEl) {
return;
}
const archivedLabelEl = document.querySelector<HTMLInputElement>('#archived-filter-checkbox');
if (!archivedLabelEl) return;
const url = new URL(window.location.href);
const archivedLabels = document.querySelectorAll('[data-is-archived]');
@ -219,7 +216,7 @@ function initArchivedLabelFilter() {
}
const selectedLabels = (url.searchParams.get('labels') || '')
.split(',')
.map((id) => id < 0 ? `${~id + 1}` : id); // selectedLabels contains -ve ids, which are excluded so convert any -ve value id to +ve
.map((id) => parseInt(id) < 0 ? `${~id + 1}` : id); // selectedLabels contains -ve ids, which are excluded so convert any -ve value id to +ve
const archivedElToggle = () => {
for (const label of archivedLabels) {
@ -241,9 +238,9 @@ function initArchivedLabelFilter() {
}
export function initRepoIssueList() {
if (!document.querySelectorAll('.page-content.repository.issue-list, .page-content.repository.milestone-issue-list').length) return;
if (!document.querySelector('.page-content.repository.issue-list, .page-content.repository.milestone-issue-list')) return;
initRepoIssueListCheckboxes();
initRepoIssueListAuthorDropdown();
queryElems(document, '.ui.dropdown.user-remote-search', (el) => initDropdownUserRemoteSearch(el));
initIssuePinSort();
initArchivedLabelFilter();
}

View File

@ -8,6 +8,7 @@ import {parseIssuePageInfo, toAbsoluteUrl} from '../utils.ts';
import {GET, POST} from '../modules/fetch.ts';
import {showErrorToast} from '../modules/toast.ts';
import {initRepoIssueSidebar} from './repo-issue-sidebar.ts';
import {fomanticQuery} from '../modules/fomantic/base.ts';
const {appSubUrl} = window.config;
@ -31,8 +32,8 @@ export function initRepoIssueSidebarList() {
if (crossRepoSearch === 'true') {
issueSearchUrl = `${appSubUrl}/issues/search?q={query}&priority_repo_id=${issuePageInfo.repoId}&type=${issuePageInfo.issueDependencySearchType}`;
}
$('#new-dependency-drop-list')
.dropdown({
fomanticQuery('#new-dependency-drop-list').dropdown({
fullTextSearch: true,
apiSettings: {
url: issueSearchUrl,
onResponse(response) {
@ -54,11 +55,12 @@ export function initRepoIssueSidebarList() {
},
cache: false,
},
fullTextSearch: true,
});
}
$('.menu a.label-filter-item').each(function () {
export function initRepoIssueLabelFilter() {
// the "label-filter" is used in 2 templates: projects/view, issue/filter_list (issue list page including the milestone page)
$('.ui.dropdown.label-filter a.label-filter-item').each(function () {
$(this).on('click', function (e) {
if (e.altKey) {
e.preventDefault();
@ -66,11 +68,9 @@ export function initRepoIssueSidebarList() {
}
});
});
// FIXME: it is wrong place to init ".ui.dropdown.label-filter"
$('.menu .ui.dropdown.label-filter').on('keydown', (e) => {
$('.ui.dropdown.label-filter').on('keydown', (e) => {
if (e.altKey && e.key === 'Enter') {
const selectedItem = document.querySelector('.menu .ui.dropdown.label-filter .menu .item.selected');
const selectedItem = document.querySelector('.ui.dropdown.label-filter .menu .item.selected');
if (selectedItem) {
excludeLabel(selectedItem);
}

View File

@ -29,7 +29,7 @@ import {
initRepoIssueWipTitle,
initRepoPullRequestMergeInstruction,
initRepoPullRequestAllowMaintainerEdit,
initRepoPullRequestReview, initRepoIssueSidebarList,
initRepoPullRequestReview, initRepoIssueSidebarList, initRepoIssueLabelFilter,
} from './features/repo-issue.ts';
import {initRepoEllipsisButton, initCommitStatuses} from './features/repo-commit.ts';
import {initRepoTopicBar} from './features/repo-home.ts';
@ -181,6 +181,7 @@ onDomReady(() => {
initRepoGraphGit,
initRepoIssueContentHistory,
initRepoIssueList,
initRepoIssueLabelFilter,
initRepoIssueSidebarList,
initRepoIssueReferenceRepositorySearch,
initRepoIssueWipTitle,

View File

@ -0,0 +1,56 @@
import {createElementFromHTML} from '../../utils/dom.ts';
import {hideScopedEmptyDividers} from './dropdown.ts';
test('hideScopedEmptyDividers-simple', () => {
const container = createElementFromHTML(`<div>
<div class="divider"></div>
<div class="item">a</div>
<div class="divider"></div>
<div class="divider"></div>
<div class="divider"></div>
<div class="item">b</div>
<div class="divider"></div>
</div>`);
hideScopedEmptyDividers(container);
expect(container.innerHTML).toEqual(`
<div class="divider hidden transition"></div>
<div class="item">a</div>
<div class="divider hidden transition"></div>
<div class="divider hidden transition"></div>
<div class="divider"></div>
<div class="item">b</div>
<div class="divider hidden transition"></div>
`);
});
test('hideScopedEmptyDividers-hidden1', () => {
const container = createElementFromHTML(`<div>
<div class="item">a</div>
<div class="divider" data-scope="b"></div>
<div class="item tw-hidden" data-scope="b">b</div>
</div>`);
hideScopedEmptyDividers(container);
expect(container.innerHTML).toEqual(`
<div class="item">a</div>
<div class="divider hidden transition" data-scope="b"></div>
<div class="item tw-hidden" data-scope="b">b</div>
`);
});
test('hideScopedEmptyDividers-hidden2', () => {
const container = createElementFromHTML(`<div>
<div class="item" data-scope="">a</div>
<div class="divider" data-scope="b"></div>
<div class="item tw-hidden" data-scope="b">b</div>
<div class="divider" data-scope=""></div>
<div class="item" data-scope="">c</div>
</div>`);
hideScopedEmptyDividers(container);
expect(container.innerHTML).toEqual(`
<div class="item" data-scope="">a</div>
<div class="divider hidden transition" data-scope="b"></div>
<div class="item tw-hidden" data-scope="b">b</div>
<div class="divider hidden transition" data-scope=""></div>
<div class="item" data-scope="">c</div>
`);
});

View File

@ -59,6 +59,12 @@ function updateSelectionLabel(label: HTMLElement) {
}
}
function processMenuItems($dropdown, dropdownCall) {
const hideEmptyDividers = dropdownCall('setting', 'hideDividers') === 'empty';
const itemsMenu = $dropdown[0].querySelector('.scrolling.menu') || $dropdown[0].querySelector('.menu');
if (hideEmptyDividers) hideScopedEmptyDividers(itemsMenu);
}
// delegate the dropdown's template functions and callback functions to add aria attributes.
function delegateOne($dropdown: any) {
const dropdownCall = fomanticDropdownFn.bind($dropdown);
@ -72,6 +78,18 @@ function delegateOne($dropdown: any) {
// * If the "dropdown icon" is clicked again when the menu is visible, Fomantic calls "blurSearch", so hide the menu
dropdownCall('internal', 'blurSearch', function () { oldBlurSearch.call(this); dropdownCall('hide') });
const oldFilterItems = dropdownCall('internal', 'filterItems');
dropdownCall('internal', 'filterItems', function (...args: any[]) {
oldFilterItems.call(this, ...args);
processMenuItems($dropdown, dropdownCall);
});
const oldShow = dropdownCall('internal', 'show');
dropdownCall('internal', 'show', function (...args: any[]) {
oldShow.call(this, ...args);
processMenuItems($dropdown, dropdownCall);
});
// the "template" functions are used for dynamic creation (eg: AJAX)
const dropdownTemplates = {...dropdownCall('setting', 'templates'), t: performance.now()};
const dropdownTemplatesMenuOld = dropdownTemplates.menu;
@ -271,3 +289,65 @@ function attachDomEvents(dropdown: HTMLElement, focusable: HTMLElement, menu: HT
ignoreClickPreEvents = ignoreClickPreVisible = 0;
}, true);
}
// Although Fomantic Dropdown supports "hideDividers", it doesn't really work with our "scoped dividers"
// At the moment, "label dropdown items" use scopes, a sample case is:
// * a-label
// * divider
// * scope/1
// * scope/2
// * divider
// * z-label
// when the "scope/*" are filtered out, we'd like to see "a-label" and "z-label" without the divider.
export function hideScopedEmptyDividers(container: Element) {
const visibleItems: Element[] = [];
const curScopeVisibleItems: Element[] = [];
let curScope: string = '', lastVisibleScope: string = '';
const isScopedDivider = (item: Element) => item.matches('.divider') && item.hasAttribute('data-scope');
const hideDivider = (item: Element) => item.classList.add('hidden', 'transition'); // dropdown has its own classes to hide items
const handleScopeSwitch = (itemScope: string) => {
if (curScopeVisibleItems.length === 1 && isScopedDivider(curScopeVisibleItems[0])) {
hideDivider(curScopeVisibleItems[0]);
} else if (curScopeVisibleItems.length) {
if (isScopedDivider(curScopeVisibleItems[0]) && lastVisibleScope === curScope) {
hideDivider(curScopeVisibleItems[0]);
curScopeVisibleItems.shift();
}
visibleItems.push(...curScopeVisibleItems);
lastVisibleScope = curScope;
}
curScope = itemScope;
curScopeVisibleItems.length = 0;
};
// hide the scope dividers if the scope items are empty
for (const item of container.children) {
const itemScope = item.getAttribute('data-scope') || '';
if (itemScope !== curScope) {
handleScopeSwitch(itemScope);
}
if (!item.classList.contains('filtered') && !item.classList.contains('tw-hidden')) {
curScopeVisibleItems.push(item as HTMLElement);
}
}
handleScopeSwitch('');
// hide all leading and trailing dividers
while (visibleItems.length) {
if (!visibleItems[0].matches('.divider')) break;
hideDivider(visibleItems[0]);
visibleItems.shift();
}
while (visibleItems.length) {
if (!visibleItems[visibleItems.length - 1].matches('.divider')) break;
hideDivider(visibleItems[visibleItems.length - 1]);
visibleItems.pop();
}
// hide all duplicate dividers, hide current divider if next sibling is still divider
// no need to update "visibleItems" array since this is the last loop
for (const item of visibleItems) {
if (!item.matches('.divider')) continue;
if (item.nextElementSibling?.matches('.divider')) hideDivider(item);
}
}

View File

@ -12,7 +12,7 @@ window.customElements.define('overflow-menu', class extends HTMLElement {
mutationObserver: MutationObserver;
lastWidth: number;
updateItems = throttle(100, () => { // eslint-disable-line unicorn/consistent-function-scoping -- https://github.com/sindresorhus/eslint-plugin-unicorn/issues/2088
updateItems = throttle(100, () => {
if (!this.tippyContent) {
const div = document.createElement('div');
div.classList.add('tippy-target');