Skip to content

Commit 960b1b4

Browse files
committed
fix ui
1 parent 9f37cbf commit 960b1b4

File tree

9 files changed

+127
-98
lines changed

9 files changed

+127
-98
lines changed
Lines changed: 87 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,97 @@
11
{{template "org/settings/layout_head" (dict "ctxData" . "pageClass" "organization settings options")}}
2-
<div class="org-setting-content">
3-
<h4 class="ui top attached header">
4-
{{ctx.Locale.Tr "org.settings.options"}}
5-
</h4>
6-
<div class="ui attached segment">
7-
<form class="ui form" action="{{.Link}}" method="post">
8-
{{.CsrfTokenHtml}}
9-
<div class="field {{if .Err_FullName}}error{{end}}">
10-
<label for="full_name">{{ctx.Locale.Tr "org.org_full_name_holder"}}</label>
11-
<input id="full_name" name="full_name" value="{{.Org.FullName}}" maxlength="100">
12-
</div>
13-
<div class="field {{if .Err_Email}}error{{end}}">
14-
<label for="email">{{ctx.Locale.Tr "org.settings.email"}}</label>
15-
<input id="email" name="email" type="email" value="{{.Org.Email}}" maxlength="255">
16-
</div>
17-
<div class="field {{if .Err_Description}}error{{end}}">
18-
{{/* it is rendered as markdown, but the length is limited, so at the moment we do not use the markdown editor here */}}
19-
<label for="description">{{ctx.Locale.Tr "org.org_desc"}}</label>
20-
<textarea id="description" name="description" rows="2" maxlength="255">{{.Org.Description}}</textarea>
21-
</div>
22-
<div class="field {{if .Err_Website}}error{{end}}">
23-
<label for="website">{{ctx.Locale.Tr "org.settings.website"}}</label>
24-
<input id="website" name="website" type="url" value="{{.Org.Website}}" maxlength="255">
25-
</div>
26-
<div class="field">
27-
<label for="location">{{ctx.Locale.Tr "org.settings.location"}}</label>
28-
<input id="location" name="location" value="{{.Org.Location}}" maxlength="50">
29-
</div>
302

31-
<div class="divider"></div>
32-
<div class="field" id="visibility_box">
33-
<label for="visibility">{{ctx.Locale.Tr "org.settings.visibility"}}</label>
34-
<div class="field">
35-
<div class="ui radio checkbox">
36-
<input class="enable-system-radio" name="visibility" type="radio" value="0" {{if eq .CurrentVisibility 0}}checked{{end}}>
37-
<label>{{ctx.Locale.Tr "org.settings.visibility.public"}}</label>
38-
</div>
39-
</div>
40-
<div class="field">
41-
<div class="ui radio checkbox">
42-
<input class="enable-system-radio" name="visibility" type="radio" value="1" {{if eq .CurrentVisibility 1}}checked{{end}}>
43-
<label>{{ctx.Locale.Tr "org.settings.visibility.limited"}}</label>
44-
</div>
45-
</div>
46-
<div class="field">
47-
<div class="ui radio checkbox">
48-
<input class="enable-system-radio" name="visibility" type="radio" value="2" {{if eq .CurrentVisibility 2}}checked{{end}}>
49-
<label>{{ctx.Locale.Tr "org.settings.visibility.private"}}</label>
50-
</div>
51-
</div>
52-
</div>
3+
<div class="ui segments org-setting-content">
4+
<h4 class="ui top attached header">
5+
{{ctx.Locale.Tr "org.settings.options"}}
6+
</h4>
7+
<div class="ui attached segment">
8+
<form class="ui form" action="{{.Link}}" method="post">
9+
{{.CsrfTokenHtml}}
10+
<div class="field {{if .Err_FullName}}error{{end}}">
11+
<label for="full_name">{{ctx.Locale.Tr "org.org_full_name_holder"}}</label>
12+
<input id="full_name" name="full_name" value="{{.Org.FullName}}" maxlength="100">
13+
</div>
14+
<div class="field {{if .Err_Email}}error{{end}}">
15+
<label for="email">{{ctx.Locale.Tr "org.settings.email"}}</label>
16+
<input id="email" name="email" type="email" value="{{.Org.Email}}" maxlength="255">
17+
</div>
18+
<div class="field {{if .Err_Description}}error{{end}}">
19+
{{/* it is rendered as markdown, but the length is limited, so at the moment we do not use the markdown editor here */}}
20+
<label for="description">{{ctx.Locale.Tr "org.org_desc"}}</label>
21+
<textarea id="description" name="description" rows="2" maxlength="255">{{.Org.Description}}</textarea>
22+
</div>
23+
<div class="field {{if .Err_Website}}error{{end}}">
24+
<label for="website">{{ctx.Locale.Tr "org.settings.website"}}</label>
25+
<input id="website" name="website" type="url" value="{{.Org.Website}}" maxlength="255">
26+
</div>
27+
<div class="field">
28+
<label for="location">{{ctx.Locale.Tr "org.settings.location"}}</label>
29+
<input id="location" name="location" value="{{.Org.Location}}" maxlength="50">
30+
</div>
31+
32+
<div class="divider"></div>
33+
<div class="field" id="visibility_box">
34+
<label for="visibility">{{ctx.Locale.Tr "org.settings.visibility"}}</label>
35+
<div class="field">
36+
<div class="ui radio checkbox">
37+
<input class="enable-system-radio" name="visibility" type="radio" value="0" {{if eq .CurrentVisibility 0}}checked{{end}}>
38+
<label>{{ctx.Locale.Tr "org.settings.visibility.public"}}</label>
39+
</div>
40+
</div>
41+
<div class="field">
42+
<div class="ui radio checkbox">
43+
<input class="enable-system-radio" name="visibility" type="radio" value="1" {{if eq .CurrentVisibility 1}}checked{{end}}>
44+
<label>{{ctx.Locale.Tr "org.settings.visibility.limited"}}</label>
45+
</div>
46+
</div>
47+
<div class="field">
48+
<div class="ui radio checkbox">
49+
<input class="enable-system-radio" name="visibility" type="radio" value="2" {{if eq .CurrentVisibility 2}}checked{{end}}>
50+
<label>{{ctx.Locale.Tr "org.settings.visibility.private"}}</label>
51+
</div>
52+
</div>
53+
</div>
5354

54-
<div class="field" id="permission_box">
55-
<label>{{ctx.Locale.Tr "org.settings.permission"}}</label>
56-
<div class="field">
57-
<div class="ui checkbox">
58-
<input type="checkbox" name="repo_admin_change_team_access" {{if .RepoAdminChangeTeamAccess}}checked{{end}}>
59-
<label>{{ctx.Locale.Tr "org.settings.repoadminchangeteam"}}</label>
60-
</div>
61-
</div>
62-
</div>
55+
<div class="field" id="permission_box">
56+
<label>{{ctx.Locale.Tr "org.settings.permission"}}</label>
57+
<div class="field">
58+
<div class="ui checkbox">
59+
<input type="checkbox" name="repo_admin_change_team_access" {{if .RepoAdminChangeTeamAccess}}checked{{end}}>
60+
<label>{{ctx.Locale.Tr "org.settings.repoadminchangeteam"}}</label>
61+
</div>
62+
</div>
63+
</div>
6364

64-
{{if .SignedUser.IsAdmin}}
65-
<div class="divider"></div>
65+
{{if .SignedUser.IsAdmin}}
66+
<div class="divider"></div>
6667

67-
<div class="inline field {{if .Err_MaxRepoCreation}}error{{end}}">
68-
<label for="max_repo_creation">{{ctx.Locale.Tr "admin.users.max_repo_creation"}}</label>
69-
<input id="max_repo_creation" name="max_repo_creation" type="number" min="-1" value="{{.Org.MaxRepoCreation}}">
70-
<p class="help">{{ctx.Locale.Tr "admin.users.max_repo_creation_desc"}}</p>
71-
</div>
72-
{{end}}
68+
<div class="inline field {{if .Err_MaxRepoCreation}}error{{end}}">
69+
<label for="max_repo_creation">{{ctx.Locale.Tr "admin.users.max_repo_creation"}}</label>
70+
<input id="max_repo_creation" name="max_repo_creation" type="number" min="-1" value="{{.Org.MaxRepoCreation}}">
71+
<p class="help">{{ctx.Locale.Tr "admin.users.max_repo_creation_desc"}}</p>
72+
</div>
73+
{{end}}
7374

74-
<div class="field">
75-
<button class="ui primary button">{{ctx.Locale.Tr "org.settings.update_settings"}}</button>
76-
</div>
77-
</form>
75+
<div class="field">
76+
<button class="ui primary button">{{ctx.Locale.Tr "org.settings.update_settings"}}</button>
77+
</div>
78+
</form>
7879

79-
<div class="divider"></div>
80+
<div class="divider"></div>
8081

81-
<form class="ui form" action="{{.Link}}/avatar" method="post" enctype="multipart/form-data">
82-
{{.CsrfTokenHtml}}
83-
<div class="inline field">
84-
{{template "shared/avatar_upload_crop" dict "LabelText" (ctx.Locale.Tr "settings.choose_new_avatar")}}
85-
</div>
86-
<div class="field">
87-
<button class="ui primary button">{{ctx.Locale.Tr "settings.update_avatar"}}</button>
88-
<button class="ui red button link-action" data-url="{{.Link}}/avatar/delete">{{ctx.Locale.Tr "settings.delete_current_avatar"}}</button>
89-
</div>
90-
</form>
91-
</div>
82+
<form class="ui form" action="{{.Link}}/avatar" method="post" enctype="multipart/form-data">
83+
{{.CsrfTokenHtml}}
84+
<div class="inline field">
85+
{{template "shared/avatar_upload_crop" dict "LabelText" (ctx.Locale.Tr "settings.choose_new_avatar")}}
86+
</div>
87+
<div class="field">
88+
<button class="ui primary button">{{ctx.Locale.Tr "settings.update_avatar"}}</button>
89+
<button class="ui red button link-action" data-url="{{.Link}}/avatar/delete">{{ctx.Locale.Tr "settings.delete_current_avatar"}}</button>
9290
</div>
93-
{{template "org/settings/options_dangerzone" .}}
91+
</form>
92+
</div>
93+
</div>
94+
95+
{{template "org/settings/options_dangerzone" .}}
96+
9497
{{template "org/settings/layout_footer" .}}

web_src/css/base.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
--page-spacing: 16px; /* space between page elements */
3131
--page-margin-x: 32px; /* minimum space on left and right side of page */
3232
--page-space-bottom: 64px; /* space between last page element and footer */
33+
34+
/* z-index */
35+
--z-index-modal: 1001; /* modal dialog, hard-coded from Fomantic modal.css */
36+
--z-index-toast: 1002; /* should be larger than modal */
3337
}
3438

3539
@media (min-width: 768px) and (max-width: 1200px) {

web_src/css/modules/dimmer.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
opacity: 1;
2121
}
2222

23-
.ui.dimmer > * {
23+
.ui.dimmer > .ui.modal {
2424
position: static;
2525
margin-top: auto !important;
2626
margin-bottom: auto !important;

web_src/css/modules/toast.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
position: fixed;
44
opacity: 0;
55
transition: all .2s ease;
6-
z-index: 500;
6+
z-index: var(--z-index-toast);
77
border-radius: var(--border-radius);
88
box-shadow: 0 8px 24px var(--color-shadow);
99
display: flex;

web_src/fomantic/build/components/dropdown.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ $.fn.dropdown = function(parameters) {
525525
return true;
526526
}
527527
if(settings.onShow.call(element) !== false) {
528-
settings.onAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
528+
$module.fomanticExt.onDropdownAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
529529
module.animate.show(function() {
530530
if( module.can.click() ) {
531531
module.bind.intent();
@@ -753,7 +753,7 @@ $.fn.dropdown = function(parameters) {
753753
if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
754754
module.show();
755755
}
756-
settings.onAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
756+
$module.fomanticExt.onDropdownAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
757757
}
758758
;
759759
if(settings.useLabels && module.has.maxSelections()) {
@@ -3994,8 +3994,6 @@ $.fn.dropdown.settings = {
39943994
onShow : function(){},
39953995
onHide : function(){},
39963996

3997-
onAfterFiltered: function(){}, // GITEA-PATCH: callback to correctly handle the filtered items
3998-
39993997
/* Component */
40003998
name : 'Dropdown',
40013999
namespace : 'dropdown',

web_src/fomantic/build/components/modal.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ $.fn.modal = function(parameters) {
467467
ignoreRepeatedEvents = false;
468468
return false;
469469
}
470-
470+
$module.fomanticExt.onModalBeforeHidden.call(element); // GITEA-PATCH: handle more UI updates before hidden
471471
if( module.is.animating() || module.is.active() ) {
472472
if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
473473
module.remove.active();
@@ -641,7 +641,7 @@ $.fn.modal = function(parameters) {
641641
$module
642642
.off('mousedown' + elementEventNamespace)
643643
;
644-
}
644+
}
645645
$dimmer
646646
.off('mousedown' + elementEventNamespace)
647647
;
@@ -877,7 +877,7 @@ $.fn.modal = function(parameters) {
877877
? $(document).scrollTop() + settings.padding
878878
: $(document).scrollTop() + (module.cache.contextHeight - module.cache.height - settings.padding),
879879
marginLeft: -(module.cache.width / 2)
880-
})
880+
})
881881
;
882882
} else {
883883
$module
@@ -886,7 +886,7 @@ $.fn.modal = function(parameters) {
886886
? -(module.cache.height / 2)
887887
: settings.padding / 2,
888888
marginLeft: -(module.cache.width / 2)
889-
})
889+
})
890890
;
891891
}
892892
module.verbose('Setting modal offset for legacy mode');

web_src/js/modules/fomantic/dropdown.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ const fomanticDropdownFn = $.fn.dropdown;
99
// use our own `$().dropdown` function to patch Fomantic's dropdown module
1010
export function initAriaDropdownPatch() {
1111
if ($.fn.dropdown === ariaDropdownFn) throw new Error('initAriaDropdownPatch could only be called once');
12-
$.fn.dropdown.settings.onAfterFiltered = onAfterFiltered;
1312
$.fn.dropdown = ariaDropdownFn;
1413
$.fn.fomanticExt.onResponseKeepSelectedItem = onResponseKeepSelectedItem;
14+
$.fn.fomanticExt.onDropdownAfterFiltered = onDropdownAfterFiltered;
1515
(ariaDropdownFn as FomanticInitFunction).settings = fomanticDropdownFn.settings;
1616
}
1717

@@ -71,7 +71,7 @@ function updateSelectionLabel(label: HTMLElement) {
7171
}
7272
}
7373

74-
function onAfterFiltered(this: any) {
74+
function onDropdownAfterFiltered(this: any) {
7575
const $dropdown = $(this).closest('.ui.dropdown'); // "this" can be the "ui dropdown" or "<select>"
7676
const hideEmptyDividers = $dropdown.dropdown('setting', 'hideDividers') === 'empty';
7777
const itemsMenu = $dropdown[0].querySelector('.scrolling.menu') || $dropdown[0].querySelector('.menu');

web_src/js/modules/fomantic/modal.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import $ from 'jquery';
22
import type {FomanticInitFunction} from '../../types.ts';
3+
import {queryElems} from '../../utils/dom.ts';
4+
import {hideToastsFrom} from '../toast.ts';
35

46
const fomanticModalFn = $.fn.modal;
57

68
// use our own `$.fn.modal` to patch Fomantic's modal module
79
export function initAriaModalPatch() {
810
if ($.fn.modal === ariaModalFn) throw new Error('initAriaModalPatch could only be called once');
911
$.fn.modal = ariaModalFn;
12+
$.fn.fomanticExt.onModalBeforeHidden = onModalBeforeHidden;
1013
(ariaModalFn as FomanticInitFunction).settings = fomanticModalFn.settings;
1114
}
1215

@@ -27,3 +30,10 @@ function ariaModalFn(this: any, ...args: Parameters<FomanticInitFunction>) {
2730
}
2831
return ret;
2932
}
33+
34+
function onModalBeforeHidden(this: any) {
35+
const $modal = $(this);
36+
const elModal = $modal[0];
37+
queryElems(elModal, 'form', (form: HTMLFormElement) => form.reset());
38+
hideToastsFrom(elModal.closest('.ui.dimmer') ?? document.body);
39+
}

web_src/js/modules/toast.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,17 @@ type ToastOpts = {
4040
preventDuplicates?: boolean,
4141
} & Options;
4242

43+
type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast };
44+
4345
// See https://github.com/apvarun/toastify-js#api for options
4446
function showToast(message: string, level: Intent, {gravity, position, duration, useHtmlBody, preventDuplicates = true, ...other}: ToastOpts = {}): Toast {
4547
const body = useHtmlBody ? String(message) : htmlEscape(message);
4648
const key = `${level}-${body}`;
49+
const parent = document.querySelector('.ui.dimmer.active') ?? document.body;
4750

48-
// prevent showing duplicate toasts with same level and message, and give a visual feedback for end users
51+
// prevent showing duplicate toasts with the same level and message, and give visual feedback for end users
4952
if (preventDuplicates) {
50-
const toastEl = document.querySelector(`.toastify[data-toast-unique-key="${CSS.escape(key)}"]`);
53+
const toastEl = parent.querySelector(`:scope > .toastify[data-toast-unique-key="${CSS.escape(key)}"]`);
5154
if (toastEl) {
5255
const toastDupNumEl = toastEl.querySelector('.toast-duplicate-number');
5356
showElem(toastDupNumEl);
@@ -59,6 +62,7 @@ function showToast(message: string, level: Intent, {gravity, position, duration,
5962

6063
const {icon, background, duration: levelDuration} = levels[level ?? 'info'];
6164
const toast = Toastify({
65+
selector: parent,
6266
text: `
6367
<div class='toast-icon'>${svg(icon)}</div>
6468
<div class='toast-body'><span class="toast-duplicate-number tw-hidden">1</span>${body}</div>
@@ -75,6 +79,7 @@ function showToast(message: string, level: Intent, {gravity, position, duration,
7579
toast.showToast();
7680
toast.toastElement.querySelector('.toast-close').addEventListener('click', () => toast.hideToast());
7781
toast.toastElement.setAttribute('data-toast-unique-key', key);
82+
(toast.toastElement as ToastifyElement)._giteaToastifyInstance = toast;
7883
return toast;
7984
}
8085

@@ -89,3 +94,12 @@ export function showWarningToast(message: string, opts?: ToastOpts): Toast {
8994
export function showErrorToast(message: string, opts?: ToastOpts): Toast {
9095
return showToast(message, 'error', opts);
9196
}
97+
98+
export function hideToastsFrom(parent: Element): void {
99+
const toasts = parent.querySelectorAll(':scope > .toastify');
100+
console.log(toasts);
101+
for (const toast of toasts) {
102+
const inst = (toast as ToastifyElement)._giteaToastifyInstance;
103+
inst?.hideToast();
104+
}
105+
}

0 commit comments

Comments
 (0)