feat: capytal forgejo configuration
This commit is contained in:
2
capytal/TRADEMARK
Normal file
2
capytal/TRADEMARK
Normal file
@@ -0,0 +1,2 @@
|
||||
"Capytal", "Capytal Company", "Capytal Code", "Capytal Creators", the Capytal Logo,
|
||||
the Capytal Code Logo, are trademarks of Gustavo L. de Mello.
|
||||
5
capytal/default.nix
Normal file
5
capytal/default.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./forgejo
|
||||
];
|
||||
}
|
||||
BIN
capytal/forgejo/assets/icon.png
Normal file
BIN
capytal/forgejo/assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
288
capytal/forgejo/assets/icon.svg
Normal file
288
capytal/forgejo/assets/icon.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 200 KiB |
BIN
capytal/forgejo/assets/logo.png
Normal file
BIN
capytal/forgejo/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
288
capytal/forgejo/assets/logo.svg
Normal file
288
capytal/forgejo/assets/logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 200 KiB |
103
capytal/forgejo/default.nix
Normal file
103
capytal/forgejo/default.nix
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
config,
|
||||
inputs,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
...
|
||||
}:
|
||||
with builtins; let
|
||||
secrets = config.spacestation-secrets.lesser;
|
||||
|
||||
frappurccino-theme =
|
||||
readFile
|
||||
"${inputs.frappurccino-forgejo.packages.${pkgs.system}.default}/css/theme-frappurccino-mocha-sky.css";
|
||||
|
||||
cal-sans = pkgs.fetchzip {
|
||||
url = "https://github.com/calcom/font/releases/download/v1.0.0/CalSans_Semibold_v1.0.0.zip";
|
||||
stripRoot = false;
|
||||
hash = "sha256-JqU64JUgWimJgrKX3XYcml8xsvy//K7O5clNKJRGaTM=";
|
||||
};
|
||||
fonts-css = pkgs.writeText "custom.css" ''
|
||||
@font-face {
|
||||
family: 'Cal Sans';
|
||||
src:
|
||||
url('assets/fonts/CalSans-SemiBold.woff2') format('woff2'),
|
||||
url('assets/fonts/CalSans-SemiBold.woff') format('woff'),
|
||||
url('assets/fonts/CalSans-SemiBold.ttf') format('truetype');
|
||||
};
|
||||
'';
|
||||
in {
|
||||
imports = [
|
||||
../../modules/forgejo
|
||||
];
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.forgejo;
|
||||
actions = {
|
||||
enable = true;
|
||||
token = secrets.services.forgejo.actions-token;
|
||||
url = "https://forgejo.capytal.company";
|
||||
labels = secrets.services.forgejo.actions-labels;
|
||||
};
|
||||
customization = {
|
||||
assets = {
|
||||
"fonts" = {
|
||||
source = "${cal-sans}/fonts/webfonts";
|
||||
recursive = true;
|
||||
};
|
||||
"fonts.css" = {
|
||||
source = fonts-css;
|
||||
};
|
||||
"img/home-logo.png" = {
|
||||
source = ./assets/logo.png;
|
||||
};
|
||||
"img/home-logo.svg" = {
|
||||
source = ./assets/logo.svg;
|
||||
};
|
||||
};
|
||||
templates = {
|
||||
header = ''
|
||||
<link rel="stylesheet" type="text/css" href="assets/fonts.css">
|
||||
${readFile ./templates/custom/header.tmpl}
|
||||
'';
|
||||
home = ./templates/home.tmpl;
|
||||
};
|
||||
theme = {
|
||||
"frappurccino" = frappurccino-theme;
|
||||
};
|
||||
favicon.png = ./assets/icon.png;
|
||||
favicon.svg = ./assets/icon.svg;
|
||||
logo.png = ./assets/icon.png;
|
||||
logo.svg = ./assets/icon.svg;
|
||||
};
|
||||
# users = {
|
||||
# user1 = {
|
||||
# name = /. + config.sops.secrets."forgejo/user1/name".path;
|
||||
# password = /. + config.sops.secrets."forgejo/user1/password".path;
|
||||
# email = /. + config.sops.secrets."forgejo/user1/email".path;
|
||||
# admin = true;
|
||||
# };
|
||||
# };
|
||||
settings = {
|
||||
DEFAULT = {
|
||||
APP_NAME = "Capytal Code";
|
||||
};
|
||||
server = rec {
|
||||
HTTP_PORT = secrets.services.forgejo.port;
|
||||
DOMAIN = "forgejo.capytal.company";
|
||||
ROOT_URL = "https://${DOMAIN}";
|
||||
};
|
||||
admin = {
|
||||
DISABLE_REGULAR_ORG_CREATION = true;
|
||||
USER_DISABLED_FEATURES = "deletion manage_ssh_keys manage_gpg_keys";
|
||||
EXTERNAL_USER_DISABLED_FEATURES = "deletion manage_ssh_keys manage_gpg_keys";
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
};
|
||||
ui = {
|
||||
DEFAULT_THEME = "frappurccino";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
55
capytal/forgejo/templates/custom/header.tmpl
Normal file
55
capytal/forgejo/templates/custom/header.tmpl
Normal file
@@ -0,0 +1,55 @@
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=red-hat-display:300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i|roboto:100" rel="stylesheet" />
|
||||
<script src="/assets/js/htmx.js"></script>
|
||||
<script src="/assets/js/header.js" defer></script>
|
||||
<style type="text/css">
|
||||
:root * {
|
||||
--fonts-proportional: "Red Hat Display", "Noto Sans", "Liberation Sans", sans-serif, var(--fonts-emoji) !important;
|
||||
}
|
||||
@font-face {
|
||||
family: "Cal Sans";
|
||||
src:
|
||||
url('assets/fonts/CalSans-SemiBold.woff2') format('woff2'),
|
||||
url('assets/fonts/CalSans-SemiBold.woff') format('woff'),
|
||||
url('assets/fonts/CalSans-SemiBold.ttf') format('truetype');
|
||||
};
|
||||
</style>
|
||||
<style type="text/css">
|
||||
@keyframes enter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
.slide-enter-content > * {
|
||||
--stagger: 0;
|
||||
--delay: 150ms;
|
||||
--start: 0ms;
|
||||
animation: enter 0.5s both 1;
|
||||
animation-delay: calc(var(--start) + var(--stagger) * var(--delay));
|
||||
}
|
||||
.slide-enter-content > *:nth-child(1) { --stagger: 1; }
|
||||
.slide-enter-content > *:nth-child(2) { --stagger: 2; }
|
||||
.slide-enter-content > *:nth-child(3) { --stagger: 3; }
|
||||
.slide-enter-content > *:nth-child(4) { --stagger: 4; }
|
||||
.slide-enter-content > *:nth-child(5) { --stagger: 5; }
|
||||
.slide-enter-content > *:nth-child(6) { --stagger: 6; }
|
||||
.slide-enter-content > *:nth-child(7) { --stagger: 7; }
|
||||
.slide-enter-content > *:nth-child(8) { --stagger: 8; }
|
||||
.slide-enter-content > *:nth-child(9) { --stagger: 9; }
|
||||
.slide-enter-content > *:nth-child(10) { --stagger: 10; }
|
||||
.slide-enter-content > *:nth-child(11) { --stagger: 11; }
|
||||
.slide-enter-content > *:nth-child(12) { --stagger: 12; }
|
||||
.slide-enter-content > *:nth-child(13) { --stagger: 13; }
|
||||
.slide-enter-content > *:nth-child(14) { --stagger: 14; }
|
||||
.slide-enter-content > *:nth-child(15) { --stagger: 15; }
|
||||
.slide-enter-content > *:nth-child(16) { --stagger: 16; }
|
||||
.slide-enter-content > *:nth-child(17) { --stagger: 17; }
|
||||
.slide-enter-content > *:nth-child(18) { --stagger: 18; }
|
||||
.slide-enter-content > *:nth-child(19) { --stagger: 19; }
|
||||
.slide-enter-content > *:nth-child(20) { --stagger: 20; }
|
||||
</style>
|
||||
73
capytal/forgejo/templates/explore/repo_list.tmpl
Normal file
73
capytal/forgejo/templates/explore/repo_list.tmpl
Normal file
@@ -0,0 +1,73 @@
|
||||
<div class="flex-list slide-enter-content">
|
||||
{{range .Repos}}
|
||||
<div class="flex-item">
|
||||
<div class="flex-item-leading">
|
||||
{{template "repo/icon" .}}
|
||||
</div>
|
||||
<div class="flex-item-main">
|
||||
<div class="flex-item-header">
|
||||
<div class="flex-item-title">
|
||||
{{if and (or $.PageIsExplore $.PageIsProfileStarList) .Owner}}
|
||||
<a class="text primary name" href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a>/
|
||||
{{end}}
|
||||
<a class="text primary name" href="{{.Link}}">{{.Name}}</a>
|
||||
<span class="label-list">
|
||||
{{if .IsArchived}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.archived"}}</span>
|
||||
{{end}}
|
||||
{{if .IsPrivate}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.private"}}</span>
|
||||
{{else}}
|
||||
{{if .Owner.Visibility.IsPrivate}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.internal"}}</span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .IsTemplate}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.template"}}</span>
|
||||
{{end}}
|
||||
{{if eq .ObjectFormatName "sha256"}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.sha256"}}</span>
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-item-trailing muted-links">
|
||||
{{if .PrimaryLanguage}}
|
||||
<a class="flex-text-inline" href="?q={{$.Keyword}}&sort={{$.SortType}}&language={{.PrimaryLanguage.Language}}{{if $.TabName}}&tab={{$.TabName}}{{end}}">
|
||||
<i class="color-icon tw-mr-2" style="background-color: {{.PrimaryLanguage.Color}}"></i>
|
||||
{{.PrimaryLanguage.Language}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if not $.DisableStars}}
|
||||
<a class="flex-text-inline" href="{{.Link}}/stars" aria-label="{{ctx.Locale.TrN .NumStars "explore.stars_one" "explore.stars_few" .NumStars}}" {{if ge .NumStars 1000}}data-tooltip-content="{{.NumStars}}"{{end}}>
|
||||
{{svg "octicon-star" 16}}
|
||||
{{CountFmt .NumStars}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if not $.DisableForks}}
|
||||
<a class="flex-text-inline" href="{{.Link}}/forks" aria-label="{{ctx.Locale.TrN .NumForks "explore.forks_one" "explore.forks_few" .NumForks}}" {{if ge .NumForks 1000}}data-tooltip-content="{{.NumForks}}"{{end}}>
|
||||
{{svg "octicon-git-branch" 16}}
|
||||
{{CountFmt .NumForks}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{$description := .DescriptionHTML $.Context}}
|
||||
{{if $description}}
|
||||
<div class="flex-item-body">{{$description}}</div>
|
||||
{{end}}
|
||||
{{if .Topics}}
|
||||
<div class="label-list">
|
||||
{{range .Topics}}
|
||||
{{if ne . ""}}<a class="ui label" href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1">{{.}}</a>{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="flex-item-body">{{ctx.Locale.Tr "org.repo_updated" (TimeSinceUnix .UpdatedUnix ctx.Locale)}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div>
|
||||
{{ctx.Locale.Tr "search.no_results"}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
33
capytal/forgejo/templates/explore/user_list.tmpl
Normal file
33
capytal/forgejo/templates/explore/user_list.tmpl
Normal file
@@ -0,0 +1,33 @@
|
||||
<div class="flex-list slide-enter-content">
|
||||
{{range .Users}}
|
||||
<div class="flex-item tw-items-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)}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="flex-item">
|
||||
{{ctx.Locale.Tr "search.no_results"}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
51
capytal/forgejo/templates/home.tmpl
Normal file
51
capytal/forgejo/templates/home.tmpl
Normal file
@@ -0,0 +1,51 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}" class="page-content home">
|
||||
<div class="tw-mb-8 tw-px-8">
|
||||
<div class="center">
|
||||
<img class="logo" style="max-width:70%;max-height:100%;" src="{{AssetUrlPrefix}}/img/home-logo.svg" alt="{{ctx.Locale.Tr "logo"}}">
|
||||
<div class="hero">
|
||||
<!-- <h1 class="ui icon header title cal-sans">
|
||||
{{AppDisplayName}}
|
||||
</h1> -->
|
||||
<h2 style="font-family:'Cal Sans';">From dreams, to code.</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="ui stackable middle very relaxed page grid">
|
||||
<div class="eight wide center column">
|
||||
<h1 class="hero ui icon header">
|
||||
{{svg "octicon-flame"}} {{ctx.Locale.Tr "startpage.install"}}
|
||||
</h1>
|
||||
<p class="large">
|
||||
{{ctx.Locale.Tr "startpage.install_desc" "https://forgejo.org/download/#installation-from-binary" "https://forgejo.org/download/#container-image" "https://forgejo.org/download"}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
<h1 class="hero ui icon header">
|
||||
{{svg "octicon-device-desktop"}} {{ctx.Locale.Tr "startpage.platform"}}
|
||||
</h1>
|
||||
<p class="large">
|
||||
{{ctx.Locale.Tr "startpage.platform_desc" "https://go.dev/"}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui stackable middle very relaxed page grid">
|
||||
<div class="eight wide center column">
|
||||
<h1 class="hero ui icon header">
|
||||
{{svg "octicon-rocket"}} {{ctx.Locale.Tr "startpage.lightweight"}}
|
||||
</h1>
|
||||
<p class="large">
|
||||
{{ctx.Locale.Tr "startpage.lightweight_desc"}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
<h1 class="hero ui icon header">
|
||||
{{svg "octicon-code"}} {{ctx.Locale.Tr "startpage.license"}}
|
||||
</h1>
|
||||
<p class="large">
|
||||
{{ctx.Locale.Tr "startpage.license_desc" "https://forgejo.org/download" "https://codeberg.org/forgejo/forgejo"}}
|
||||
</p>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
37
capytal/forgejo/templates/org/header.tmpl
Normal file
37
capytal/forgejo/templates/org/header.tmpl
Normal file
@@ -0,0 +1,37 @@
|
||||
<div class="ui container tw-flex">
|
||||
{{ctx.AvatarUtils.Avatar .Org 100 "org-avatar"}}
|
||||
<div id="org-info" class="tw-flex tw-flex-col">
|
||||
<div class="ui header">
|
||||
<div style="font-family:'Cal Sans'" class="org-title">
|
||||
{{.Org.DisplayName}}
|
||||
<span class="org-visibility">
|
||||
{{if .Org.Visibility.IsLimited}}<span class="ui large basic horizontal label">{{ctx.Locale.Tr "org.settings.visibility.limited_shortname"}}</span>{{end}}
|
||||
{{if .Org.Visibility.IsPrivate}}<span class="ui large basic horizontal label">{{ctx.Locale.Tr "org.settings.visibility.private_shortname"}}</span>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<span class="tw-flex tw-items-center button-row tw-ml-auto tw-text-16 tw-whitespace-nowrap">
|
||||
{{if .EnableFeed}}
|
||||
<a class="ui basic label button tw-mr-0" href="{{.Org.HomeLink}}.rss" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">
|
||||
{{svg "octicon-rss" 24}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .IsSigned}}
|
||||
{{template "org/follow_unfollow" .}}
|
||||
{{end}}
|
||||
{{if .IsOrganizationMember}}
|
||||
<a class="ui basic button tw-mr-0" href="{{.OrgLink}}/dashboard">{{ctx.Locale.Tr "org.open_dashboard"}}</a>
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
{{if .RenderedDescription}}<div class="render-content markup">{{.RenderedDescription}}</div>{{end}}
|
||||
<div class="text light meta tw-mt-1">
|
||||
{{if .Org.Location}}<div class="flex-text-block">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>{{end}}
|
||||
{{if .Org.Website}}<div class="flex-text-block">{{svg "octicon-link"}} <a class="muted" target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
|
||||
{{if .IsSigned}}
|
||||
{{if .Org.Email}}<div class="flex-text-block">{{svg "octicon-mail"}} <a class="muted" href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></div>{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "org/menu" .}}
|
||||
164
capytal/forgejo/templates/repo/home.tmpl
Normal file
164
capytal/forgejo/templates/repo/home.tmpl
Normal file
@@ -0,0 +1,164 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content repository file list {{if .IsBlame}}blame{{end}}">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container slide-enter-content {{if .IsBlame}}fluid padded{{end}}">
|
||||
{{template "base/alert" .}}
|
||||
{{template "repo/code/recently_pushed_new_branches" .}}
|
||||
{{if and (not .HideRepoInfo) (not .IsBlame)}}
|
||||
<div class="repo-description">
|
||||
<div id="repo-desc" class="tw-break-anywhere tw-text-16">
|
||||
{{$description := .Repository.DescriptionHTML $.Context}}
|
||||
{{if $description}}<span class="description">{{$description | RenderCodeBlock}}</span>{{else}}<span class="no-description text-italic">{{ctx.Locale.Tr "repo.no_desc"}}</span>{{end}}
|
||||
{{if .Repository.Website}}<a class="link" href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}
|
||||
</div>
|
||||
<form class="ignore-dirty" action="{{.RepoLink}}/search/{{if .CodeIndexerDisabled}}{{.BranchNameSubURL}}{{end}}" method="get" data-test-tag="codesearch">
|
||||
<div class="ui small action input">
|
||||
<input name="q" value="{{.Keyword}}" placeholder="{{ctx.Locale.Tr "search.code_kind"}}">
|
||||
{{template "shared/search/button"}}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tw-flex tw-items-center tw-flex-wrap tw-gap-2 tw-my-2" id="repo-topics">
|
||||
{{/* it should match the code in issue-home.js */}}
|
||||
{{range .Topics}}<a class="repo-topic ui large label" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
|
||||
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<button id="manage_topic" class="btn interact-fg tw-text-12">{{ctx.Locale.Tr "repo.topic.manage_topics"}}</button>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}
|
||||
<div class="ui form tw-hidden tw-flex tw-gap-2 tw-my-2" id="topic_edit">
|
||||
<div class="ui fluid multiple search selection dropdown tw-flex-wrap tw-flex-1">
|
||||
<input type="hidden" name="topics" value="{{range $i, $v := .Topics}}{{.Name}}{{if Eval $i "+" 1 "<" (len $.Topics)}},{{end}}{{end}}">
|
||||
{{range .Topics}}
|
||||
{{/* keep the same layout as Fomantic UI generated labels */}}
|
||||
<a class="ui label transition visible tw-cursor-default tw-inline-block" data-value="{{.Name}}">{{.Name}}{{svg "octicon-x" 16 "delete icon"}}</a>
|
||||
{{end}}
|
||||
<div class="text"></div>
|
||||
</div>
|
||||
<div>
|
||||
<button class="ui basic button" id="cancel_topic_edit">{{ctx.Locale.Tr "cancel"}}</button>
|
||||
<button class="ui primary button" id="save_topic" data-link="{{.RepoLink}}/topics">{{ctx.Locale.Tr "save"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if RepoFlagsEnabled}}
|
||||
{{template "custom/repo_flag_banners" .}}
|
||||
{{if .SignedUser.IsAdmin}}
|
||||
{{template "repo/admin_flags" .}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .Repository.IsArchived}}
|
||||
<div class="ui warning message tw-text-center">
|
||||
{{if .Repository.ArchivedUnix.IsZero}}
|
||||
{{ctx.Locale.Tr "repo.archive.title"}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "repo.archive.title_date" (DateTime "long" .Repository.ArchivedUnix)}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "repo/sub_menu" .}}
|
||||
{{$n := len .TreeNames}}
|
||||
{{$l := Eval $n "-" 1}}
|
||||
{{$isHomepage := (eq $n 0)}}
|
||||
<div class="repo-button-row">
|
||||
<div class="tw-flex tw-items-center tw-gap-y-2">
|
||||
{{template "repo/branch_dropdown" dict "root" . "ContainerClasses" "tw-mr-1"}}
|
||||
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
|
||||
{{$cmpBranch := ""}}
|
||||
{{if ne .Repository.ID .BaseRepo.ID}}
|
||||
{{$cmpBranch = printf "%s/%s:" (.Repository.OwnerName|PathEscape) (.Repository.Name|PathEscape)}}
|
||||
{{end}}
|
||||
{{$cmpBranch = print $cmpBranch (.BranchName|PathEscapeSegments)}}
|
||||
{{$compareLink := printf "%s/compare/%s...%s" .BaseRepo.Link (.BaseRepo.DefaultBranch|PathEscapeSegments) $cmpBranch}}
|
||||
<a id="new-pull-request" role="button" class="ui compact basic button" href="{{$compareLink}}"
|
||||
data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}">
|
||||
{{svg "octicon-git-pull-request"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<!-- Show go to file and breadcrumbs if not on home page -->
|
||||
{{if $isHomepage}}
|
||||
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
|
||||
{{end}}
|
||||
|
||||
{{if and .CanWriteCode .IsViewBranch (not .Repository.IsMirror) (not .Repository.IsArchived) (not .IsViewFile)}}
|
||||
<button class="ui dropdown basic compact jump button tw-mr-1"{{if not .Repository.CanEnableEditor}} disabled{{end}}>
|
||||
{{ctx.Locale.Tr "repo.editor.add_file"}}
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<a class="item" href="{{.RepoLink}}/_new/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{ctx.Locale.Tr "repo.editor.new_file"}}
|
||||
</a>
|
||||
{{if .RepositoryUploadEnabled}}
|
||||
<a class="item" href="{{.RepoLink}}/_upload/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{ctx.Locale.Tr "repo.editor.upload_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item" href="{{.RepoLink}}/_diffpatch/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{ctx.Locale.Tr "repo.editor.patch"}}
|
||||
</a>
|
||||
</div>
|
||||
</button>
|
||||
{{end}}
|
||||
|
||||
{{if and $isHomepage (.Repository.IsTemplate)}}
|
||||
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
|
||||
{{ctx.Locale.Tr "repo.use_template"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if (not $isHomepage)}}
|
||||
<span class="breadcrumb repo-path tw-ml-1">
|
||||
<a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
|
||||
{{- range $i, $v := .TreeNames -}}
|
||||
<span class="breadcrumb-divider">/</span>
|
||||
{{- if eq $i $l -}}
|
||||
<span class="active section" title="{{$v}}">{{$v}}</span>
|
||||
{{- else -}}
|
||||
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
</span>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="tw-flex tw-items-center">
|
||||
<!-- Only show clone panel in repository home page -->
|
||||
{{if $isHomepage}}
|
||||
<div class="clone-panel ui action tiny input">
|
||||
{{template "repo/clone_buttons" .}}
|
||||
<button class="ui small jump dropdown icon button" data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}">
|
||||
{{svg "octicon-kebab-horizontal"}}
|
||||
<div class="menu">
|
||||
{{if not $.DisableDownloadSourceArchives}}
|
||||
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.download_zip"}}</a>
|
||||
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.download_tar"}}</a>
|
||||
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.download_bundle"}}</a>
|
||||
{{end}}
|
||||
{{if .CitationExist}}
|
||||
<a class="item" id="cite-repo-button">{{svg "octicon-cross-reference" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.cite_this_repo"}}</a>
|
||||
{{end}}
|
||||
{{range .OpenWithEditorApps}}
|
||||
<a class="item js-clone-url-editor" data-href-template="{{.OpenURL}}">{{.IconHTML}}{{ctx.Locale.Tr "repo.open_with_editor" .DisplayName}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</button>
|
||||
{{template "repo/clone_script" .}}{{/* the script will update `.js-clone-url` and related elements */}}
|
||||
</div>
|
||||
{{template "repo/cite/cite_modal" .}}
|
||||
{{end}}
|
||||
{{if and (not $isHomepage) (not .IsViewFile) (not .IsBlame)}}{{/* IsViewDirectory (not home), TODO: split the templates, avoid using "if" tricks */}}
|
||||
<a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
|
||||
{{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if .IsViewFile}}
|
||||
{{template "repo/view_file" .}}
|
||||
{{else if .IsBlame}}
|
||||
{{template "repo/blame" .}}
|
||||
{{else}}{{/* IsViewDirectory */}}
|
||||
{{template "repo/view_list" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
55
capytal/forgejo/templates/repo/issue/list.tmpl
Normal file
55
capytal/forgejo/templates/repo/issue/list.tmpl
Normal file
@@ -0,0 +1,55 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content repository issue-list">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container slide-enter-content">
|
||||
{{template "base/alert" .}}
|
||||
|
||||
{{if .PinnedIssues}}
|
||||
<div id="issue-pins" {{if .IsRepoAdmin}}data-is-repo-admin{{end}}>
|
||||
{{range .PinnedIssues}}
|
||||
<div class="issue-card tw-break-anywhere {{if $.IsRepoAdmin}}tw-cursor-grab{{end}}" data-move-url="{{$.Link}}/move_pin" data-issue-id="{{.ID}}">
|
||||
{{template "repo/issue/card" (dict "Issue" . "Page" $ "isPinnedIssueCard" true)}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="list-header list-header-issues">
|
||||
{{template "repo/issue/navbar" .}}
|
||||
{{template "repo/issue/search" .}}
|
||||
{{if not .Repository.IsArchived}}
|
||||
{{if .PageIsIssueList}}
|
||||
<a class="ui small primary button issue-list-new" href="{{.RepoLink}}/issues/new{{if .NewIssueChooseTemplate}}/choose{{end}}">{{ctx.Locale.Tr "repo.issues.new"}}</a>
|
||||
{{else}}
|
||||
<a class="ui small primary button new-pr-button issue-list-new{{if not .PullRequestCtx.Allowed}} disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.Repository.Link}}/compare/{{.Repository.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{ctx.Locale.Tr "repo.pulls.new"}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if not .PageIsIssueList}}
|
||||
<a class="ui small primary small button issue-list-new{{if not .PullRequestCtx.Allowed}} disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.PullRequestCtx.BaseRepo.Link}}/compare/{{.PullRequestCtx.BaseRepo.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{ctx.Locale.Tr "action.compare_commits_general"}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{template "repo/issue/filters" .}}
|
||||
|
||||
<div id="issue-actions" class="issue-list-toolbar tw-hidden">
|
||||
<div class="issue-list-toolbar-left">
|
||||
{{template "repo/issue/openclose" .}}
|
||||
<!-- Total Tracked Time -->
|
||||
{{if .TotalTrackedTime}}
|
||||
<div class="ui compact tiny secondary menu">
|
||||
<span class="item" data-tooltip-content='{{ctx.Locale.Tr "tracked_time_summary"}}'>
|
||||
{{svg "octicon-clock"}}
|
||||
{{.TotalTrackedTime | Sec2Time}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="issue-list-toolbar-right">
|
||||
{{template "repo/issue/filter_actions" .}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "shared/issuelist" dict "." . "listType" "repo"}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
163
capytal/forgejo/templates/shared/issuelist.tmpl
Normal file
163
capytal/forgejo/templates/shared/issuelist.tmpl
Normal file
@@ -0,0 +1,163 @@
|
||||
<div id="issue-list" class="flex-list slide-enter-content">
|
||||
{{$approvalCounts := .ApprovalCounts}}
|
||||
{{range .Issues}}
|
||||
<div class="flex-item">
|
||||
|
||||
<div class="flex-item-icon">
|
||||
{{if $.CanWriteIssuesOrPulls}}
|
||||
<input type="checkbox" autocomplete="off" class="issue-checkbox tw-mr-4" data-issue-id={{.ID}} aria-label="{{ctx.Locale.Tr "repo.issues.action_check"}} "{{.Title}}"">
|
||||
{{end}}
|
||||
{{template "shared/issueicon" .}}
|
||||
</div>
|
||||
|
||||
<div class="flex-item-main">
|
||||
<div class="flex-item-header">
|
||||
<div class="flex-item-title">
|
||||
<a class="tw-no-underline issue-title" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{RenderEmoji $.Context .Title | RenderCodeBlock}}</a>
|
||||
{{if .IsPull}}
|
||||
{{if (index $.CommitStatuses .PullRequest.ID)}}
|
||||
{{template "repo/commit_statuses" dict "Status" (index $.CommitLastStatus .PullRequest.ID) "Statuses" (index $.CommitStatuses .PullRequest.ID)}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
<span class="labels-list tw-ml-1">
|
||||
{{range .Labels}}
|
||||
<a href="?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}{{if ne $.listType "milestone"}}&milestone={{$.MilestoneID}}{{end}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}&fuzzy={{$.IsFuzzy}}{{if $.ShowArchivedLabels}}&archived=true{{end}}" rel="nofollow">{{RenderLabel $.Context ctx.Locale .}}</a>
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
{{if or .TotalTrackedTime .Assignees .NumComments}}
|
||||
<div class="flex-item-trailing">
|
||||
{{if .TotalTrackedTime}}
|
||||
<div class="text grey flex-text-block">
|
||||
{{svg "octicon-clock" 16}}
|
||||
{{.TotalTrackedTime | Sec2Time}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Assignees}}
|
||||
<div class="text grey">
|
||||
{{range .Assignees}}
|
||||
<a class="ui assignee tw-no-underline" href="{{.HomeLink}}" data-tooltip-content="{{.GetDisplayName}}">
|
||||
{{ctx.AvatarUtils.Avatar . 20}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .NumComments}}
|
||||
<div class="text grey">
|
||||
<a class="tw-no-underline muted flex-text-block" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">
|
||||
{{svg "octicon-comment" 16}}{{.NumComments}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
<a class="index" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">
|
||||
{{if eq $.listType "dashboard"}}
|
||||
{{.Repo.FullName}}#{{.Index}}
|
||||
{{else}}
|
||||
#{{.Index}}
|
||||
{{end}}
|
||||
</a>
|
||||
{{$timeStr := TimeSinceUnix .GetLastEventTimestamp ctx.Locale}}
|
||||
{{if .OriginalAuthor}}
|
||||
{{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor}}
|
||||
{{else if gt .Poster.ID 0}}
|
||||
{{ctx.Locale.Tr .GetLastEventLabel $timeStr .Poster.HomeLink .Poster.GetDisplayName}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .Poster.GetDisplayName}}
|
||||
{{end}}
|
||||
{{if .IsPull}}
|
||||
<div class="branches flex-text-inline">
|
||||
<div class="branch">
|
||||
<a href="{{.PullRequest.BaseRepo.Link}}/src/branch/{{PathEscapeSegments .PullRequest.BaseBranch}}">
|
||||
{{/* inline to remove the spaces between spans */}}
|
||||
{{if ne .RepoID .PullRequest.BaseRepoID}}<span class="truncated-name">{{.PullRequest.BaseRepo.OwnerName}}</span>:{{end}}<span class="truncated-name">{{.PullRequest.BaseBranch}}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{svg "gitea-double-chevron-left" 12}}
|
||||
{{if .PullRequest.HeadRepo}}
|
||||
<div class="branch">
|
||||
<a href="{{.PullRequest.HeadRepo.Link}}/src/branch/{{PathEscapeSegments .PullRequest.HeadBranch}}">
|
||||
{{/* inline to remove the spaces between spans */}}
|
||||
{{if ne .RepoID .PullRequest.HeadRepoID}}<span class="truncated-name">{{.PullRequest.HeadRepo.OwnerName}}</span>:{{end}}<span class="truncated-name">{{.PullRequest.HeadBranch}}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if and .Milestone (ne $.listType "milestone")}}
|
||||
<a class="milestone flex-text-inline tw-max-w-[300px]" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{.Repo.Link}}/milestone/{{.Milestone.ID}}"{{end}}>
|
||||
{{svg "octicon-milestone" 14}}
|
||||
<span class="gt-ellipsis">{{.Milestone.Name}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .Project}}
|
||||
<a class="project flex-text-inline tw-max-w-[300px]" href="{{.Project.Link ctx}}">
|
||||
{{svg .Project.IconName 14}}
|
||||
<span class="gt-ellipsis">{{.Project.Title}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .Ref}}
|
||||
<a class="ref flex-text-inline tw-max-w-[300px]" {{if $.RepoLink}}href="{{index $.IssueRefURLs .ID}}"{{else}}href="{{.Repo.Link}}{{index $.IssueRefURLs .ID}}"{{end}}>
|
||||
{{svg "octicon-git-branch" 14}}
|
||||
<span class="gt-ellipsis">{{index $.IssueRefEndNames .ID}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
{{$tasks := .GetTasks}}
|
||||
{{if gt $tasks 0}}
|
||||
{{$tasksDone := .GetTasksDone}}
|
||||
<span class="checklist flex-text-inline">
|
||||
{{svg "octicon-checklist" 14}}{{$tasksDone}} / {{$tasks}}
|
||||
<progress value="{{$tasksDone}}" max="{{$tasks}}"></progress>
|
||||
</span>
|
||||
{{end}}
|
||||
{{if ne .DeadlineUnix 0}}
|
||||
<span class="due-date flex-text-inline" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date"}}">
|
||||
<span{{if .IsOverdue}} class="text red"{{end}}>
|
||||
{{svg "octicon-calendar" 14}}
|
||||
{{DateTime "short" (.DeadlineUnix.FormatDate)}}
|
||||
</span>
|
||||
</span>
|
||||
{{end}}
|
||||
{{if .IsPull}}
|
||||
{{$approveOfficial := call $approvalCounts .ID "approve"}}
|
||||
{{$rejectOfficial := call $approvalCounts .ID "reject"}}
|
||||
{{$waitingOfficial := call $approvalCounts .ID "waiting"}}
|
||||
{{if gt $approveOfficial 0}}
|
||||
<span class="approvals green flex-text-inline">
|
||||
{{svg "octicon-check" 14}}
|
||||
{{ctx.Locale.TrN $approveOfficial "repo.pulls.approve_count_1" "repo.pulls.approve_count_n" $approveOfficial}}
|
||||
</span>
|
||||
{{end}}
|
||||
{{if gt $rejectOfficial 0}}
|
||||
<span class="rejects red flex-text-inline">
|
||||
{{svg "octicon-diff" 14}}
|
||||
{{ctx.Locale.TrN $rejectOfficial "repo.pulls.reject_count_1" "repo.pulls.reject_count_n" $rejectOfficial}}
|
||||
</span>
|
||||
{{end}}
|
||||
{{if gt $waitingOfficial 0}}
|
||||
<span class="waiting flex-text-inline">
|
||||
{{svg "octicon-eye" 14}}
|
||||
{{ctx.Locale.TrN $waitingOfficial "repo.pulls.waiting_count_1" "repo.pulls.waiting_count_n" $waitingOfficial}}
|
||||
</span>
|
||||
{{end}}
|
||||
{{if and (not .PullRequest.HasMerged) .PullRequest.ConflictedFiles}}
|
||||
<span class="conflicting flex-text-inline">
|
||||
{{svg "octicon-x" 14}}
|
||||
{{ctx.Locale.TrN (len .PullRequest.ConflictedFiles) "repo.pulls.num_conflicting_files_1" "repo.pulls.num_conflicting_files_n" (len .PullRequest.ConflictedFiles)}}
|
||||
</span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .IssueIndexerUnavailable}}
|
||||
<div class="ui error message">
|
||||
<p>{{ctx.Locale.Tr "search.keyword_search_unavailable"}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{template "base/paginate" .}}
|
||||
127
capytal/forgejo/templates/user/dashboard/feeds.tmpl
Normal file
127
capytal/forgejo/templates/user/dashboard/feeds.tmpl
Normal file
@@ -0,0 +1,127 @@
|
||||
<div id="activity-feed" class="flex-list slide-enter-content">
|
||||
{{range .Feeds}}
|
||||
<div class="flex-item">
|
||||
<div class="flex-item-leading">
|
||||
{{ctx.AvatarUtils.AvatarByAction .}}
|
||||
</div>
|
||||
<div class="flex-item-main tw-gap-2">
|
||||
<div>
|
||||
{{if gt .ActUser.ID 0}}
|
||||
<a href="{{AppSubUrl}}/{{(.GetActUserName ctx) | PathEscape}}" title="{{.GetActDisplayNameTitle ctx}}">{{.GetActDisplayName ctx}}</a>
|
||||
{{else}}
|
||||
{{.ShortActUserName ctx}}
|
||||
{{end}}
|
||||
{{if .GetOpType.InActions "create_repo"}}
|
||||
{{ctx.Locale.Tr "action.create_repo" (.GetRepoLink ctx) (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "rename_repo"}}
|
||||
{{ctx.Locale.Tr "action.rename_repo" .GetContent (.GetRepoLink ctx) (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "commit_repo"}}
|
||||
{{if .Content}}
|
||||
{{ctx.Locale.Tr "action.commit_repo" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "action.create_branch" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}}
|
||||
{{end}}
|
||||
{{else if .GetOpType.InActions "create_issue"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.create_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "create_pull_request"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.create_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "transfer_repo"}}
|
||||
{{ctx.Locale.Tr "action.transfer_repo" .GetContent (.GetRepoLink ctx) (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "push_tag"}}
|
||||
{{ctx.Locale.Tr "action.push_tag" (.GetRepoLink ctx) (.GetRefLink ctx) .GetTag (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "comment_issue"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.comment_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "merge_pull_request"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.merge_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "close_issue"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.close_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "reopen_issue"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.reopen_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "close_pull_request"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.close_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "reopen_pull_request"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.reopen_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "delete_tag"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.delete_tag" (.GetRepoLink ctx) .GetTag (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "delete_branch"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.delete_branch" (.GetRepoLink ctx) .GetBranch (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "mirror_sync_push"}}
|
||||
{{ctx.Locale.Tr "action.mirror_sync_push" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "mirror_sync_create"}}
|
||||
{{ctx.Locale.Tr "action.mirror_sync_create" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "mirror_sync_delete"}}
|
||||
{{ctx.Locale.Tr "action.mirror_sync_delete" (.GetRepoLink ctx) .GetBranch (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "approve_pull_request"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.approve_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "reject_pull_request"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.reject_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "comment_pull"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{ctx.Locale.Tr "action.comment_pull" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}}
|
||||
{{else if .GetOpType.InActions "publish_release"}}
|
||||
{{$linkText := .Content | RenderEmoji $.Context}}
|
||||
{{ctx.Locale.Tr "action.publish_release" (.GetRepoLink ctx) (printf "%s/releases/tag/%s" (.GetRepoLink ctx) .GetTag) (.ShortRepoPath ctx) $linkText}}
|
||||
{{else if .GetOpType.InActions "review_dismissed"}}
|
||||
{{$index := index .GetIssueInfos 0}}
|
||||
{{$reviewer := index .GetIssueInfos 1}}
|
||||
{{ctx.Locale.Tr "action.review_dismissed" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx) $reviewer}}
|
||||
{{end}}
|
||||
{{TimeSince .GetCreate ctx.Locale}}
|
||||
</div>
|
||||
{{if .GetOpType.InActions "commit_repo" "mirror_sync_push"}}
|
||||
{{$push := ActionContent2Commits .}}
|
||||
{{$repoLink := (.GetRepoLink ctx)}}
|
||||
{{$repo := .Repo}}
|
||||
<div class="tw-flex tw-flex-col tw-gap-1">
|
||||
{{range $push.Commits}}
|
||||
{{$commitLink := printf "%s/commit/%s" $repoLink .Sha1}}
|
||||
<div class="flex-text-block">
|
||||
<img class="ui avatar" src="{{$push.AvatarLink $.Context .AuthorEmail}}" title="{{.AuthorName}}" width="16" height="16">
|
||||
<a class="ui sha label" href="{{$commitLink}}">{{ShortSha .Sha1}}</a>
|
||||
<span class="text truncate">
|
||||
{{RenderCommitMessage $.Context .Message ($repo.ComposeMetas ctx)}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if and (gt $push.Len 1) $push.CompareURL}}
|
||||
<a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{ctx.Locale.Tr "action.compare_commits" $push.Len}} »</a>
|
||||
{{end}}
|
||||
{{else if .GetOpType.InActions "create_issue"}}
|
||||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span>
|
||||
{{else if .GetOpType.InActions "create_pull_request"}}
|
||||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span>
|
||||
{{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}}
|
||||
<a href="{{.GetCommentLink ctx}}" class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</a>
|
||||
{{$comment := index .GetIssueInfos 1}}
|
||||
{{if $comment}}
|
||||
<div class="markup tw-text-14">{{RenderMarkdownToHtml ctx $comment}}</div>
|
||||
{{end}}
|
||||
{{else if .GetOpType.InActions "merge_pull_request"}}
|
||||
<div class="flex-item-body text black">{{index .GetIssueInfos 1}}</div>
|
||||
{{else if .GetOpType.InActions "close_issue" "reopen_issue" "close_pull_request" "reopen_pull_request"}}
|
||||
<span class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</span>
|
||||
{{else if .GetOpType.InActions "pull_review_dismissed"}}
|
||||
<div class="flex-item-body text black">{{ctx.Locale.Tr "action.review_dismissed_reason"}}</div>
|
||||
<div class="flex-item-body text black">{{index .GetIssueInfos 2 | RenderEmoji $.Context}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-item-trailing">
|
||||
{{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32 "text grey tw-mr-1"}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "base/paginate" .}}
|
||||
</div>
|
||||
@@ -3,14 +3,16 @@
|
||||
lib,
|
||||
inputs,
|
||||
pkgs,
|
||||
pkgs-unstable,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
inputs.dot013-environment.nixosModules.default
|
||||
./hardware-configuration.nix
|
||||
./services
|
||||
./modules
|
||||
./secrets.nix
|
||||
./capytal
|
||||
];
|
||||
|
||||
programs.nh.enable = true;
|
||||
@@ -19,7 +21,11 @@
|
||||
profiles.locale.enable = true;
|
||||
|
||||
home-manager.backupFileExtension = "backup~";
|
||||
home-manager.extraSpecialArgs = {inherit inputs;};
|
||||
home-manager.extraSpecialArgs = {
|
||||
inherit inputs;
|
||||
inherit pkgs;
|
||||
inherit pkgs-unstable;
|
||||
};
|
||||
users.users."guz" = {
|
||||
shell = pkgs.zsh;
|
||||
hashedPasswordFile = builtins.toString config.sops.secrets."guz/password".path;
|
||||
|
||||
80
flake.lock
generated
80
flake.lock
generated
@@ -2,14 +2,16 @@
|
||||
"nodes": {
|
||||
"dot013-environment": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725634253,
|
||||
"narHash": "sha256-GbBtwR/rfu9nmfP9O87XitYRbJEQgxkxvHe6nzcHrYA=",
|
||||
"lastModified": 1725918868,
|
||||
"narHash": "sha256-XYZiGWFT8r9GrIIHyhN/3dYbkUCcAy4v5PyKYUzPOiI=",
|
||||
"owner": "dot013",
|
||||
"repo": "environment",
|
||||
"rev": "91185158c5aca939661a128c50d1df55417e8dd7",
|
||||
"rev": "f340ff699bd735d617148cd023885f1acd5b615f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -18,6 +20,48 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"frappurccino-forgejo": {
|
||||
"inputs": {
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726239025,
|
||||
"narHash": "sha256-9INgfUmWSE4kT/0niKvpqhuesP4FR7lBplaKfHm/q+g=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "b24a35a56013a760515198fae58ce8711a22d05c",
|
||||
"revCount": 54,
|
||||
"type": "git",
|
||||
"url": "file:///home/guz/.projects/capytal/frappurccino-forgejo"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "file:///home/guz/.projects/capytal/frappurccino-forgejo"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"frappurccino-forgejo",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -61,16 +105,16 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1724224976,
|
||||
"narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=",
|
||||
"lastModified": 1725930920,
|
||||
"narHash": "sha256-RVhD9hnlTT2nJzPHlAqrWqCkA7T6CYrP41IoVRkciZM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c374d94f1536013ca8e92341b540eba4c22f9c62",
|
||||
"rev": "44a71ff39c182edaf25a7ace5c9454e7cba2c658",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -91,18 +135,18 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1725693463,
|
||||
"narHash": "sha256-ZPzhebbWBOr0zRWW10FfqfbJlan3G96/h3uqhiFqmwg=",
|
||||
"lastModified": 1726062873,
|
||||
"narHash": "sha256-IiA3jfbR7K/B5+9byVi9BZGWTD4VSbWe8VLpp9B/iYk=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "68e7dce0a6532e876980764167ad158174402c6f",
|
||||
"rev": "4f807e8940284ad7925ebd0a0993d2a1791acb2f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-24.05",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -110,9 +154,11 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"dot013-environment": "dot013-environment",
|
||||
"frappurccino-forgejo": "frappurccino-forgejo",
|
||||
"home-manager": "home-manager",
|
||||
"nix-index-database": "nix-index-database",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"sops-nix": "sops-nix"
|
||||
}
|
||||
},
|
||||
@@ -124,11 +170,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725765163,
|
||||
"narHash": "sha256-rfd2c47iVSFI6bRYy5l8wRijRBaYDeU7dM8XCDUGqlA=",
|
||||
"lastModified": 1726218807,
|
||||
"narHash": "sha256-z7CoWbSOtsOz8TmRKDnobURkKfv6nPZCo3ayolNuQGc=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "b68757cd2c3fa66d6ccaa0d046ce42a9324e0070",
|
||||
"rev": "f30b1bac192e2dc252107ac8a59a03ad25e1b96e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
|
||||
dot013-environment.url = "github:dot013/environment";
|
||||
dot013-environment.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
|
||||
frappurccino-forgejo = {
|
||||
url = "git+file:///home/guz/.projects/capytal/frappurccino-forgejo";
|
||||
# url = "git+https://forgejo.capytal.company/capytal/frappurccino-forgejo";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
outputs = {
|
||||
nixpkgs,
|
||||
|
||||
136
modules/forgejo/customization.nix
Normal file
136
modules/forgejo/customization.nix
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
config,
|
||||
inputs,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.forgejo.customization;
|
||||
forgejo = config.services.forgejo;
|
||||
|
||||
fileType = with lib.types; either str (either lines path);
|
||||
in {
|
||||
imports = [
|
||||
inputs.home-manager.nixosModules.default
|
||||
];
|
||||
options.services.forgejo.customization = with lib;
|
||||
with lib.types; {
|
||||
enable = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
assets = mkOption {
|
||||
type = attrsOf anything;
|
||||
default = {};
|
||||
};
|
||||
templates = {
|
||||
header = mkOption {
|
||||
type = nullOr fileType;
|
||||
default = null;
|
||||
};
|
||||
home = mkOption {
|
||||
type = nullOr fileType;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
logo.svg = mkOption {
|
||||
type = nullOr fileType;
|
||||
default = null;
|
||||
};
|
||||
logo.png = mkOption {
|
||||
type = nullOr fileType;
|
||||
default = null;
|
||||
};
|
||||
favicon.svg = mkOption {
|
||||
type = nullOr fileType;
|
||||
default = null;
|
||||
};
|
||||
favicon.png = mkOption {
|
||||
type = nullOr fileType;
|
||||
default = null;
|
||||
};
|
||||
theme = mkOption {
|
||||
type = nullOr (either (attrsOf fileType) fileType);
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
config = with lib;
|
||||
mkIf cfg.enable {
|
||||
home-manager.users."${forgejo.user}" = let
|
||||
home = {
|
||||
lib,
|
||||
forgejoConfig,
|
||||
customization,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
with builtins; {
|
||||
imports = [];
|
||||
|
||||
programs.home-manager.enable = true;
|
||||
|
||||
home.username = "${forgejoConfig.user}";
|
||||
home.homeDirectory = "${forgejoConfig.stateDir}";
|
||||
|
||||
home.file = let
|
||||
fileTypeToHomeFile = theme:
|
||||
if (isString theme)
|
||||
then {
|
||||
text = theme;
|
||||
}
|
||||
else {source = theme;};
|
||||
assetsDir = "${forgejoConfig.customDir}/public/assets";
|
||||
templatesDir = "${forgejoConfig.customDir}/templates";
|
||||
in
|
||||
{
|
||||
"${templatesDir}/custom/header.tmpl" =
|
||||
mkIf (!(isNull customization.templates.header))
|
||||
(fileTypeToHomeFile customization.templates.header);
|
||||
|
||||
"${templatesDir}/home.tmpl" =
|
||||
mkIf (!(isNull customization.templates.home))
|
||||
(fileTypeToHomeFile customization.templates.home);
|
||||
|
||||
"${assetsDir}/img/logo.svg" =
|
||||
mkIf (!(isNull customization.logo.svg))
|
||||
(fileTypeToHomeFile customization.logo.svg);
|
||||
|
||||
"${assetsDir}/img/logo.png" =
|
||||
mkIf (!(isNull customization.logo.png))
|
||||
(fileTypeToHomeFile customization.logo.png);
|
||||
|
||||
"${assetsDir}/img/favicon.svg" =
|
||||
mkIf (!(isNull customization.favicon.svg))
|
||||
(fileTypeToHomeFile customization.favicon.svg);
|
||||
|
||||
"${assetsDir}/img/favicon.png" =
|
||||
mkIf (!(isNull customization.favicon.png))
|
||||
(fileTypeToHomeFile customization.favicon.png);
|
||||
}
|
||||
// (lib.attrsets.mapAttrs'
|
||||
(n: v: lib.attrsets.nameValuePair "${assetsDir}/${n}" v)
|
||||
customization.assets)
|
||||
// (
|
||||
if (!(isNull customization.theme))
|
||||
then
|
||||
if isAttrs customization.theme
|
||||
then
|
||||
(lib.attrsets.mapAttrs'
|
||||
(n: v:
|
||||
lib.attrsets.nameValuePair "${assetsDir}/css/theme-${n}.css" (fileTypeToHomeFile v))
|
||||
customization.theme)
|
||||
else {
|
||||
"${assetsDir}/css/theme-custom.css" = fileTypeToHomeFile customization.theme;
|
||||
}
|
||||
else {}
|
||||
);
|
||||
home.stateVersion = "23.11"; # DO NOT CHANGE
|
||||
};
|
||||
in
|
||||
home {
|
||||
inherit lib;
|
||||
forgejoConfig = forgejo;
|
||||
customization = cfg;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,57 +2,94 @@
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.forgejo;
|
||||
yamlFormat = pkgs.formats.yaml {};
|
||||
users = builtins.attrValues (builtins.mapAttrs
|
||||
(username: info: {
|
||||
name =
|
||||
if isNull info.name
|
||||
then username
|
||||
else info.name;
|
||||
email = info.email;
|
||||
password = info.password;
|
||||
admin = info.admin;
|
||||
})
|
||||
cfg.users);
|
||||
initList = l: lib.strings.concatStringsSep "," l;
|
||||
|
||||
initList = l: (lib.strings.concatStringsSep "," l);
|
||||
|
||||
customThemes = with builtins;
|
||||
with lib.attrsets;
|
||||
if !(isNull cfg.customization.theme)
|
||||
then
|
||||
(
|
||||
if (isAttrs cfg.customization.theme)
|
||||
then (mapAttrsToList (n: v: n) cfg.customization.theme)
|
||||
else ["custom"]
|
||||
)
|
||||
else [];
|
||||
in {
|
||||
imports = [];
|
||||
imports = [
|
||||
./users.nix
|
||||
./customization.nix
|
||||
];
|
||||
options.services.forgejo = with lib;
|
||||
with lib.types; {
|
||||
handleUndeclaredUsers = mkOption {
|
||||
settings = {
|
||||
DEFAULT = {
|
||||
APP_NAME = mkOption {
|
||||
type = str;
|
||||
default = "Forgejo: Beyond code. We forge.";
|
||||
};
|
||||
};
|
||||
actions = {
|
||||
ENABLED = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
default = cfg.actions.enable;
|
||||
};
|
||||
users = mkOption {
|
||||
type = attrsOf (submodule ({
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
with lib.types; {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = nullOr (either str path);
|
||||
default = null;
|
||||
};
|
||||
password = mkOption {
|
||||
type = either str path;
|
||||
};
|
||||
email = mkOption {
|
||||
type = either str path;
|
||||
};
|
||||
admin = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
DEFAULT_ACTIONS_URL = mkOption {
|
||||
type = str;
|
||||
default = "https://localhost:${toString cfg.settings.server.HTTP_PORT}";
|
||||
};
|
||||
};
|
||||
repository = {
|
||||
DEFAULT_REPO_UNITS = mkOption {
|
||||
type = listOf str;
|
||||
default = ["repo.code"];
|
||||
apply = t: initList t;
|
||||
};
|
||||
DISABLED_REPO_UNITS = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
apply = t:
|
||||
initList (t
|
||||
++ (
|
||||
if !cfg.actions.enable
|
||||
then ["repo.actions"]
|
||||
else []
|
||||
));
|
||||
};
|
||||
};
|
||||
ui = {
|
||||
DEFAULT_THEME = mkOption {
|
||||
type = str;
|
||||
default = with builtins;
|
||||
if (!(isNull cfg.customization.theme))
|
||||
then elemAt customThemes 0
|
||||
else "forgejo-auto";
|
||||
};
|
||||
THEMES = mkOption {
|
||||
type = listOf str;
|
||||
default = [
|
||||
"forgejo-auto"
|
||||
"forgejo-light"
|
||||
"forgejo-dark"
|
||||
"gitea-auto"
|
||||
"gitea-light"
|
||||
"gitea-dark"
|
||||
"forgejo-auto-deuteranopania-protanopia"
|
||||
"forgejo-light-deuteranopania-protanopia"
|
||||
"forgejo-dark-deuteranopania-protanopia"
|
||||
"forgejo-auto-tritanopia"
|
||||
"forgejo-light-tritanopia"
|
||||
"forgejo-dark-tritanopia"
|
||||
];
|
||||
apply = t: let
|
||||
list = t ++ customThemes;
|
||||
in
|
||||
initList list;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = {};
|
||||
};
|
||||
actions = {
|
||||
enable = mkOption {
|
||||
@@ -100,27 +137,7 @@ in {
|
||||
|
||||
services.forgejo = {
|
||||
user = mkDefault "git";
|
||||
group = mkDefault cfg.user;
|
||||
settings = {
|
||||
DEFAULT = {
|
||||
APP_NAME = mkDefault "Forgejo: Beyond coding. We forge.";
|
||||
};
|
||||
actions = {
|
||||
ENABLED = mkDefault cfg.actions.enable;
|
||||
DEFAULT_ACTIONS_URL = mkDefault "http://localhost:${toString cfg.settings.server.HTTP_PORT}";
|
||||
};
|
||||
repository = {
|
||||
DEFAULT_REPO_UNITS = mkDefault (initList [
|
||||
"repo.code"
|
||||
]);
|
||||
DISABLED_REPO_UNITS = mkIf (!cfg.actions.enable) (mkDefault (initList [
|
||||
"repo.actions"
|
||||
]));
|
||||
};
|
||||
service = {
|
||||
# DISABLE_REGISTRARION = mkDefault true;
|
||||
};
|
||||
};
|
||||
group = cfg.user;
|
||||
};
|
||||
|
||||
virtualisation.docker.enable = mkIf cfg.actions.enable (mkDefault true);
|
||||
@@ -142,64 +159,5 @@ in {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services."forgejo-users-setup" = with builtins; {
|
||||
script = ''
|
||||
function gum() { ${pkgs.gum}/bin/gum "$@"; }
|
||||
function forgejo() {
|
||||
# local config_file="${toString cfg.stateDir}/custom/conf/app.ini";
|
||||
# touch $config_file
|
||||
${cfg.package}/bin/gitea \
|
||||
--work-path ${cfg.stateDir} \
|
||||
"$@"
|
||||
}
|
||||
function fjuser() { forgejo admin user "$@"; }
|
||||
function awk() { ${pkgs.gawk}/bin/awk "$@"; }
|
||||
|
||||
handle_undeclared_users="${
|
||||
if cfg.handleUndeclaredUsers
|
||||
then "true"
|
||||
else "false"
|
||||
}";
|
||||
|
||||
declared_users=(${toString (map (user: "${
|
||||
if isPath user.name
|
||||
then "$(cat ${toString user.name})"
|
||||
else user.name
|
||||
}")
|
||||
users)});
|
||||
|
||||
${readFile ./user-handler.sh}
|
||||
|
||||
${toString (map (user: ''
|
||||
set-user "${
|
||||
if isPath user.name
|
||||
then "$(cat ${toString user.name})"
|
||||
else user.name
|
||||
}" "${
|
||||
if isPath user.email
|
||||
then "$(cat ${toString user.email})"
|
||||
else user.email
|
||||
}" "${
|
||||
if isPath user.password
|
||||
then "$(cat ${toString user.password})"
|
||||
else user.password
|
||||
}" \
|
||||
"${
|
||||
if user.admin
|
||||
then "true"
|
||||
else "false"
|
||||
}"
|
||||
'')
|
||||
users)}
|
||||
'';
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["forgejo.service"];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
122
modules/forgejo/users.nix
Normal file
122
modules/forgejo/users.nix
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.forgejo.users;
|
||||
forgejo = config.services.forgejo;
|
||||
in {
|
||||
imports = [];
|
||||
options.services.forgejo.users = with lib;
|
||||
with lib.types; {
|
||||
enable = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
handleUndeclaredUsers = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
users = mkOption {
|
||||
type = attrsOf (submodule ({
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
with lib.types; {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = nullOr (either str path);
|
||||
default = null;
|
||||
};
|
||||
password = mkOption {
|
||||
type = either str path;
|
||||
};
|
||||
email = mkOption {
|
||||
type = either str path;
|
||||
};
|
||||
admin = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
config = with lib;
|
||||
mkIf cfg.enable {
|
||||
systemd.services."forgejo-users-setup" = with builtins; let
|
||||
users = builtins.attrValues (builtins.mapAttrs
|
||||
(username: info: {
|
||||
name =
|
||||
if isNull info.name
|
||||
then username
|
||||
else info.name;
|
||||
email = info.email;
|
||||
password = info.password;
|
||||
admin = info.admin;
|
||||
})
|
||||
cfg.users);
|
||||
in {
|
||||
script = ''
|
||||
function gum() { ${pkgs.gum}/bin/gum "$@"; }
|
||||
function forgejo() {
|
||||
# local config_file="${toString forgejo.stateDir}/custom/conf/app.ini";
|
||||
# touch $config_file
|
||||
${forgejo.package}/bin/gitea \
|
||||
--work-path ${forgejo.stateDir} \
|
||||
"$@"
|
||||
}
|
||||
function fjuser() { forgejo admin user "$@"; }
|
||||
function awk() { ${pkgs.gawk}/bin/awk "$@"; }
|
||||
|
||||
handle_undeclared_users="${
|
||||
if cfg.handleUndeclaredUsers
|
||||
then "true"
|
||||
else "false"
|
||||
}";
|
||||
|
||||
declared_users=(${toString (map (user: "${
|
||||
if isPath user.name
|
||||
then "$(cat ${toString user.name})"
|
||||
else user.name
|
||||
}")
|
||||
users)});
|
||||
|
||||
${readFile ./users.sh}
|
||||
|
||||
${toString (map (user: ''
|
||||
set-user "${
|
||||
if isPath user.name
|
||||
then "$(cat ${toString user.name})"
|
||||
else user.name
|
||||
}" "${
|
||||
if isPath user.email
|
||||
then "$(cat ${toString user.email})"
|
||||
else user.email
|
||||
}" "${
|
||||
if isPath user.password
|
||||
then "$(cat ${toString user.password})"
|
||||
else user.password
|
||||
}" \
|
||||
"${
|
||||
if user.admin
|
||||
then "true"
|
||||
else "false"
|
||||
}"
|
||||
'')
|
||||
users)}
|
||||
'';
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["forgejo.service"];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = forgejo.user;
|
||||
Group = forgejo.group;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
./adguardhome.nix
|
||||
./caddy.nix
|
||||
./containers
|
||||
./forgejo.nix
|
||||
./tailscale.nix
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
secrets = config.spacestation-secrets.lesser;
|
||||
in {
|
||||
imports = [
|
||||
../modules/forgejo
|
||||
];
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
actions = {
|
||||
enable = true;
|
||||
token = secrets.services.forgejo.actions-token;
|
||||
url = "http://192.168.1.10:${toString secrets.services.forgejo.port}";
|
||||
labels = secrets.services.forgejo.actions-labels;
|
||||
};
|
||||
users = {
|
||||
user1 = {
|
||||
name = /. + config.sops.secrets."forgejo/user1/name".path;
|
||||
password = /. + config.sops.secrets."forgejo/user1/password".path;
|
||||
email = /. + config.sops.secrets."forgejo/user1/email".path;
|
||||
admin = true;
|
||||
};
|
||||
};
|
||||
settings = {
|
||||
server = {
|
||||
HTTP_PORT = secrets.services.forgejo.port;
|
||||
DOMAIN = "forgejo.capytal.company";
|
||||
ROOT_URL = "https://forgejo.capytal.company";
|
||||
};
|
||||
admin = {
|
||||
DISABLE_REGULAR_ORG_CREATION = true;
|
||||
USER_DISABLED_FEATURES = "deletion manage_ssh_keys manage_gpg_keys";
|
||||
EXTERNAL_USER_DISABLED_FEATURES = "deletion manage_ssh_keys manage_gpg_keys";
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user