mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-18 00:01:32 -04:00
Compare commits
No commits in common. "3ff81d38d87b88de004d666816e0ece46ea8bf65" and "c35b16a9a491ffbd093bf3e759e94cdbc960fe9c" have entirely different histories.
3ff81d38d8
...
c35b16a9a4
@ -108,9 +108,10 @@ func RenderCommitBody(ctx context.Context, msg, urlPrefix string, metas map[stri
|
||||
// Match text that is between back ticks.
|
||||
var codeMatcher = regexp.MustCompile("`([^`]+)`")
|
||||
|
||||
// RenderCodeBlock renders "`…`" as highlighted "<code>" block, intended for issue and PR titles
|
||||
// RenderCodeBlock renders "`…`" as highlighted "<code>" block.
|
||||
// Intended for issue and PR titles, these containers should have styles for "<code>" elements
|
||||
func RenderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML {
|
||||
htmlWithCodeTags := codeMatcher.ReplaceAllString(string(htmlEscapedTextToRender), `<code class="inline-code-block">$1</code>`) // replace with HTML <code> tags
|
||||
htmlWithCodeTags := codeMatcher.ReplaceAllString(string(htmlEscapedTextToRender), "<code>$1</code>") // replace with HTML <code> tags
|
||||
return template.HTML(htmlWithCodeTags)
|
||||
}
|
||||
|
||||
|
@ -2823,7 +2823,6 @@ users.list_status_filter.is_prohibit_login = Prohibit Login
|
||||
users.list_status_filter.not_prohibit_login = Allow Login
|
||||
users.list_status_filter.is_2fa_enabled = 2FA Enabled
|
||||
users.list_status_filter.not_2fa_enabled = 2FA Disabled
|
||||
users.details = User Details
|
||||
|
||||
emails.email_manage_panel = User Email Management
|
||||
emails.primary = Primary
|
||||
|
@ -1777,19 +1777,6 @@ milestones.filter_sort.most_complete=消化率の高い順
|
||||
milestones.filter_sort.most_issues=イシューの多い順
|
||||
milestones.filter_sort.least_issues=イシューの少ない順
|
||||
|
||||
signing.will_sign=このコミットは鍵 "%s" で署名されます。
|
||||
signing.wont_sign.error=コミットの署名可否を確認中にエラーが発生しました。
|
||||
signing.wont_sign.nokey=このコミットに署名するための鍵がありません。
|
||||
signing.wont_sign.never=コミットが署名されることはありません。
|
||||
signing.wont_sign.always=コミットは常に署名されます。
|
||||
signing.wont_sign.pubkey=アカウントに公開鍵が登録されていないため、コミットは署名されません。
|
||||
signing.wont_sign.twofa=コミットに署名するには、2要素認証を有効にする必要があります。
|
||||
signing.wont_sign.parentsigned=親コミットが署名されていないため、このコミットも署名されません。
|
||||
signing.wont_sign.basesigned=ベース側のコミットが署名されていないため、マージは署名されません。
|
||||
signing.wont_sign.headsigned=HEADコミットが署名されていないため、マージは署名されません。
|
||||
signing.wont_sign.commitssigned=関連するコミットすべてが署名されていないため、マージは署名されません。
|
||||
signing.wont_sign.approved=PRが未承認のため、マージは署名されません。
|
||||
signing.wont_sign.not_signed_in=サインインしていません。
|
||||
|
||||
ext_wiki=外部Wikiへのアクセス
|
||||
ext_wiki.desc=外部Wikiへのリンク。
|
||||
@ -1919,9 +1906,7 @@ settings.mirror_settings.docs.disabled_push_mirror.info=プッシュ方式のミ
|
||||
settings.mirror_settings.docs.no_new_mirrors=このリポジトリは他のリポジトリと変更をミラーリングしています。 現時点では新しいミラーを作成することはできないことに留意してください。
|
||||
settings.mirror_settings.docs.can_still_use=既存ミラーを変更したりミラーを新規に作成することはできませんが、既存ミラーを利用することは可能です。
|
||||
settings.mirror_settings.docs.pull_mirror_instructions=プル方式のミラーを設定するには、次を参照:
|
||||
settings.mirror_settings.docs.more_information_if_disabled=プッシュミラーとプルミラーの詳細は、こちらをご覧ください:
|
||||
settings.mirror_settings.docs.doc_link_title=リポジトリをミラーリングするには?
|
||||
settings.mirror_settings.docs.doc_link_pull_section=ドキュメントの「リモートリポジトリからのプル」セクション。
|
||||
settings.mirror_settings.docs.pulling_remote_title=リモートリポジトリからのプル
|
||||
settings.mirror_settings.mirrored_repository=同期するリポジトリ
|
||||
settings.mirror_settings.direction=方向
|
||||
@ -2001,7 +1986,6 @@ settings.transfer.rejected=リポジトリの移転は拒否されました。
|
||||
settings.transfer.success=リポジトリの移転が成功しました。
|
||||
settings.transfer_abort=転送をキャンセル
|
||||
settings.transfer_abort_invalid=存在しないリポジトリの移転はキャンセルできません。
|
||||
settings.transfer_abort_success=%s へのリポジトリ移転は正常にキャンセルされました。
|
||||
settings.transfer_desc=別のユーザーやあなたが管理者権限を持っている組織にリポジトリを移転します。
|
||||
settings.transfer_form_title=確認のためリポジトリ名を入力:
|
||||
settings.transfer_in_progress=現在進行中の移転があります。このリポジトリを別のユーザーに移転したい場合はキャンセルしてください。
|
||||
@ -2277,17 +2261,11 @@ settings.matrix.room_id=ルーム ID
|
||||
settings.matrix.message_type=メッセージ種別
|
||||
settings.archive.button=アーカイブ
|
||||
settings.archive.header=このリポジトリをアーカイブ
|
||||
settings.archive.text=リポジトリをアーカイブするとリポジトリ全体が読み出し専用となります。 ダッシュボードにも表示されなくなります。 新たなコミット、あるいは、イシューやプルリクエストの作成は、誰もできなくなります (あなたでさえも!)。
|
||||
settings.archive.success=リポジトリをアーカイブしました。
|
||||
settings.archive.error=リポジトリのアーカイブ設定でエラーが発生しました。 詳細はログを確認してください。
|
||||
settings.archive.error_ismirror=ミラーのリポジトリはアーカイブできません。
|
||||
settings.archive.branchsettings_unavailable=ブランチ設定は、アーカイブリポジトリでは使用できません。
|
||||
settings.archive.tagsettings_unavailable=タグ設定は、アーカイブリポジトリでは使用できません。
|
||||
settings.unarchive.button=アーカイブ解除
|
||||
settings.unarchive.header=このリポジトリをアーカイブ解除
|
||||
settings.unarchive.text=リポジトリのアーカイブを解除すると、コミット、プッシュ、新規のイシューやプルリクエストを受け付ける機能が復活します。
|
||||
settings.unarchive.success=リポジトリのアーカイブを解除しました。
|
||||
settings.unarchive.error=リポジトリのアーカイブ解除でエラーが発生しました。 詳細はログを確認してください。
|
||||
settings.update_avatar_success=リポジトリのアバターを更新しました。
|
||||
settings.lfs=LFS
|
||||
settings.lfs_filelist=このリポジトリに含まれているLFSファイル
|
||||
@ -2410,7 +2388,6 @@ release.edit_release=リリースを更新
|
||||
release.delete_release=リリースを削除
|
||||
release.delete_tag=タグを削除
|
||||
release.deletion=リリースの削除
|
||||
release.deletion_desc=リリースの削除は、Giteaからの削除だけを行います。 Gitタグやリポジトリの内容、履歴には影響しません。 続行しますか?
|
||||
release.deletion_success=リリースを削除しました。
|
||||
release.deletion_tag_desc=リポジトリからこのタグを削除します。 リポジトリの内容と履歴はそのまま残ります。 続行しますか?
|
||||
release.deletion_tag_success=タグを削除しました。
|
||||
@ -2431,7 +2408,6 @@ branch.already_exists=ブランチ "%s" は既に存在します。
|
||||
branch.delete_head=削除
|
||||
branch.delete=ブランチ "%s" の削除
|
||||
branch.delete_html=ブランチ削除
|
||||
branch.delete_desc=ブランチの削除は恒久的です。 実際に削除されるまでの短い期間、ブランチが存在したままになることもありますが、たいていは元に戻すことはできません。 続行しますか?
|
||||
branch.deletion_success=ブランチ "%s" を削除しました。
|
||||
branch.deletion_failed=ブランチ "%s" の削除に失敗しました。
|
||||
branch.delete_branch_has_new_commits=マージ後に新しいコミットが追加されているため、ブランチ "%s" を削除できません。
|
||||
@ -2597,7 +2573,6 @@ teams.all_repositories_helper=チームはすべてのリポジトリにアク
|
||||
teams.all_repositories_read_permission_desc=このチームは<strong>すべてのリポジトリ</strong>の<strong>読み取り</strong>アクセス権を持ちます: メンバーはリポジトリの閲覧とクローンが可能です。
|
||||
teams.all_repositories_write_permission_desc=このチームは<strong>すべてのリポジトリ</strong>の<strong>書き込み</strong>アクセス権を持ちます: メンバーはリポジトリの読み取りとプッシュが可能です。
|
||||
teams.all_repositories_admin_permission_desc=このチームは<strong>すべてのリポジトリ</strong>の<strong>管理者</strong>アクセス権を持ちます: メンバーはリポジトリの読み取り、プッシュ、共同作業者の追加が可能です。
|
||||
teams.invite.title=あなたは組織 <strong>%[2]s</strong> 内のチーム <strong>%[1]s</strong> への参加に招待されました。
|
||||
teams.invite.by=%s からの招待
|
||||
teams.invite.description=下のボタンをクリックしてチームに参加してください。
|
||||
|
||||
@ -2627,13 +2602,11 @@ dashboard.clean_unbind_oauth=関連付けられていないOAuth接続を削除
|
||||
dashboard.clean_unbind_oauth_success=関連付けられていないOAuth接続をすべて削除しました。
|
||||
dashboard.task.started=タスクを開始しました: %[1]s
|
||||
dashboard.task.process=タスク: %[1]s
|
||||
dashboard.task.cancelled=タスク: %[1]s をキャンセル: %[3]s
|
||||
dashboard.task.error=タスクでエラー: %[1]s: %[3]s
|
||||
dashboard.task.finished=タスク: %[2]s が開始したタスク %[1]s が完了
|
||||
dashboard.task.unknown=不明なタスクです: %[1]s
|
||||
dashboard.cron.started=Cronを開始しました: %[1]s
|
||||
dashboard.cron.process=Cron: %[1]s
|
||||
dashboard.cron.cancelled=Cron: %[1]s をキャンセル: %[3]s
|
||||
dashboard.cron.error=Cronでエラー: %s: %[3]s
|
||||
dashboard.cron.finished=Cron: %[1]s が完了
|
||||
dashboard.delete_inactive_accounts=アクティベートされていないアカウントをすべて削除
|
||||
@ -3322,17 +3295,14 @@ settings.delete.success=パッケージを削除しました。
|
||||
settings.delete.error=パッケージの削除に失敗しました。
|
||||
owner.settings.cargo.title=Cargoレジストリ インデックス
|
||||
owner.settings.cargo.initialize=インデックスを初期化
|
||||
owner.settings.cargo.initialize.description=Cargoレジストリを使用するには、インデックス用の特別なgitリポジトリが必要です。 このオプションを使用するとそのリポジトリを(再)作成し、自動的に構成します。
|
||||
owner.settings.cargo.initialize.error=Cargoインデックスの初期化に失敗しました: %v
|
||||
owner.settings.cargo.initialize.success=Cargoインデックスは正常に作成されました。
|
||||
owner.settings.cargo.rebuild=インデックスを再構築
|
||||
owner.settings.cargo.rebuild.description=インデックスが格納されているCargoパッケージと同期していない場合は、再構築すると良いでしょう。
|
||||
owner.settings.cargo.rebuild.error=Cargoインデックスの再構築に失敗しました: %v
|
||||
owner.settings.cargo.rebuild.success=Cargoインデックスは正常に再構築されました。
|
||||
owner.settings.cleanuprules.title=クリーンアップルールの管理
|
||||
owner.settings.cleanuprules.add=クリーンアップルールを追加
|
||||
owner.settings.cleanuprules.edit=クリーンアップルールを編集
|
||||
owner.settings.cleanuprules.none=クリーンアップルールはありません。 ドキュメントを参照してください。
|
||||
owner.settings.cleanuprules.preview=クリーンアップルールをプレビュー
|
||||
owner.settings.cleanuprules.preview.overview=%d パッケージが削除される予定です。
|
||||
owner.settings.cleanuprules.preview.none=クリーンアップルールと一致するパッケージがありません。
|
||||
@ -3351,7 +3321,6 @@ owner.settings.cleanuprules.success.update=クリーンアップルールが更
|
||||
owner.settings.cleanuprules.success.delete=クリーンアップルールが削除されました。
|
||||
owner.settings.chef.title=Chefレジストリ
|
||||
owner.settings.chef.keypair=キーペアを生成
|
||||
owner.settings.chef.keypair.description=Chefレジストリの認証にはキーペアが必要です。 すでにキーペアを生成していた場合、新しいキーペアを生成すると古いキーペアは破棄されます。
|
||||
|
||||
[secrets]
|
||||
secrets=シークレット
|
||||
|
@ -13,8 +13,6 @@ import (
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
org_model "code.gitea.io/gitea/models/organization"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
system_model "code.gitea.io/gitea/models/system"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/auth/password"
|
||||
@ -34,7 +32,6 @@ import (
|
||||
const (
|
||||
tplUsers base.TplName = "admin/user/list"
|
||||
tplUserNew base.TplName = "admin/user/new"
|
||||
tplUserView base.TplName = "admin/user/view"
|
||||
tplUserEdit base.TplName = "admin/user/edit"
|
||||
)
|
||||
|
||||
@ -252,61 +249,6 @@ func prepareUserInfo(ctx *context.Context) *user_model.User {
|
||||
return u
|
||||
}
|
||||
|
||||
func ViewUser(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("admin.users.details")
|
||||
ctx.Data["PageIsAdminUsers"] = true
|
||||
ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation
|
||||
ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
|
||||
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||
|
||||
u := prepareUserInfo(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
repos, count, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
OwnerID: u.ID,
|
||||
OrderBy: db.SearchOrderByAlphabetically,
|
||||
Private: true,
|
||||
Collaborate: util.OptionalBoolFalse,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchRepository", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Repos"] = repos
|
||||
ctx.Data["ReposTotal"] = int(count)
|
||||
|
||||
emails, err := user_model.GetEmailAddresses(ctx.Doer.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetEmailAddresses", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Emails"] = emails
|
||||
ctx.Data["EmailsTotal"] = len(emails)
|
||||
|
||||
orgs, err := org_model.FindOrgs(org_model.FindOrgOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
UserID: u.ID,
|
||||
IncludePrivate: true,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("FindOrgs", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Users"] = orgs // needed to be able to use explore/user_list template
|
||||
ctx.Data["OrgsTotal"] = len(orgs)
|
||||
|
||||
ctx.HTML(http.StatusOK, tplUserView)
|
||||
}
|
||||
|
||||
// EditUser show editing user page
|
||||
func EditUser(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("admin.users.edit_account")
|
||||
|
@ -398,11 +398,6 @@ func SignUp(ctx *context.Context) {
|
||||
// Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true
|
||||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration
|
||||
|
||||
redirectTo := ctx.FormString("redirect_to")
|
||||
if len(redirectTo) > 0 {
|
||||
middleware.SetRedirectToCookie(ctx.Resp, redirectTo)
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, tplSignUp)
|
||||
}
|
||||
|
||||
@ -734,12 +729,6 @@ func handleAccountActivation(ctx *context.Context, user *user_model.User) {
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("auth.account_activated"))
|
||||
if redirectTo := ctx.GetSiteCookie("redirect_to"); len(redirectTo) > 0 {
|
||||
middleware.DeleteRedirectToCookie(ctx.Resp)
|
||||
ctx.RedirectToFirst(redirectTo)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/")
|
||||
}
|
||||
|
||||
|
@ -902,17 +902,9 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles
|
||||
|
||||
// NewIssue render creating issue page
|
||||
func NewIssue(ctx *context.Context) {
|
||||
issueConfig, _ := issue_service.GetTemplateConfigFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||
hasTemplates := issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||
if !issueConfig.BlankIssuesEnabled && hasTemplates {
|
||||
// The "issues/new" and "issues/new/choose" share the same query parameters "project" and "milestone", if blank issues are disabled, just redirect to the "issues/choose" page with these parameters.
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/new/choose?%s", ctx.Repo.Repository.Link(), ctx.Req.URL.RawQuery), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["NewIssueChooseTemplate"] = hasTemplates
|
||||
ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
|
||||
title := ctx.FormString("title")
|
||||
ctx.Data["TitleQuery"] = title
|
||||
|
@ -573,8 +573,7 @@ func registerRoutes(m *web.Route) {
|
||||
m.Group("/users", func() {
|
||||
m.Get("", admin.Users)
|
||||
m.Combo("/new").Get(admin.NewUser).Post(web.Bind(forms.AdminCreateUserForm{}), admin.NewUserPost)
|
||||
m.Get("/{userid}", admin.ViewUser)
|
||||
m.Combo("/{userid}/edit").Get(admin.EditUser).Post(web.Bind(forms.AdminEditUserForm{}), admin.EditUserPost)
|
||||
m.Combo("/{userid}").Get(admin.EditUser).Post(web.Bind(forms.AdminEditUserForm{}), admin.EditUserPost)
|
||||
m.Post("/{userid}/delete", admin.DeleteUser)
|
||||
m.Post("/{userid}/avatar", web.Bind(forms.AvatarForm{}), admin.AvatarPost)
|
||||
m.Post("/{userid}/avatar/delete", admin.DeleteAvatar)
|
||||
|
@ -120,9 +120,9 @@ func VerifyAuthWithOptions(options *VerifyOptions) func(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect to dashboard (or alternate location) if user tries to visit any non-login page.
|
||||
// Redirect to dashboard if user tries to visit any non-login page.
|
||||
if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" {
|
||||
ctx.RedirectToFirst(ctx.FormString("redirect_to"))
|
||||
ctx.Redirect(setting.AppSubURL + "/")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,6 @@ package mailer
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
org_model "code.gitea.io/gitea/models/organization"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -35,22 +33,6 @@ func MailTeamInvite(ctx context.Context, inviter *user_model.User, team *org_mod
|
||||
|
||||
locale := translation.NewLocale(inviter.Language)
|
||||
|
||||
// check if a user with this email already exists
|
||||
user, err := user_model.GetUserByEmail(ctx, invite.Email)
|
||||
if err != nil && !user_model.IsErrUserNotExist(err) {
|
||||
return err
|
||||
} else if user != nil && user.ProhibitLogin {
|
||||
return fmt.Errorf("login is prohibited for the invited user")
|
||||
}
|
||||
|
||||
inviteRedirect := url.QueryEscape(fmt.Sprintf("/org/invite/%s", invite.Token))
|
||||
inviteURL := fmt.Sprintf("%suser/sign_up?redirect_to=%s", setting.AppURL, inviteRedirect)
|
||||
|
||||
if err == nil && user != nil {
|
||||
// user account exists
|
||||
inviteURL = fmt.Sprintf("%suser/login?redirect_to=%s", setting.AppURL, inviteRedirect)
|
||||
}
|
||||
|
||||
subject := locale.Tr("mail.team_invite.subject", inviter.DisplayName(), org.DisplayName())
|
||||
mailMeta := map[string]any{
|
||||
"Inviter": inviter,
|
||||
@ -58,7 +40,6 @@ func MailTeamInvite(ctx context.Context, inviter *user_model.User, team *org_mod
|
||||
"Team": team,
|
||||
"Invite": invite,
|
||||
"Subject": subject,
|
||||
"InviteURL": inviteURL,
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{{template "base/head" .ctxData}}
|
||||
<div role="main" aria-label="{{.ctxData.Title}}" class="page-content {{.pageClass}}">
|
||||
<div class="ui container gt-mb-4">
|
||||
<div class="ui container">
|
||||
{{template "base/alert" .ctxData}}
|
||||
</div>
|
||||
<div class="ui container flex-container">
|
||||
|
@ -68,35 +68,36 @@
|
||||
</th>
|
||||
<th>{{.locale.Tr "email"}}</th>
|
||||
<th>{{.locale.Tr "admin.users.activated"}}</th>
|
||||
<th>{{.locale.Tr "admin.users.admin"}}</th>
|
||||
<th>{{.locale.Tr "admin.users.restricted"}}</th>
|
||||
<th>{{.locale.Tr "admin.users.2fa"}}</th>
|
||||
<th>{{.locale.Tr "admin.users.repos"}}</th>
|
||||
<th>{{.locale.Tr "admin.users.created"}}</th>
|
||||
<th data-sortt-asc="lastlogin" data-sortt-desc="reverselastlogin">
|
||||
{{.locale.Tr "admin.users.last_login"}}
|
||||
{{SortArrow "lastlogin" "reverselastlogin" $.SortType false}}
|
||||
</th>
|
||||
<th>{{.locale.Tr "admin.users.edit"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Users}}
|
||||
<tr>
|
||||
<td>{{.ID}}</td>
|
||||
<td>
|
||||
<a href="{{$.Link}}/{{.ID}}">{{.Name}}</a>
|
||||
{{if .IsAdmin}}
|
||||
<span class="ui basic label">{{$.locale.Tr "admin.users.admin"}}</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td><a href="{{.HomeLink}}">{{.Name}}</a></td>
|
||||
<td class="gt-ellipsis gt-max-width-12rem">{{.Email}}</td>
|
||||
<td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
||||
<td>{{if .IsAdmin}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
||||
<td>{{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
||||
<td>{{if index $.UsersTwoFaStatus .ID}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
||||
<td>{{.NumRepos}}</td>
|
||||
<td>{{DateTime "short" .CreatedUnix}}</td>
|
||||
{{if .LastLoginUnix}}
|
||||
<td>{{DateTime "short" .LastLoginUnix}}</td>
|
||||
{{else}}
|
||||
<td><span>{{$.locale.Tr "admin.users.never_login"}}</span></td>
|
||||
{{end}}
|
||||
<td><a href="{{$.Link}}/{{.ID}}">{{svg "octicon-pencil"}}</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
|
@ -1,48 +0,0 @@
|
||||
{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin view user")}}
|
||||
|
||||
<div class="admin-setting-content">
|
||||
<div class="admin-responsive-columns">
|
||||
<div class="gt-f1">
|
||||
<h4 class="ui top attached header">
|
||||
{{.Title}}
|
||||
<div class="ui right">
|
||||
<a class="ui primary tiny button" href="{{.Link}}/edit">{{ctx.Locale.Tr "admin.users.edit"}}</a>
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
{{template "admin/user/view_details" .}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="gt-f1">
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "admin.emails"}}
|
||||
<div class="ui right">
|
||||
{{.EmailsTotal}}
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
{{template "admin/user/view_emails" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "admin.repositories"}}
|
||||
<div class="ui right">
|
||||
{{.ReposTotal}}
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
{{template "explore/repo_list" .}}
|
||||
</div>
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "settings.organization"}}
|
||||
<div class="ui right">
|
||||
{{.OrgsTotal}}
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
{{template "explore/user_list" .}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "admin/layout_footer" .}}
|
@ -1,65 +0,0 @@
|
||||
<div class="flex-list">
|
||||
<div class="flex-item">
|
||||
<div class="flex-item-leading">
|
||||
{{ctx.AvatarUtils.Avatar .User 48}}
|
||||
</div>
|
||||
<div class="flex-item-main">
|
||||
<div class="flex-item-title">
|
||||
{{template "shared/user/name" .User}}
|
||||
{{if .User.IsAdmin}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "admin.users.admin"}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
<b>{{ctx.Locale.Tr "admin.users.auth_source"}}:</b>
|
||||
{{if eq .LoginSource.ID 0}}
|
||||
{{ctx.Locale.Tr "admin.users.local"}}
|
||||
{{else}}
|
||||
{{.LoginSource.Name}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
<b>{{ctx.Locale.Tr "admin.users.activated"}}:</b>
|
||||
{{if .User.IsActive}}
|
||||
{{svg "octicon-check"}}
|
||||
{{else}}
|
||||
{{svg "octicon-x"}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
<b>{{ctx.Locale.Tr "admin.users.restricted"}}:</b>
|
||||
{{if .User.IsRestricted}}
|
||||
{{svg "octicon-check"}}
|
||||
{{else}}
|
||||
{{svg "octicon-x"}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
<b>{{ctx.Locale.Tr "settings.visibility"}}:</b>
|
||||
{{if .User.Visibility.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}}
|
||||
{{if .User.Visibility.IsPrivate}}{{ctx.Locale.Tr "settings.visibility.private"}}{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
<b>{{ctx.Locale.Tr "admin.users.2fa"}}:</b>
|
||||
{{if .TwoFactorEnabled}}
|
||||
<span class="text green">{{svg "octicon-check"}}</span>
|
||||
{{else}}
|
||||
{{svg "octicon-x"}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .User.Location}}
|
||||
<div class="flex-item-body">
|
||||
<span class="flex-text-inline">{{svg "octicon-location"}}{{.User.Location}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .User.Website}}
|
||||
<div class="flex-item-body">
|
||||
<span class="flex-text-inline">
|
||||
{{svg "octicon-link"}}
|
||||
<a target="_blank" href="{{.User.Website}}">{{.User.Website}}</a>
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,19 +0,0 @@
|
||||
<div class="flex-list">
|
||||
{{range .Emails}}
|
||||
<div class="flex-item">
|
||||
<div class="flex-item-main">
|
||||
<div class="flex-text-block">
|
||||
{{.Email}}
|
||||
{{if .IsPrimary}}
|
||||
<div class="ui primary label">{{ctx.Locale.Tr "settings.primary"}}</div>
|
||||
{{end}}
|
||||
{{if .IsActivated}}
|
||||
<div class="ui green label">{{ctx.Locale.Tr "settings.activated"}}</div>
|
||||
{{else}}
|
||||
<div class="ui label">{{ctx.Locale.Tr "settings.requires_activation"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
@ -2,8 +2,7 @@
|
||||
<link rel="stylesheet" href="{{AssetUrlPrefix}}/css/devtest.css?v={{AssetVersion}}">
|
||||
<div class="page-content devtest">
|
||||
<div class="ui container">
|
||||
<h1>Flex List (standalone)</h1>
|
||||
<div class="divider"></div>
|
||||
<h1 class="gt-border-secondary-bottom">Flex List (standalone)</h1>
|
||||
<div class="flex-list">
|
||||
<div class="flex-item">
|
||||
<div class="flex-item-leading">
|
||||
@ -86,7 +85,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div class="divider gt-my-0"></div>
|
||||
|
||||
<h1>Flex List (with "ui segment")</h1>
|
||||
<div class="ui attached segment">
|
||||
@ -102,14 +101,6 @@
|
||||
<div class="flex-item">item 2</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>If parent provides the padding/margin space:</h1>
|
||||
<div class="gt-border-secondary gt-py-4">
|
||||
<div class="flex-list flex-space-fitted">
|
||||
<div class="flex-item">item 1 (no padding top)</div>
|
||||
<div class="flex-item">item 2 (no padding bottom)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
@ -1,31 +0,0 @@
|
||||
<div class="flex-list">
|
||||
{{range .Users}}
|
||||
<div class="flex-item flex-item-center">
|
||||
<div class="flex-item-leading">
|
||||
{{ctx.AvatarUtils.Avatar . 48}}
|
||||
</div>
|
||||
<div class="flex-item-main">
|
||||
<div class="flex-item-title">
|
||||
{{template "shared/user/name" .}}
|
||||
{{if .Visibility.IsPrivate}}
|
||||
<span class="ui basic tiny label">{{ctx.Locale.Tr "repo.desc.private"}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
{{if .Location}}
|
||||
<span class="flex-text-inline">{{svg "octicon-location"}}{{.Location}}</span>
|
||||
{{end}}
|
||||
{{if and .Email (or (and $.ShowUserEmail $.IsSigned (not .KeepEmailPrivate)) $.PageIsAdminUsers)}}
|
||||
<span class="flex-text-inline">
|
||||
{{svg "octicon-mail"}}
|
||||
<a href="mailto:{{.Email}}">{{.Email}}</a>
|
||||
</span>
|
||||
{{end}}
|
||||
<span class="flex-text-inline">{{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix) | Safe}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="flex-item">{{ctx.Locale.Tr "explore.user_no_results"}}</div>
|
||||
{{end}}
|
||||
</div>
|
@ -4,7 +4,37 @@
|
||||
<div class="ui container">
|
||||
{{template "explore/search" .}}
|
||||
|
||||
{{template "explore/user_list" .}}
|
||||
<div class="flex-list">
|
||||
{{range .Users}}
|
||||
<div class="flex-item flex-item-center">
|
||||
<div class="flex-item-leading">
|
||||
{{ctx.AvatarUtils.Avatar . 48}}
|
||||
</div>
|
||||
<div class="flex-item-main">
|
||||
<div class="flex-item-title">
|
||||
{{template "shared/user/name" .}}
|
||||
{{if .Visibility.IsPrivate}}
|
||||
<span class="ui basic tiny label">{{$.locale.Tr "repo.desc.private"}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
{{if .Location}}
|
||||
<span class="flex-text-inline">{{svg "octicon-location"}}{{.Location}}</span>
|
||||
{{end}}
|
||||
{{if and $.ShowUserEmail .Email $.IsSigned (not .KeepEmailPrivate)}}
|
||||
<span class="flex-text-inline">
|
||||
{{svg "octicon-mail"}}
|
||||
<a href="mailto:{{.Email}}" rel="nofollow">{{.Email}}</a>
|
||||
</span>
|
||||
{{end}}
|
||||
<span class="flex-text-inline">{{svg "octicon-calendar"}}{{$.locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix) | Safe}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="flex-item">{{$.locale.Tr "explore.user_no_results"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{template "base/paginate" .}}
|
||||
</div>
|
||||
|
@ -4,9 +4,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="format-detection" content="telephone=no,date=no,address=no,email=no,url=no">
|
||||
</head>
|
||||
{{$invite_url := printf "%sorg/invite/%s" AppUrl (QueryEscape .Invite.Token)}}
|
||||
<body>
|
||||
<p>{{.locale.Tr "mail.team_invite.text_1" (DotEscape .Inviter.DisplayName) (DotEscape .Team.Name) (DotEscape .Organization.DisplayName) | Str2html}}</p>
|
||||
<p>{{.locale.Tr "mail.team_invite.text_2"}}</p><p><a href="{{.InviteURL}}">{{.InviteURL}}</a></p>
|
||||
<p>{{.locale.Tr "mail.team_invite.text_2"}}</p><p><a href="{{$invite_url}}">{{$invite_url}}</a></p>
|
||||
<p>{{.locale.Tr "mail.link_not_working_do_paste"}}</p>
|
||||
<p>{{.locale.Tr "mail.team_invite.text_3" .Invite.Email}}</p>
|
||||
|
||||
|
@ -12,9 +12,8 @@
|
||||
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
|
||||
</div>
|
||||
</form>
|
||||
<div>
|
||||
<div class="{{if .PackageDescriptors}}flex-list{{end}} gt-pt-4">
|
||||
{{range .PackageDescriptors}}
|
||||
<div class="flex-list">
|
||||
<div class="flex-item">
|
||||
<div class="flex-item-main">
|
||||
<div class="flex-item-title">
|
||||
@ -35,7 +34,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
{{if not .HasPackages}}
|
||||
<div class="empty center">
|
||||
@ -48,7 +46,7 @@
|
||||
<p>{{.locale.Tr "packages.empty.documentation" "https://docs.gitea.com/usage/packages/overview/" | Safe}}</p>
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="gt-py-4">{{.locale.Tr "packages.filter.no_result"}}</p>
|
||||
<p>{{.locale.Tr "packages.filter.no_result"}}</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{template "base/paginate" .}}
|
||||
|
@ -18,9 +18,8 @@
|
||||
<button class="ui primary button">{{.locale.Tr "explore.search"}}</button>
|
||||
</div>
|
||||
</form>
|
||||
<div>
|
||||
<div class="{{if .PackageDescriptors}}flex-list{{end}} gt-pt-4">
|
||||
{{range .PackageDescriptors}}
|
||||
<div class="flex-list">
|
||||
<div class="flex-item">
|
||||
<div class="flex-item-main">
|
||||
<a class="flex-item-title" href="{{.FullWebLink}}">{{.Version.LowerVersion}}</a>
|
||||
@ -29,9 +28,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="gt-py-4">{{.locale.Tr "packages.filter.no_result"}}</p>
|
||||
<p>{{.locale.Tr "packages.filter.no_result"}}</p>
|
||||
{{end}}
|
||||
{{template "base/paginate" .}}
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="flex-list">
|
||||
<div class="flex-list gt-m-0">
|
||||
{{if eq (len .Runs) 0}}
|
||||
<div class="empty center">
|
||||
{{svg "octicon-no-entry" 48}}
|
||||
|
@ -47,7 +47,7 @@
|
||||
<td class="lines-type-marker lines-type-marker-old del-code"><span class="gt-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
|
||||
<td class="lines-code lines-code-old del-code">{{/*
|
||||
*/}}{{if and $.root.SignedUserID $.root.PageIsPullFiles}}{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-left{{if (not $line.CanComment)}} gt-invisible{{end}}" data-side="left" data-idx="{{$line.LeftIdx}}">{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-left{{if (not $line.CanComment)}} invisible{{end}}" data-side="left" data-idx="{{$line.LeftIdx}}">{{/*
|
||||
*/}}{{svg "octicon-plus"}}{{/*
|
||||
*/}}</button>{{/*
|
||||
*/}}{{end}}{{/*
|
||||
@ -62,7 +62,7 @@
|
||||
<td class="lines-type-marker lines-type-marker-new add-code">{{if $match.RightIdx}}<span class="gt-mono" data-type-marker="{{$match.GetLineTypeMarker}}"></span>{{end}}</td>
|
||||
<td class="lines-code lines-code-new add-code">{{/*
|
||||
*/}}{{if and $.root.SignedUserID $.root.PageIsPullFiles}}{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-right{{if (not $match.CanComment)}} gt-invisible{{end}}" data-side="right" data-idx="{{$match.RightIdx}}">{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-right{{if (not $match.CanComment)}} invisible{{end}}" data-side="right" data-idx="{{$match.RightIdx}}">{{/*
|
||||
*/}}{{svg "octicon-plus"}}{{/*
|
||||
*/}}</button>{{/*
|
||||
*/}}{{end}}{{/*
|
||||
@ -79,7 +79,7 @@
|
||||
<td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="gt-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
|
||||
<td class="lines-code lines-code-old">{{/*
|
||||
*/}}{{if and $.root.SignedUserID $.root.PageIsPullFiles (not (eq .GetType 2))}}{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-left{{if (not $line.CanComment)}} gt-invisible{{end}}" data-side="left" data-idx="{{$line.LeftIdx}}">{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-left{{if (not $line.CanComment)}} invisible{{end}}" data-side="left" data-idx="{{$line.LeftIdx}}">{{/*
|
||||
*/}}{{svg "octicon-plus"}}{{/*
|
||||
*/}}</button>{{/*
|
||||
*/}}{{end}}{{/*
|
||||
@ -94,7 +94,7 @@
|
||||
<td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="gt-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
|
||||
<td class="lines-code lines-code-new">{{/*
|
||||
*/}}{{if and $.root.SignedUserID $.root.PageIsPullFiles (not (eq .GetType 3))}}{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-right{{if (not $line.CanComment)}} gt-invisible{{end}}" data-side="right" data-idx="{{$line.RightIdx}}">{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-right{{if (not $line.CanComment)}} invisible{{end}}" data-side="right" data-idx="{{$line.RightIdx}}">{{/*
|
||||
*/}}{{svg "octicon-plus"}}{{/*
|
||||
*/}}</button>{{/*
|
||||
*/}}{{end}}{{/*
|
||||
|
@ -52,7 +52,7 @@
|
||||
{{else}}
|
||||
<td class="chroma lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{/*
|
||||
*/}}{{if and $.root.SignedUserID $.root.PageIsPullFiles}}{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} gt-invisible{{end}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">{{/*
|
||||
*/}}<button type="button" aria-label="{{$.root.locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} invisible{{end}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">{{/*
|
||||
*/}}{{svg "octicon-plus"}}{{/*
|
||||
*/}}</button>{{/*
|
||||
*/}}{{end}}{{/*
|
||||
|
@ -6,9 +6,9 @@
|
||||
{{template "repo/code/recently_pushed_new_branches" .}}
|
||||
{{if and (not .HideRepoInfo) (not .IsBlame)}}
|
||||
<div class="ui repo-description">
|
||||
<div id="repo-desc" class="gt-font-16">
|
||||
<div id="repo-desc">
|
||||
{{$description := .Repository.DescriptionHTML $.Context}}
|
||||
{{if $description}}<span class="description">{{$description | RenderCodeBlock}}</span>{{else if .IsRepositoryAdmin}}<span class="no-description text-italic">{{.locale.Tr "repo.no_desc"}}</span>{{end}}
|
||||
{{if $description}}<span class="description">{{$description}}</span>{{else if .IsRepositoryAdmin}}<span class="no-description text-italic">{{.locale.Tr "repo.no_desc"}}</span>{{end}}
|
||||
<a class="link" href="{{.Repository.Website}}">{{.Repository.Website}}</a>
|
||||
</div>
|
||||
{{if .RepoSearchEnabled}}
|
||||
|
@ -21,18 +21,18 @@
|
||||
<div class="divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}gt-invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
<div class="divider"></div>
|
||||
{{$previousExclusiveScope = "_no_scope"}}
|
||||
{{$previousExclusiveScope := "_no_scope"}}
|
||||
{{range .OrgLabels}}
|
||||
{{$exclusiveScope := .ExclusiveScope}}
|
||||
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
|
||||
<div class="divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}gt-invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
|
@ -158,7 +158,7 @@
|
||||
<div class="no-select item">{{.locale.Tr "repo.issues.new.clear_assignees"}}</div>
|
||||
{{range .Assignees}}
|
||||
<a class="item muted" href="#" data-id="{{.ID}}" data-id-selector="#assignee_{{.ID}}">
|
||||
<span class="octicon-check gt-invisible">{{svg "octicon-check"}}</span>
|
||||
<span class="octicon-check invisible">{{svg "octicon-check"}}</span>
|
||||
<span class="text">
|
||||
{{ctx.AvatarUtils.Avatar . 28 "gt-mr-3"}}{{template "repo/search_name" .}}
|
||||
</span>
|
||||
|
@ -20,7 +20,7 @@
|
||||
{{range .Reviewers}}
|
||||
{{if .User}}
|
||||
<a class="{{if not .CanChange}}ui{{end}} item {{if .Checked}}checked{{end}} {{if not .CanChange}}ban-change{{end}}" href="#" data-id="{{.ItemID}}" data-id-selector="#review_request_{{.ItemID}}" {{if not .CanChange}} data-tooltip-content="{{$.locale.Tr "repo.issues.remove_request_review_block"}}"{{end}}>
|
||||
<span class="octicon-check {{if not .Checked}}gt-invisible{{end}}">{{svg "octicon-check"}}</span>
|
||||
<span class="octicon-check {{if not .Checked}}invisible{{end}}">{{svg "octicon-check"}}</span>
|
||||
<span class="text">
|
||||
{{ctx.AvatarUtils.Avatar .User 28 "gt-mr-3"}}{{template "repo/search_name" .User}}
|
||||
</span>
|
||||
@ -33,7 +33,7 @@
|
||||
{{range .TeamReviewers}}
|
||||
{{if .Team}}
|
||||
<a class="{{if not .CanChange}}ui{{end}} item {{if .Checked}}checked{{end}} {{if not .CanChange}}ban-change{{end}}" href="#" data-id="{{.ItemID}}" data-id-selector="#review_request_team_{{.Team.ID}}" {{if not .CanChange}} data-tooltip-content="{{$.locale.Tr "repo.issues.remove_request_review_block"}}"{{end}}>
|
||||
<span class="octicon-check {{if not .Checked}}gt-invisible{{end}}">{{svg "octicon-check" 16}}</span>
|
||||
<span class="octicon-check {{if not .Checked}}invisible{{end}}">{{svg "octicon-check" 16}}</span>
|
||||
<span class="text">
|
||||
{{svg "octicon-people" 16 "gt-ml-4 gt-mr-2"}}{{$.Issue.Repo.OwnerName}}/{{.Team.Name}}
|
||||
</span>
|
||||
@ -229,7 +229,7 @@
|
||||
{{$checked = true}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
<span class="octicon-check {{if not $checked}}gt-invisible{{end}}">{{svg "octicon-check"}}</span>
|
||||
<span class="octicon-check {{if not $checked}}invisible{{end}}">{{svg "octicon-check"}}</span>
|
||||
<span class="text">
|
||||
{{ctx.AvatarUtils.Avatar . 20 "gt-mr-3"}}{{template "repo/search_name" .}}
|
||||
</span>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<div class="{{if not .HasError}}gt-hidden{{end}}" id="add-deploy-key-panel">
|
||||
<div class="{{if not .HasError}}gt-hidden{{end}} gt-mb-4" id="add-deploy-key-panel">
|
||||
<form class="ui form" action="{{.Link}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="field">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div id="issue-list" class="flex-list">
|
||||
<div id="issue-list" class="flex-list gt-pt-4">
|
||||
{{$approvalCounts := .ApprovalCounts}}
|
||||
{{range .Issues}}
|
||||
<div class="flex-item flex-item-baseline">
|
||||
|
@ -116,7 +116,7 @@
|
||||
<div class="flex-item-body">{{TimeSince .GetCreate $.locale}}</div>
|
||||
</div>
|
||||
<div class="flex-item-trailing">
|
||||
{{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32 "text grey gt-mr-2"}}
|
||||
{{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
@ -17,7 +17,9 @@
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "user/heatmap" .}}
|
||||
<div class="feeds">
|
||||
{{template "user/dashboard/feeds" .}}
|
||||
</div>
|
||||
{{else if eq .TabName "stars"}}
|
||||
<div class="stars">
|
||||
{{template "explore/repo_search" .}}
|
||||
|
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<div class="{{if not .HasGPGError}}gt-hidden{{end}}" id="add-gpg-key-panel">
|
||||
<div class="{{if not .HasGPGError}}gt-hidden{{end}} gt-mb-4" id="add-gpg-key-panel">
|
||||
<form class="ui form{{if .HasGPGError}} error{{end}}" action="{{.Link}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<input type="hidden" name="title" value="none">
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<div class="{{if not .HasSSHError}}gt-hidden{{end}}" id="add-ssh-key-panel">
|
||||
<div class="{{if not .HasSSHError}}gt-hidden{{end}} gt-mb-4" id="add-ssh-key-panel">
|
||||
<form class="ui form" action="{{.Link}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="field {{if .Err_Title}}error{{end}}">
|
||||
|
@ -51,8 +51,8 @@ func testSuccessfullEdit(t *testing.T, formData user_model.User) {
|
||||
|
||||
func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
|
||||
session := loginUser(t, "user1")
|
||||
csrf := GetCSRF(t, session, "/admin/users/"+strconv.Itoa(int(formData.ID))+"/edit")
|
||||
req := NewRequestWithValues(t, "POST", "/admin/users/"+strconv.Itoa(int(formData.ID))+"/edit", map[string]string{
|
||||
csrf := GetCSRF(t, session, "/admin/users/"+strconv.Itoa(int(formData.ID)))
|
||||
req := NewRequestWithValues(t, "POST", "/admin/users/"+strconv.Itoa(int(formData.ID)), map[string]string{
|
||||
"_csrf": csrf,
|
||||
"user_name": formData.Name,
|
||||
"login_name": formData.LoginName,
|
||||
@ -72,7 +72,7 @@ func TestAdminDeleteUser(t *testing.T) {
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
csrf := GetCSRF(t, session, "/admin/users/8/edit")
|
||||
csrf := GetCSRF(t, session, "/admin/users/8")
|
||||
req := NewRequestWithValues(t, "POST", "/admin/users/8/delete", map[string]string{
|
||||
"_csrf": csrf,
|
||||
})
|
||||
|
@ -6,8 +6,6 @@ package integration
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@ -39,9 +37,9 @@ func TestOrgTeamEmailInvite(t *testing.T) {
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
|
||||
csrf := GetCSRF(t, session, teamURL)
|
||||
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
|
||||
url := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
|
||||
csrf := GetCSRF(t, session, url)
|
||||
req := NewRequestWithValues(t, "POST", url+"/action/add", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"uid": "1",
|
||||
"uname": user.Email,
|
||||
@ -58,9 +56,9 @@ func TestOrgTeamEmailInvite(t *testing.T) {
|
||||
session = loginUser(t, user.Name)
|
||||
|
||||
// join the team
|
||||
inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
|
||||
csrf = GetCSRF(t, session, inviteURL)
|
||||
req = NewRequestWithValues(t, "POST", inviteURL, map[string]string{
|
||||
url = fmt.Sprintf("/org/invite/%s", invites[0].Token)
|
||||
csrf = GetCSRF(t, session, url)
|
||||
req = NewRequestWithValues(t, "POST", url, map[string]string{
|
||||
"_csrf": csrf,
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
@ -71,308 +69,3 @@ func TestOrgTeamEmailInvite(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
}
|
||||
|
||||
// Check that users are redirected to accept the invitation correctly after login
|
||||
func TestOrgTeamEmailInviteRedirectsExistingUser(t *testing.T) {
|
||||
if setting.MailService == nil {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
|
||||
isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, isMember)
|
||||
|
||||
// create the invite
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
|
||||
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, teamURL),
|
||||
"uid": "1",
|
||||
"uname": user.Email,
|
||||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// get the invite token
|
||||
invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, invites, 1)
|
||||
|
||||
// accept the invite
|
||||
inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/user/login?redirect_to=%s", url.QueryEscape(inviteURL)))
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
req = NewRequestWithValues(t, "POST", "/user/login", map[string]string{
|
||||
"_csrf": doc.GetCSRF(),
|
||||
"user_name": "user5",
|
||||
"password": "password",
|
||||
})
|
||||
for _, c := range resp.Result().Cookies() {
|
||||
req.AddCookie(c)
|
||||
}
|
||||
|
||||
resp = MakeRequest(t, req, http.StatusSeeOther)
|
||||
assert.Equal(t, inviteURL, test.RedirectURL(resp))
|
||||
|
||||
// complete the login process
|
||||
ch := http.Header{}
|
||||
ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
|
||||
cr := http.Request{Header: ch}
|
||||
|
||||
session = emptyTestSession(t)
|
||||
baseURL, err := url.Parse(setting.AppURL)
|
||||
assert.NoError(t, err)
|
||||
session.jar.SetCookies(baseURL, cr.Cookies())
|
||||
|
||||
// make the request
|
||||
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
|
||||
"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
isMember, err = organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
}
|
||||
|
||||
// Check that newly signed up users are redirected to accept the invitation correctly
|
||||
func TestOrgTeamEmailInviteRedirectsNewUser(t *testing.T) {
|
||||
if setting.MailService == nil {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
|
||||
|
||||
// create the invite
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
|
||||
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, teamURL),
|
||||
"uid": "1",
|
||||
"uname": "doesnotexist@example.com",
|
||||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// get the invite token
|
||||
invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, invites, 1)
|
||||
|
||||
// accept the invite
|
||||
inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
|
||||
"_csrf": doc.GetCSRF(),
|
||||
"user_name": "doesnotexist",
|
||||
"email": "doesnotexist@example.com",
|
||||
"password": "examplePassword!1",
|
||||
"retype": "examplePassword!1",
|
||||
})
|
||||
for _, c := range resp.Result().Cookies() {
|
||||
req.AddCookie(c)
|
||||
}
|
||||
|
||||
resp = MakeRequest(t, req, http.StatusSeeOther)
|
||||
assert.Equal(t, inviteURL, test.RedirectURL(resp))
|
||||
|
||||
// complete the signup process
|
||||
ch := http.Header{}
|
||||
ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
|
||||
cr := http.Request{Header: ch}
|
||||
|
||||
session = emptyTestSession(t)
|
||||
baseURL, err := url.Parse(setting.AppURL)
|
||||
assert.NoError(t, err)
|
||||
session.jar.SetCookies(baseURL, cr.Cookies())
|
||||
|
||||
// make the redirected request
|
||||
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
|
||||
"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// get the new user
|
||||
newUser, err := user_model.GetUserByName(db.DefaultContext, "doesnotexist")
|
||||
assert.NoError(t, err)
|
||||
|
||||
isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, newUser.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
}
|
||||
|
||||
// Check that users are redirected correctly after confirming their email
|
||||
func TestOrgTeamEmailInviteRedirectsNewUserWithActivation(t *testing.T) {
|
||||
if setting.MailService == nil {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
// enable email confirmation temporarily
|
||||
defer func(prevVal bool) {
|
||||
setting.Service.RegisterEmailConfirm = prevVal
|
||||
}(setting.Service.RegisterEmailConfirm)
|
||||
setting.Service.RegisterEmailConfirm = true
|
||||
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
|
||||
|
||||
// create the invite
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
|
||||
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, teamURL),
|
||||
"uid": "1",
|
||||
"uname": "doesnotexist@example.com",
|
||||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// get the invite token
|
||||
invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, invites, 1)
|
||||
|
||||
// accept the invite
|
||||
inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
|
||||
inviteResp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
|
||||
"_csrf": doc.GetCSRF(),
|
||||
"user_name": "doesnotexist",
|
||||
"email": "doesnotexist@example.com",
|
||||
"password": "examplePassword!1",
|
||||
"retype": "examplePassword!1",
|
||||
})
|
||||
for _, c := range inviteResp.Result().Cookies() {
|
||||
req.AddCookie(c)
|
||||
}
|
||||
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
user, err := user_model.GetUserByName(db.DefaultContext, "doesnotexist")
|
||||
assert.NoError(t, err)
|
||||
|
||||
ch := http.Header{}
|
||||
ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
|
||||
cr := http.Request{Header: ch}
|
||||
|
||||
session = emptyTestSession(t)
|
||||
baseURL, err := url.Parse(setting.AppURL)
|
||||
assert.NoError(t, err)
|
||||
session.jar.SetCookies(baseURL, cr.Cookies())
|
||||
|
||||
activateURL := fmt.Sprintf("/user/activate?code=%s", user.GenerateEmailActivateCode("doesnotexist@example.com"))
|
||||
req = NewRequestWithValues(t, "POST", activateURL, map[string]string{
|
||||
"password": "examplePassword!1",
|
||||
})
|
||||
|
||||
// use the cookies set by the signup request
|
||||
for _, c := range inviteResp.Result().Cookies() {
|
||||
req.AddCookie(c)
|
||||
}
|
||||
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
// should be redirected to accept the invite
|
||||
assert.Equal(t, inviteURL, test.RedirectURL(resp))
|
||||
|
||||
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
|
||||
"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
}
|
||||
|
||||
// Test that a logged-in user who navigates to the sign-up link is then redirected using redirect_to
|
||||
// For example: an invite may have been created before the user account was created, but they may be
|
||||
// accepting the invite after having created an account separately
|
||||
func TestOrgTeamEmailInviteRedirectsExistingUserWithLogin(t *testing.T) {
|
||||
if setting.MailService == nil {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
|
||||
isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, isMember)
|
||||
|
||||
// create the invite
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
|
||||
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, teamURL),
|
||||
"uid": "1",
|
||||
"uname": user.Email,
|
||||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// get the invite token
|
||||
invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, invites, 1)
|
||||
|
||||
// note: the invited user has logged in
|
||||
session = loginUser(t, "user5")
|
||||
|
||||
// accept the invite (note: this uses the sign_up url)
|
||||
inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
assert.Equal(t, inviteURL, test.RedirectURL(resp))
|
||||
|
||||
// make the request
|
||||
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
|
||||
"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
isMember, err = organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, isMember)
|
||||
}
|
||||
|
@ -42,10 +42,3 @@
|
||||
.admin .table th {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.admin-responsive-columns {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ a.label,
|
||||
background: var(--color-hover);
|
||||
}
|
||||
|
||||
.inline-code-block {
|
||||
.issue-title code {
|
||||
padding: 2px 4px;
|
||||
border-radius: var(--border-radius-medium);
|
||||
background-color: var(--color-markup-code-block);
|
||||
@ -506,6 +506,13 @@ a.label,
|
||||
border-right-color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* fix button enlarged vertically by svg icon */
|
||||
/* TODO: change to just `.small.button:has(svg)` but may have global side effects */
|
||||
.ui.action.input .small.button:has(svg) {
|
||||
padding-top: 7px !important;
|
||||
padding-bottom: 7px !important;
|
||||
}
|
||||
|
||||
.ui.menu,
|
||||
.ui.vertical.menu {
|
||||
background: var(--color-menu);
|
||||
@ -946,6 +953,14 @@ img.ui.avatar,
|
||||
filter: saturate(2);
|
||||
}
|
||||
|
||||
/* TODO: use gt-word-break instead */
|
||||
.dont-break-out {
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
.full.height {
|
||||
flex-grow: 1;
|
||||
padding-bottom: 80px;
|
||||
@ -1999,6 +2014,11 @@ a.ui.basic.label:hover {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* TODO: replace it with gt-invisible */
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.ui.segment,
|
||||
.ui.segments,
|
||||
.ui.attached.segment {
|
||||
|
@ -95,3 +95,10 @@
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
.feeds code {
|
||||
padding: 2px 4px;
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--color-markup-code-block);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
@ -236,6 +236,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.repository.file.list #repo-desc {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.repository.file.list .repo-path {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
@ -91,23 +91,11 @@
|
||||
border-top: 1px solid var(--color-secondary);
|
||||
}
|
||||
|
||||
/* Fomantic UI segment has default "padding: 1em", so here it removes the padding-top and padding-bottom accordingly.
|
||||
Developers could also use "flex-space-fitted" class to remove the first item's padding-top and the last item's padding-bottom */
|
||||
.flex-list.flex-space-fitted > .flex-item:first-child,
|
||||
/* Fomantic UI segment has default "padding: 1em", so here it removes the padding-top and padding-bottom accordingly */
|
||||
.ui.segment > .flex-list:first-child > .flex-item:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.flex-list.flex-space-fitted > .flex-item:last-child,
|
||||
.ui.segment > .flex-list:last-child > .flex-item:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* If there is a divider besides the flex-list, some padding/margin are not needs */
|
||||
.divider + .flex-list > .flex-item:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.flex-list + .divider {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ function initRepoDiffConversationForm() {
|
||||
|
||||
$form.closest('.conversation-holder').replaceWith($newConversationHolder);
|
||||
if ($form.closest('tr').data('line-type') === 'same') {
|
||||
$(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).addClass('gt-invisible');
|
||||
$(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).addClass('invisible');
|
||||
} else {
|
||||
$(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).addClass('gt-invisible');
|
||||
$(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).addClass('invisible');
|
||||
}
|
||||
$newConversationHolder.find('.dropdown').dropdown();
|
||||
initCompReactionSelector($newConversationHolder);
|
||||
|
@ -110,7 +110,7 @@ export function initRepoIssueSidebarList() {
|
||||
}
|
||||
filteredResponse.results.push({
|
||||
name: `#${issue.number} ${htmlEscape(issue.title)
|
||||
}<div class="text small gt-word-break">${htmlEscape(issue.repository.full_name)}</div>`,
|
||||
}<div class="text small dont-break-out">${htmlEscape(issue.repository.full_name)}</div>`,
|
||||
value: issue.id,
|
||||
});
|
||||
});
|
||||
@ -178,9 +178,9 @@ export function initRepoIssueCommentDelete() {
|
||||
const idx = $conversationHolder.data('idx');
|
||||
const lineType = $conversationHolder.closest('tr').data('line-type');
|
||||
if (lineType === 'same') {
|
||||
$(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).removeClass('gt-invisible');
|
||||
$(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).removeClass('invisible');
|
||||
} else {
|
||||
$(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).removeClass('gt-invisible');
|
||||
$(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).removeClass('invisible');
|
||||
}
|
||||
$conversationHolder.remove();
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ export function initRepoCommentForm() {
|
||||
|
||||
if ($(this).hasClass('checked')) {
|
||||
$(this).removeClass('checked');
|
||||
$(this).find('.octicon-check').addClass('gt-invisible');
|
||||
$(this).find('.octicon-check').addClass('invisible');
|
||||
if (hasUpdateAction) {
|
||||
if (!($(this).data('id') in items)) {
|
||||
items[$(this).data('id')] = {
|
||||
@ -164,7 +164,7 @@ export function initRepoCommentForm() {
|
||||
}
|
||||
} else {
|
||||
$(this).addClass('checked');
|
||||
$(this).find('.octicon-check').removeClass('gt-invisible');
|
||||
$(this).find('.octicon-check').removeClass('invisible');
|
||||
if (hasUpdateAction) {
|
||||
if (!($(this).data('id') in items)) {
|
||||
items[$(this).data('id')] = {
|
||||
@ -215,7 +215,7 @@ export function initRepoCommentForm() {
|
||||
|
||||
$(this).parent().find('.item').each(function () {
|
||||
$(this).removeClass('checked');
|
||||
$(this).find('.octicon-check').addClass('gt-invisible');
|
||||
$(this).find('.octicon-check').addClass('invisible');
|
||||
});
|
||||
|
||||
if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') {
|
||||
|
Loading…
x
Reference in New Issue
Block a user