Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions custom/options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ repository = Repository
organization = Organization
mirror = Mirror
issue_milestone = Milestone
new_repo = New Repository
new_repo = New Subject
new_migrate = New Migration
new_mirror = New Mirror
new_fork = New Repository Fork
new_fork = New Subject Fork
new_org = New Organization
new_project = New Project
new_project_column = New Column
Expand Down Expand Up @@ -1035,7 +1035,7 @@ visibility.private = Private
visibility.private_tooltip = Visible only to members of organizations you have joined

[repo]
new_repo_helper = A repository contains all project files, including revision history. Already hosting one elsewhere? <a href="%s">Migrate repository.</a>
new_repo_helper = <strong>You're about to create a new subject.</strong></br>Other users can edit and fork articles within a subject on Forkana. To avoid duplication, our moderation team will review your submission. You'll be notified once the subject is approved.
owner = Owner
commits.user = User
commits.code = Code
Expand All @@ -1054,6 +1054,7 @@ template = Template
template_select = Select a template.
template_helper = Make repository a template
template_description = Template repositories let users generate new repositories with the same directory structure, files, and optional settings.
template_requirements= By creating a new subject on Forkana, you acknowledge the following:<div class="ui bulleted list very relaxed"><div class="item"><strong>Open collaboration:</strong> Articles within this subject can be edited and forked by other users to support diverse perspectives and knowledge sharing.</div><div class="item"><strong>Originality required:</strong> This subject must not duplicate an existing one. Our moderation team will review your submission to ensure it's unique.</div><div class="item"><strong>Review process:</strong> Your subject will remain pending until approved. You’ll be notified once it is published and available for contributions.</div><div class="item"><strong>Community standards:</strong> All content must follow Forkana’s Community Guidelines for respectful, factual, and constructive collaboration.</div><div class="item"><strong>Location-based content restrictions:</strong> Some content may be restricted, illegal, or regulated in certain countries or regions. By creating or contributing to an article, you confirm that your content complies with the laws of your location. Abusive, harmful, or illegal content is strictly prohibited and may result in content removal or account suspension.</div></di><i>Forkana is a platform for open knowledge where subjects evolve through collective effort. Help us build a trustworthy and inclusive knowledge base.</div>
visibility = Visibility
visibility_description = Only the owner or the organization members if they have rights, will be able to see it.
visibility_helper = Make repository private
Expand Down
2 changes: 1 addition & 1 deletion custom/public/assets/css/base.custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
.ui.popup,
.ui.form .field > .ui.input > input,
.ui.form .field > .ui.input > textarea {
border-radius: var(--border-radius) !important;
border-radius: var(--border-radius);
}
240 changes: 240 additions & 0 deletions custom/templates/repo/create.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content repository new-repo">
<div class="ui container medium-width tw-mb-8">
<h3 class="ui top attached header">
{{ctx.Locale.Tr "new_repo"}}
</h3>
<div class="ui attached segment">
<div class="tw-w-[32rem] tw-mx-auto tw-py-8">
{{template "base/alert" .}}
{{template "repo/create_helper" .}}
<form class="ui form new-repo-form" action="{{.Link}}" method="post">
<div class="tw-w-[32rem] tw-mx-auto">
{{.CsrfTokenHtml}}
<div id="create-repo-error-message" class="ui negative message tw-text-center tw-hidden"></div>
<div class="required field {{if .Err_Owner}}error{{end}}">
<label>{{ctx.Locale.Tr "repo.owner"}}</label>
<div class="ui selection dropdown ellipsis-text-items" id="repo_owner_dropdown">
<input type="hidden" name="uid" value="{{.ContextUser.ID}}">
<span class="text"></span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"
{{if not .CanCreateRepoInDoer}}
data-create-repo-disallowed-prompt="{{ctx.Locale.TrN .MaxCreationLimit "repo.form.reach_limit_of_creation_1" "repo.form.reach_limit_of_creation_n" .MaxCreationLimitOfDoer}}"
{{end}}
>
{{ctx.AvatarUtils.Avatar .SignedUser 28 "mini"}}
{{.SignedUser.ShortName 40}}
</div>
{{range .Orgs}}
<div class="item" data-value="{{.ID}}" title="{{.Name}}">
{{ctx.AvatarUtils.Avatar . 28 "mini"}}
{{.ShortName 40}}
</div>
{{end}}
</div>
</div>
<!--<span class="help">{{ctx.Locale.Tr "repo.owner_helper"}}</span> -->
</div>

<div class="tw-hidden required field {{if .Err_RepoName}}error{{end}}">
<label for="repo_name">{{ctx.Locale.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" value="{{.repo_name}}" autofocus maxlength="100" required placeholder="{{ctx.Locale.Tr "repo.repo_name_auto_generated"}}">
<span class="help" data-help-for-repo-name>{{ctx.Locale.Tr "repo.repo_name_helper"}}</span>
<span class="help tw-hidden" data-help-for-repo-name=".profile">{{ctx.Locale.Tr "repo.repo_name_profile_public_hint"}}</span>
<span class="help tw-hidden" data-help-for-repo-name=".profile-private">{{ctx.Locale.Tr "repo.repo_name_profile_private_hint"}}</span>
</div>

<div class="required field {{if .Err_Subject}}error{{end}}">
<label for="subject">
{{ctx.Locale.Tr "repo.repo_subject"}}
<span data-tooltip-content="{{ctx.Locale.Tr "repo.repo_subject_helper"}}" data-tooltip-position="top center">
{{svg "octicon-info" 14 "info icon"}}
</span>
</label>
<input id="subject" name="subject" value="{{.subject}}" required maxlength="255" placeholder="{{ctx.Locale.Tr "repo.repo_subject_placeholder"}}">
</div>

<div class="tw-hidden field">
<label>{{ctx.Locale.Tr "repo.visibility"}}</label>
<div class="ui checkbox">
{{if .IsForcedPrivate}}
<input name="private" type="checkbox" checked disabled>
<label>{{ctx.Locale.Tr "repo.visibility_helper_forced"}}</label>
{{else}}
<input name="private" type="checkbox" {{if .private}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.visibility_helper"}}</label>
{{end}}
</div>
<span class="help">{{ctx.Locale.Tr "repo.visibility_description"}}</span>
</div>
<div class="tw-hidden field {{if .Err_Description}}error{{end}}">
<label for="description">{{ctx.Locale.Tr "repo.repo_desc"}}</label>
<textarea id="description" rows="2" name="description" placeholder="{{ctx.Locale.Tr "repo.repo_desc_helper"}}" maxlength="2048">{{.description}}</textarea>
</div>
<div class="tw-hidden field">
<label>{{ctx.Locale.Tr "repo.template"}}</label>
<div id="repo_template_search" class="ui search selection dropdown">
<input type="hidden" id="repo_template" name="repo_template" value="{{or .repo_template ""}}">
<div class="default text">{{.repo_template_name}}</div>
<div class="menu">
</div>
</div>
</div>

<div id="template_units" class="tw-hidden">
<div class="inline field">
<label>{{ctx.Locale.Tr "repo.template.items"}}</label>
<div class="ui checkbox">
<input name="git_content" type="checkbox" {{if .git_content}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.template.git_content"}}</label>
</div>
<div class="ui checkbox" {{if not .SignedUser.CanEditGitHook}}data-tooltip-content="{{ctx.Locale.Tr "repo.template.git_hooks_tooltip"}}"{{end}}>
<input name="git_hooks" type="checkbox" {{if .git_hooks}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.template.git_hooks"}}</label>
</div>
</div>
<div class="inline field">
<label></label>
<div class="ui checkbox">
<input name="webhooks" type="checkbox" {{if .webhooks}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.template.webhooks"}}</label>
</div>
<div class="ui checkbox">
<input name="topics" type="checkbox" {{if .topics}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.template.topics"}}</label>
</div>
</div>
<div class="inline field">
<label></label>
<div class="ui checkbox">
<input name="avatar" type="checkbox" {{if .avatar}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.template.avatar"}}</label>
</div>
<div class="ui checkbox">
<input name="labels" type="checkbox" {{if .labels}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.template.issue_labels"}}</label>
</div>
</div>
<div class="inline field">
<label></label>
<div class="ui checkbox">
<input name="protected_branch" type="checkbox" {{if .protected_branch}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.protected_branch"}}</label>
</div>
</div>
</div>

<div id="non_template">
<div class="tw-hidden field">
<label>{{ctx.Locale.Tr "repo.issue_labels"}}</label>
<div class="ui search selection dropdown">
<input type="hidden" name="issue_labels" value="{{.issueLabels}}">
<div class="default text">{{ctx.Locale.Tr "repo.issue_labels_helper"}}</div>
<div class="menu">
<div class="item" data-value="">{{ctx.Locale.Tr "repo.issue_labels_helper"}}</div>
{{range .LabelTemplateFiles}}
<div class="item" data-value="{{.DisplayName}}">{{.DisplayName}}<br><i>({{.Description}})</i></div>
{{end}}
</div>
</div>
</div>

<div class="tw-hidden field">
<label>.gitignore</label>
<div class="ui multiple search selection dropdown">
<input type="hidden" name="gitignores" value="{{.gitignores}}">
<div class="default text">{{ctx.Locale.Tr "repo.repo_gitignore_helper"}}</div>
<div class="menu">
{{range .Gitignores}}
<div class="item" data-value="{{.}}">{{.}}</div>
{{end}}
</div>
</div>
<span class="help">{{ctx.Locale.Tr "repo.repo_gitignore_helper_desc"}}</span>
</div>
<div class="tw-hidden field">
<label>{{ctx.Locale.Tr "repo.license"}}</label>
<div class="ui search selection dropdown">
<input type="hidden" name="license" value="{{.license}}">
<div class="default text">{{ctx.Locale.Tr "repo.license_helper"}}</div>
<div class="menu">
<div class="item" data-value="">{{ctx.Locale.Tr "repo.license_helper"}}</div>
{{range .Licenses}}
<div class="item" data-value="{{.}}">{{.}}</div>
{{end}}
</div>
</div>
<span class="help">{{ctx.Locale.Tr "repo.license_helper_desc" "https://choosealicense.com/"}}</span>
</div>

<div class="tw-hidden field">
<label>{{ctx.Locale.Tr "repo.readme"}}</label>
<div class="ui selection dropdown">
<input type="hidden" name="readme" value="{{.readme}}">
<div class="default text">{{ctx.Locale.Tr "repo.readme_helper"}}</div>
<div class="menu">
{{range .Readmes}}
<div class="item" data-value="{{.}}">{{.}}</div>
{{end}}
</div>
</div>
<span class="help">{{ctx.Locale.Tr "repo.readme_helper_desc"}}</span>
</div>
<div class="tw-hidden field">
<label></label>
<div class="ui checkbox" id="auto-init">
<input name="auto_init" type="checkbox" {{if .auto_init}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.auto_init"}}</label>
</div>
</div>
<div class="tw-hidden field">
<label for="default_branch">{{ctx.Locale.Tr "repo.default_branch"}}</label>
<input id="default_branch" name="default_branch" value="{{.default_branch}}" placeholder="{{.default_branch}}">
<span class="help">{{ctx.Locale.Tr "repo.default_branch_helper"}}</span>
</div>
<div class="tw-hidden field">
<label>{{ctx.Locale.Tr "repo.object_format"}}</label>
<div class="ui selection owner dropdown">
<input type="hidden" id="object_format_name" name="object_format_name" value="{{or .object_format_name .DefaultObjectFormat.Name}}" required>
<div class="default text">{{.DefaultObjectFormat.Name}}</div>
<div class="menu">
{{range .SupportedObjectFormats}}
<div class="item" data-value="{{.Name}}">{{.Name}}</div>
{{end}}
</div>
</div>
<span class="help">{{ctx.Locale.Tr "repo.object_format_helper"}}</span>
</div>
<div class="tw-hidden field">
<label>{{ctx.Locale.Tr "repo.template"}}</label>
<div class="ui checkbox">
<input name="template" type="checkbox">
<label>{{ctx.Locale.Tr "repo.template_helper"}}</label>
</div>
</div>

<div class="field tw-mt-8">
<div class="ui checkbox">
<input id="template_requirements" name="template_requirements" type="checkbox">
<label class="tw-text-xs tw-leading-5">{{ctx.Locale.Tr "repo.template_requirements"}}</label>
</div>
</div>
</div>
<br>
<div class="field tw-flex tw-justify-end tw-gap-2">
<label></label>
<button type="button" class="ui button" onclick="history.back(); return false;">
{{ctx.Locale.Tr "cancel"}}
</button>
<button id="create-repo-submit-button" class="ui primary button" disabled>
{{ctx.Locale.Tr "repo.create_repo"}}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
{{template "base/footer" .}}
2 changes: 2 additions & 0 deletions custom/templates/repo/create_helper.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<p class="ui">{{ctx.Locale.Tr "repo.new_repo_helper"}}</p>

4 changes: 2 additions & 2 deletions custom/templates/repo/editor/edit.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<div class="ui top attached header">
<div class="ui compact small menu small-menu-items repo-editor-menu">
<a class="active item" data-tab="write">{{svg "octicon-code"}} {{if .IsNewFile}}{{ctx.Locale.Tr "repo.editor.new_file"}}{{else}}{{ctx.Locale.Tr "repo.editor.edit_file"}}{{end}}</a>
<a class="item" data-tab="preview" data-preview-url="{{.Repository.Link}}/markup" data-preview-context-ref="{{.RepoLink}}/src/{{.RefTypeNameSubURL}}">{{svg "octicon-eye"}} {{ctx.Locale.Tr "preview"}}</a>
<a class="item" data-tab="preview" data-preview-url="{{.Repository.Link}}/markup" data-preview-context-ref="{{.RepoOperationsLink}}/src/{{.RefTypeNameSubURL}}">{{svg "octicon-eye"}} {{ctx.Locale.Tr "preview"}}</a>
{{if not .IsNewFile}}
<a class="item" data-tab="diff" hx-params="context,content" hx-vals='{"context":"{{.BranchLink}}"}' hx-include="#edit_area" hx-swap="innerHTML" hx-target=".tab[data-tab='diff']" hx-indicator=".tab[data-tab='diff']" hx-post="{{.RepoLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">{{svg "octicon-diff"}} {{ctx.Locale.Tr "repo.editor.preview_changes"}}</a>
<a class="item" data-tab="diff" hx-params="context,content" hx-vals='{"context":"{{.BranchLink}}"}' hx-include="#edit_area" hx-swap="innerHTML" hx-target=".tab[data-tab='diff']" hx-indicator=".tab[data-tab='diff']" hx-post="{{.RepoOperationsLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">{{svg "octicon-diff"}} {{ctx.Locale.Tr "repo.editor.preview_changes"}}</a>
{{end}}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions custom/templates/repo/watch_unwatch.tmpl
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<form class="flex-text-inline" hx-boost="true" hx-target="this" method="post" action="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}unwatch{{else}}watch{{end}}">
<form class="flex-text-inline" hx-boost="true" hx-target="this" method="post" action="{{$.RepoOperationsLink}}/action/{{if $.IsWatchingRepo}}unwatch{{else}}watch{{end}}">
<div class="ui labeled" {{if not $.IsSigned}}data-tooltip-content="{{ctx.Locale.Tr "repo.watch_guest_user"}}"{{end}}>
{{$buttonText := ctx.Locale.Tr "repo.watch"}}
{{if $.IsWatchingRepo}}{{$buttonText = ctx.Locale.Tr "repo.unwatch"}}{{end}}
<button type="submit" class="ui compact small basic button tw-bg-transparent tw-border-0"{{if not $.IsSigned}} disabled{{end}} aria-label="{{$buttonText}}">
{{svg "octicon-eye" 16 "tw-mr-1"}}
<span class="not-mobile tw-font-bold" aria-hidden="true">{{$buttonText}}</span>
</button>
<!-- <a hx-boost="false" class="ui basic label" href="{{.RepoLink}}/watchers">
<!-- <a hx-boost="false" class="ui basic label" href="{{.RepoOperationsLink}}/watchers">
{{CountFmt .Repository.NumWatches}}
</a> -->
</div>
Expand Down
2 changes: 1 addition & 1 deletion custom/templates/shared/repo/article.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<div class="tw-flex tw-items-center tw-justify-between tw-mb-4">
<div class="tw-flex tw-items-center tw-gap-2">
{{if .IsSigned}}
<form id="fork-form" action="{{.RepoLink}}/fork" method="get" style="display: inline;">
<form id="fork-form" action="{{.RepoOperationsLink}}/fork" method="get" style="display: inline;">
<button type="submit" class="ui button">
{{svg "octicon-repo-forked" 16 "tw-mr-1"}}
Fork
Expand Down
7 changes: 6 additions & 1 deletion custom/templates/shared/repo/edit.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@
{{.CsrfTokenHtml}}
<input type="hidden" name="last_commit" value="{{.LastCommitID}}">
<input type="hidden" name="tree_path" value="{{.ReadmeTreePath}}">

{{/* Required commit choice field - default to direct commit */}}
<input type="hidden" name="commit_choice" value="direct">
{{/* Optional commit message fields - will use default if empty */}}
<input type="hidden" name="commit_summary" value="">
<input type="hidden" name="commit_message" value="">

<div class="field">
<div class="tw-p-0">
<textarea id="edit_area" name="content" class="tw-hidden" data-id="repo-{{.Repository.Name}}-{{.ReadmeTreePath}}">{{.FileContent}}</textarea>
Expand Down
9 changes: 8 additions & 1 deletion models/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -662,13 +662,20 @@ func (repo *Repository) RepoPath() string {
return RepoPath(repo.OwnerName, repo.Name)
}

// Link returns the repository relative url
// Link returns the repository relative url for viewing articles
// Uses subject name if available, falls back to repository name
func (repo *Repository) Link() string {
subject := repo.GetSubject(context.Background())
return setting.AppSubURL + "/article/" + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(subject)
}

// OperationsLink returns the repository relative url for repository operations
// This is used for file editing, forking, settings, and other repository management operations
// It always uses the repository name, not the subject name
func (repo *Repository) OperationsLink() string {
return setting.AppSubURL + "/" + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(repo.Name)
}

// ComposeCompareURL returns the repository comparison URL
func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string {
return fmt.Sprintf("%s/%s/compare/%s...%s", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name), util.PathEscapeSegments(oldCommitID), util.PathEscapeSegments(newCommitID))
Expand Down
7 changes: 7 additions & 0 deletions routers/web/repo/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ func redirectForCommitChoice[T any](ctx *context.Context, parsed *preparedEditor
}
}

// Check if the request came from an article-based route
// If so, redirect back to the article view instead of the file view
if strings.HasPrefix(ctx.Req.URL.Path, "/article/") {
ctx.JSONRedirect(ctx.Repo.RepoLink)
return
}

// redirect to the newly updated file
redirectTo := util.URLJoin(ctx.Repo.RepoLink, "src/branch", util.PathEscapeSegments(parsed.NewBranchName), util.PathEscapeSegments(treePath))
ctx.JSONRedirect(redirectTo)
Expand Down
Loading
Loading