mirror of
https://github.com/go-gitea/gitea
synced 2024-11-17 15:31:06 +01:00
Merge branch 'main' into lunny/rename_board_column
This commit is contained in:
commit
98c33445f9
15 changed files with 112 additions and 168 deletions
|
@ -2315,6 +2315,8 @@ LEVEL = Info
|
|||
;SHOW_FOOTER_VERSION = true
|
||||
;; Show template execution time in the footer
|
||||
;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
|
||||
;; Show the "powered by" text in the footer
|
||||
;SHOW_FOOTER_POWERED_BY = true
|
||||
;; Generate sitemap. Defaults to `true`.
|
||||
;ENABLE_SITEMAP = true
|
||||
;; Enable/Disable RSS/Atom feed
|
||||
|
|
|
@ -1429,5 +1429,6 @@ Like `uses: https://gitea.com/actions/checkout@v4` or `uses: http://your-git-ser
|
|||
|
||||
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
|
||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
||||
- `SHOW_FOOTER_POWERED_BY`: **true**: Show the "powered by" text in the footer.
|
||||
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
|
||||
- `ENABLE_FEED`: **true**: Enable/Disable RSS/Atom feed.
|
||||
|
|
|
@ -1353,5 +1353,6 @@ PROXY_HOSTS = *.github.com
|
|||
|
||||
- `SHOW_FOOTER_VERSION`: **true**: 在页面底部显示Gitea的版本。
|
||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: 在页脚显示模板执行的时间。
|
||||
- `SHOW_FOOTER_POWERED_BY`: **true**: 在页脚显示“由...提供动力”的文本。
|
||||
- `ENABLE_SITEMAP`: **true**: 生成sitemap.
|
||||
- `ENABLE_FEED`: **true**: 是否启用RSS/Atom
|
||||
|
|
|
@ -304,7 +304,8 @@ services:
|
|||
- GITEA__mailer__ENABLED=true
|
||||
- GITEA__mailer__FROM=${GITEA__mailer__FROM:?GITEA__mailer__FROM not set}
|
||||
- GITEA__mailer__PROTOCOL=smtps
|
||||
- GITEA__mailer__HOST=${GITEA__mailer__HOST:?GITEA__mailer__HOST not set}
|
||||
- GITEA__mailer__SMTP_ADDR=${GITEA__mailer__SMTP_ADDR:?GITEA__mailer__SMTP_ADDR not set}
|
||||
- GITEA__mailer__SMTP_PORT=${GITEA__mailer__SMTP_PORT:?GITEA__mailer__SMTP_PORT not set}
|
||||
- GITEA__mailer__USER=${GITEA__mailer__USER:-apikey}
|
||||
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
|
||||
```
|
||||
|
|
|
@ -44,7 +44,7 @@ func (c *FilesystemClient) Download(ctx context.Context, objects []Pointer, call
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
if err := callback(p, f, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ func (c *FilesystemClient) Upload(ctx context.Context, objects []Pointer, callba
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
_, err = io.Copy(f, content)
|
||||
|
||||
return err
|
||||
|
|
|
@ -8,6 +8,7 @@ import "code.gitea.io/gitea/modules/log"
|
|||
type OtherConfig struct {
|
||||
ShowFooterVersion bool
|
||||
ShowFooterTemplateLoadTime bool
|
||||
ShowFooterPoweredBy bool
|
||||
EnableFeed bool
|
||||
EnableSitemap bool
|
||||
}
|
||||
|
@ -15,6 +16,7 @@ type OtherConfig struct {
|
|||
var Other = OtherConfig{
|
||||
ShowFooterVersion: true,
|
||||
ShowFooterTemplateLoadTime: true,
|
||||
ShowFooterPoweredBy: true,
|
||||
EnableSitemap: true,
|
||||
EnableFeed: true,
|
||||
}
|
||||
|
|
|
@ -106,6 +106,9 @@ func NewFuncMap() template.FuncMap {
|
|||
"ShowFooterTemplateLoadTime": func() bool {
|
||||
return setting.Other.ShowFooterTemplateLoadTime
|
||||
},
|
||||
"ShowFooterPoweredBy": func() bool {
|
||||
return setting.Other.ShowFooterPoweredBy
|
||||
},
|
||||
"AllowedReactions": func() []string {
|
||||
return setting.UI.Reactions
|
||||
},
|
||||
|
|
|
@ -1233,6 +1233,8 @@ file_view_rendered=Ver resultado processado
|
|||
file_view_raw=Ver em bruto
|
||||
file_permalink=Ligação permanente
|
||||
file_too_large=O ficheiro é demasiado grande para ser apresentado.
|
||||
code_preview_line_from_to=Linhas %[1]d até %[2]d em %[3]s
|
||||
code_preview_line_in=Linha %[1]d em %[2]s
|
||||
invisible_runes_header=`Este ficheiro contém caracteres Unicode invisíveis`
|
||||
invisible_runes_description=`Este ficheiro contém caracteres Unicode indistinguíveis para humanos mas que podem ser processados de forma diferente por um computador. Se acha que é intencional, pode ignorar este aviso com segurança. Use o botão Revelar para os mostrar.`
|
||||
ambiguous_runes_header=`Este ficheiro contém caracteres Unicode ambíguos`
|
||||
|
|
12
package-lock.json
generated
12
package-lock.json
generated
|
@ -13,7 +13,6 @@
|
|||
"@github/relative-time-element": "4.4.0",
|
||||
"@github/text-expander-element": "2.6.1",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||
"@melloware/coloris": "0.23.0",
|
||||
"@primer/octicons": "19.9.0",
|
||||
"add-asset-webpack-plugin": "2.0.1",
|
||||
"ansi_up": "6.0.2",
|
||||
|
@ -54,6 +53,7 @@
|
|||
"toastify-js": "1.12.0",
|
||||
"tributejs": "5.1.3",
|
||||
"uint8-to-base64": "0.2.0",
|
||||
"vanilla-colorful": "0.7.2",
|
||||
"vue": "3.4.21",
|
||||
"vue-bar-graph": "2.0.0",
|
||||
"vue-chartjs": "5.3.0",
|
||||
|
@ -1290,11 +1290,6 @@
|
|||
"@mcaptcha/core-glue": "^0.1.0-alpha-5"
|
||||
}
|
||||
},
|
||||
"node_modules/@melloware/coloris": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@melloware/coloris/-/coloris-0.23.0.tgz",
|
||||
"integrity": "sha512-VGIjI9+IQwg6BHjIE10yl0K2ARYz5bsjn6BgFEs1y1ErPAQymgdoxwVcSVL4Ai5t9OVs8xaCB7JKHqFu2N96Ow=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
@ -11853,6 +11848,11 @@
|
|||
"builtins": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/vanilla-colorful": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
|
||||
"integrity": "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg=="
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.2.6",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.6.tgz",
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
"@github/relative-time-element": "4.4.0",
|
||||
"@github/text-expander-element": "2.6.1",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||
"@melloware/coloris": "0.23.0",
|
||||
"@primer/octicons": "19.9.0",
|
||||
"add-asset-webpack-plugin": "2.0.1",
|
||||
"ansi_up": "6.0.2",
|
||||
|
@ -53,6 +52,7 @@
|
|||
"toastify-js": "1.12.0",
|
||||
"tributejs": "5.1.3",
|
||||
"uint8-to-base64": "0.2.0",
|
||||
"vanilla-colorful": "0.7.2",
|
||||
"vue": "3.4.21",
|
||||
"vue-bar-graph": "2.0.0",
|
||||
"vue-chartjs": "5.3.0",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<footer class="page-footer" role="group" aria-label="{{ctx.Locale.Tr "aria.footer"}}">
|
||||
<div class="left-links" role="contentinfo" aria-label="{{ctx.Locale.Tr "aria.footer.software"}}">
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://about.gitea.com">{{ctx.Locale.Tr "powered_by" "Gitea"}}</a>
|
||||
{{if ShowFooterPoweredBy}}
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://about.gitea.com">{{ctx.Locale.Tr "powered_by" "Gitea"}}</a>
|
||||
{{end}}
|
||||
{{if (or .ShowFooterVersion .PageIsAdmin)}}
|
||||
{{ctx.Locale.Tr "version"}}:
|
||||
{{if .IsAdmin}}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/* This is a stripped-down version of coloris's CSS tailored to our needs. It does only include
|
||||
opaqua colors, and if more features like opacity are needed, the CSS needs to be extended
|
||||
based on upstream: https://github.com/mdbassit/Coloris/blob/main/src/coloris.css. */
|
||||
|
||||
.js-color-picker-input {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.js-color-picker-input input {
|
||||
|
@ -13,152 +9,39 @@
|
|||
padding-left: 32px !important;
|
||||
}
|
||||
|
||||
.clr-picker {
|
||||
display: none;
|
||||
flex-wrap: wrap;
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
z-index: 1002; /* above .ui.modal which has 1001 */
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--color-menu);
|
||||
justify-content: flex-end;
|
||||
direction: ltr;
|
||||
box-shadow: 0 5px 20px var(--color-shadow);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.clr-picker.clr-open {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.clr-gradient {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-radius: 3px 3px 0 0;
|
||||
background: linear-gradient(rgba(0,0,0,0), #000), linear-gradient(90deg, #fff, currentcolor); /* stylelint-disable-line scale-unlimited/declaration-strict-value */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-marker {
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: -6px 0 0 -6px;
|
||||
border: 1px solid var(--color-white);
|
||||
border-radius: 50%;
|
||||
background-color: currentcolor;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-webkit-slider-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-moz-range-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.clr-hue {
|
||||
background: linear-gradient(to right, #f00 0%, #ff0 16.66%, #0f0 33.33%, #0ff 50%, #00f 66.66%, #f0f 83.33%, #f00 100%); /* stylelint-disable-line scale-unlimited/declaration-strict-value */
|
||||
position: relative;
|
||||
width: calc(100% - 40px);
|
||||
height: 10px;
|
||||
margin: 10px 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.clr-hue input[type="range"] {
|
||||
position: absolute;
|
||||
width: calc(100% + 32px);
|
||||
margin: 0;
|
||||
background-color: transparent;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.clr-hue div {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: 2px solid var(--color-white);
|
||||
border-radius: 50%;
|
||||
background-color: currentcolor;
|
||||
box-shadow: 0 0 1px var(--color-shadow);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.clr-field {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.clr-field button {
|
||||
.js-color-picker-input .preview-square {
|
||||
position: absolute;
|
||||
aspect-ratio: 1;
|
||||
height: 16px;
|
||||
left: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
pointer-events: none;
|
||||
border-radius: 2px;
|
||||
background: repeating-linear-gradient(45deg, #aaa 25%, transparent 25%, transparent 75%, #aaa 75%, #aaa), repeating-linear-gradient(45deg, #aaa 25%, #fff 25%, #fff 75%, #aaa 75%, #aaa); /* stylelint-disable-line scale-unlimited/declaration-strict-value */
|
||||
background-position: 0 0, 4px 4px;
|
||||
background-size: 8px 8px;
|
||||
}
|
||||
|
||||
.clr-field button::after {
|
||||
.js-color-picker-input .preview-square::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: inherit;
|
||||
background-color: currentcolor;
|
||||
}
|
||||
|
||||
.clr-marker:focus {
|
||||
outline: none;
|
||||
hex-color-picker {
|
||||
width: 180px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.clr-keyboard-nav .clr-marker:focus,
|
||||
.clr-keyboard-nav .clr-hue input:focus + div,
|
||||
.clr-keyboard-nav .clr-alpha input:focus + div {
|
||||
outline: none;
|
||||
box-shadow: 0 0 2px 2px var(--color-white);
|
||||
hex-color-picker::part(hue-pointer),
|
||||
hex-color-picker::part(saturation-pointer) {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.clr-picker .clr-preview,
|
||||
.clr-picker .clr-clear,
|
||||
.clr-picker .clr-swatches,
|
||||
.clr-picker .clr-format,
|
||||
.clr-picker .clr-alpha,
|
||||
.clr-picker .clr-color {
|
||||
display: none;
|
||||
hex-color-picker::part(hue) {
|
||||
flex-basis: 16px;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,17 @@
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
/* bare theme, no styling at all, except box-shadow */
|
||||
.tippy-box[data-theme="bare"] {
|
||||
border: none;
|
||||
box-shadow: 0 6px 18px var(--color-shadow);
|
||||
}
|
||||
|
||||
.tippy-box[data-theme="bare"] .tippy-content {
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* tooltip theme for text tooltips */
|
||||
|
||||
.tippy-box[data-theme="tooltip"] {
|
||||
|
|
|
@ -1,31 +1,66 @@
|
|||
export async function initColorPickers(selector = '.js-color-picker-input input', opts = {}) {
|
||||
const inputEls = document.querySelectorAll(selector);
|
||||
if (!inputEls.length) return;
|
||||
import {createTippy} from '../modules/tippy.js';
|
||||
|
||||
const [{coloris, init}] = await Promise.all([
|
||||
import(/* webpackChunkName: "colorpicker" */'@melloware/coloris'),
|
||||
export async function initColorPickers() {
|
||||
const els = document.getElementsByClassName('js-color-picker-input');
|
||||
if (!els.length) return;
|
||||
|
||||
await Promise.all([
|
||||
import(/* webpackChunkName: "colorpicker" */'vanilla-colorful/hex-color-picker.js'),
|
||||
import(/* webpackChunkName: "colorpicker" */'../../css/features/colorpicker.css'),
|
||||
]);
|
||||
|
||||
init();
|
||||
coloris({
|
||||
el: selector,
|
||||
alpha: false,
|
||||
focusInput: true,
|
||||
selectInput: false,
|
||||
...opts,
|
||||
});
|
||||
|
||||
for (const inputEl of inputEls) {
|
||||
const parent = inputEl.closest('.js-color-picker-input');
|
||||
// prevent tabbing on the color preview `button` inside the input
|
||||
parent.querySelector('button').tabIndex = -1;
|
||||
// init precolors
|
||||
for (const el of parent.querySelectorAll('.precolors .color')) {
|
||||
el.addEventListener('click', (e) => {
|
||||
inputEl.value = e.target.getAttribute('data-color-hex');
|
||||
inputEl.dispatchEvent(new Event('input', {bubbles: true}));
|
||||
});
|
||||
}
|
||||
for (const el of els) {
|
||||
initPicker(el);
|
||||
}
|
||||
}
|
||||
|
||||
function updateSquare(el, newValue) {
|
||||
el.style.color = /#[0-9a-f]{6}/i.test(newValue) ? newValue : 'transparent';
|
||||
}
|
||||
|
||||
function updatePicker(el, newValue) {
|
||||
el.setAttribute('color', newValue);
|
||||
}
|
||||
|
||||
function initPicker(el) {
|
||||
const input = el.querySelector('input');
|
||||
|
||||
const square = document.createElement('div');
|
||||
square.classList.add('preview-square');
|
||||
updateSquare(square, input.value);
|
||||
el.append(square);
|
||||
|
||||
const picker = document.createElement('hex-color-picker');
|
||||
picker.addEventListener('color-changed', (e) => {
|
||||
input.value = e.detail.value;
|
||||
input.focus();
|
||||
updateSquare(square, e.detail.value);
|
||||
});
|
||||
|
||||
input.addEventListener('input', (e) => {
|
||||
updateSquare(square, e.target.value);
|
||||
updatePicker(picker, e.target.value);
|
||||
});
|
||||
|
||||
createTippy(input, {
|
||||
trigger: 'focus click',
|
||||
theme: 'bare',
|
||||
hideOnClick: true,
|
||||
content: picker,
|
||||
placement: 'bottom-start',
|
||||
interactive: true,
|
||||
onShow() {
|
||||
updatePicker(picker, input.value);
|
||||
},
|
||||
});
|
||||
|
||||
// init precolors
|
||||
for (const colorEl of el.querySelectorAll('.precolors .color')) {
|
||||
colorEl.addEventListener('click', (e) => {
|
||||
const newValue = e.target.getAttribute('data-color-hex');
|
||||
input.value = newValue;
|
||||
input.dispatchEvent(new Event('input', {bubbles: true}));
|
||||
updateSquare(square, newValue);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,12 @@ import {isDocumentFragmentOrElementNode} from '../utils/dom.js';
|
|||
import {formatDatetime} from '../utils/time.js';
|
||||
|
||||
const visibleInstances = new Set();
|
||||
const arrowSvg = `<svg width="16" height="7"><path d="m0 7 8-7 8 7Z" class="tippy-svg-arrow-outer"/><path d="m0 8 8-7 8 7Z" class="tippy-svg-arrow-inner"/></svg>`;
|
||||
|
||||
export function createTippy(target, opts = {}) {
|
||||
// the callback functions should be destructured from opts,
|
||||
// because we should use our own wrapper functions to handle them, do not let the user override them
|
||||
const {onHide, onShow, onDestroy, role, theme, ...other} = opts;
|
||||
const {onHide, onShow, onDestroy, role, theme, arrow, ...other} = opts;
|
||||
|
||||
const instance = tippy(target, {
|
||||
appendTo: document.body,
|
||||
|
@ -35,9 +36,9 @@ export function createTippy(target, opts = {}) {
|
|||
visibleInstances.add(instance);
|
||||
return onShow?.(instance);
|
||||
},
|
||||
arrow: `<svg width="16" height="7"><path d="m0 7 8-7 8 7Z" class="tippy-svg-arrow-outer"/><path d="m0 8 8-7 8 7Z" class="tippy-svg-arrow-inner"/></svg>`,
|
||||
arrow: arrow || (theme === 'bare' ? false : arrowSvg),
|
||||
role: role || 'menu', // HTML role attribute
|
||||
theme: theme || role || 'menu', // CSS theme, either "tooltip", "menu" or "box-with-header"
|
||||
theme: theme || role || 'menu', // CSS theme, either "tooltip", "menu", "box-with-header" or "bare"
|
||||
plugins: [followCursor],
|
||||
...other,
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue