mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: make default support links respect --docs-url (#14176)
make default support links respect --docs-url
This commit is contained in:
@@ -2,7 +2,10 @@ package appearance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/coder/coder/v2/buildinfo"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
@@ -10,36 +13,50 @@ type Fetcher interface {
|
||||
Fetch(ctx context.Context) (codersdk.AppearanceConfig, error)
|
||||
}
|
||||
|
||||
var DefaultSupportLinks = []codersdk.LinkConfig{
|
||||
{
|
||||
Name: "Documentation",
|
||||
Target: "https://coder.com/docs/coder-oss",
|
||||
Icon: "docs",
|
||||
},
|
||||
{
|
||||
Name: "Report a bug",
|
||||
Target: "https://github.com/coder/coder/issues/new?labels=needs+grooming&body={CODER_BUILD_INFO}",
|
||||
Icon: "bug",
|
||||
},
|
||||
{
|
||||
Name: "Join the Coder Discord",
|
||||
Target: "https://coder.com/chat?utm_source=coder&utm_medium=coder&utm_campaign=server-footer",
|
||||
Icon: "chat",
|
||||
},
|
||||
{
|
||||
Name: "Star the Repo",
|
||||
Target: "https://github.com/coder/coder",
|
||||
Icon: "star",
|
||||
},
|
||||
func DefaultSupportLinks(docsURL string) []codersdk.LinkConfig {
|
||||
version := buildinfo.Version()
|
||||
if docsURL == "" {
|
||||
docsURL = "https://coder.com/docs/@" + strings.Split(version, "-")[0]
|
||||
}
|
||||
buildInfo := fmt.Sprintf("Version: [`%s`](%s)", version, buildinfo.ExternalURL())
|
||||
|
||||
return []codersdk.LinkConfig{
|
||||
{
|
||||
Name: "Documentation",
|
||||
Target: docsURL,
|
||||
Icon: "docs",
|
||||
},
|
||||
{
|
||||
Name: "Report a bug",
|
||||
Target: "https://github.com/coder/coder/issues/new?labels=needs+grooming&body=" + buildInfo,
|
||||
Icon: "bug",
|
||||
},
|
||||
{
|
||||
Name: "Join the Coder Discord",
|
||||
Target: "https://coder.com/chat?utm_source=coder&utm_medium=coder&utm_campaign=server-footer",
|
||||
Icon: "chat",
|
||||
},
|
||||
{
|
||||
Name: "Star the Repo",
|
||||
Target: "https://github.com/coder/coder",
|
||||
Icon: "star",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type AGPLFetcher struct{}
|
||||
type AGPLFetcher struct {
|
||||
docsURL string
|
||||
}
|
||||
|
||||
func (AGPLFetcher) Fetch(context.Context) (codersdk.AppearanceConfig, error) {
|
||||
func (f AGPLFetcher) Fetch(context.Context) (codersdk.AppearanceConfig, error) {
|
||||
return codersdk.AppearanceConfig{
|
||||
AnnouncementBanners: []codersdk.BannerConfig{},
|
||||
SupportLinks: DefaultSupportLinks,
|
||||
SupportLinks: DefaultSupportLinks(f.docsURL),
|
||||
}, nil
|
||||
}
|
||||
|
||||
var DefaultFetcher Fetcher = AGPLFetcher{}
|
||||
func NewDefaultFetcher(docsURL string) Fetcher {
|
||||
return &AGPLFetcher{
|
||||
docsURL: docsURL,
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -475,7 +475,8 @@ func New(options *Options) *API {
|
||||
dbRolluper: options.DatabaseRolluper,
|
||||
}
|
||||
|
||||
api.AppearanceFetcher.Store(&appearance.DefaultFetcher)
|
||||
f := appearance.NewDefaultFetcher(api.DeploymentValues.DocsURL.String())
|
||||
api.AppearanceFetcher.Store(&f)
|
||||
api.PortSharer.Store(&portsharing.DefaultPortSharer)
|
||||
buildInfo := codersdk.BuildInfoResponse{
|
||||
ExternalURL: buildinfo.ExternalURL(),
|
||||
|
||||
@@ -44,12 +44,16 @@ func (api *API) appearance(rw http.ResponseWriter, r *http.Request) {
|
||||
type appearanceFetcher struct {
|
||||
database database.Store
|
||||
supportLinks []codersdk.LinkConfig
|
||||
docsURL string
|
||||
coderVersion string
|
||||
}
|
||||
|
||||
func newAppearanceFetcher(store database.Store, links []codersdk.LinkConfig) agpl.Fetcher {
|
||||
func newAppearanceFetcher(store database.Store, links []codersdk.LinkConfig, docsURL, coderVersion string) agpl.Fetcher {
|
||||
return &appearanceFetcher{
|
||||
database: store,
|
||||
supportLinks: links,
|
||||
docsURL: docsURL,
|
||||
coderVersion: coderVersion,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +94,7 @@ func (f *appearanceFetcher) Fetch(ctx context.Context) (codersdk.AppearanceConfi
|
||||
ApplicationName: applicationName,
|
||||
LogoURL: logoURL,
|
||||
AnnouncementBanners: []codersdk.BannerConfig{},
|
||||
SupportLinks: agpl.DefaultSupportLinks,
|
||||
SupportLinks: agpl.DefaultSupportLinks(f.docsURL),
|
||||
}
|
||||
|
||||
if announcementBannersJSON != "" {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -229,6 +230,26 @@ func TestCustomSupportLinks(t *testing.T) {
|
||||
require.Equal(t, supportLinks, appr.SupportLinks)
|
||||
}
|
||||
|
||||
func TestDefaultSupportLinksWithCustomDocsUrl(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Don't need to set the license, as default links are passed without it.
|
||||
testURLRawString := "http://google.com"
|
||||
testURL, err := url.Parse(testURLRawString)
|
||||
require.NoError(t, err)
|
||||
cfg := coderdtest.DeploymentValues(t)
|
||||
cfg.DocsURL = *serpent.URLOf(testURL)
|
||||
adminClient, adminUser := coderdenttest.New(t, &coderdenttest.Options{DontAddLicense: true, Options: &coderdtest.Options{DeploymentValues: cfg}})
|
||||
anotherClient, _ := coderdtest.CreateAnotherUser(t, adminClient, adminUser.OrganizationID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
|
||||
defer cancel()
|
||||
|
||||
appr, err := anotherClient.Appearance(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, appearance.DefaultSupportLinks(testURLRawString), appr.SupportLinks)
|
||||
}
|
||||
|
||||
func TestDefaultSupportLinks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -241,5 +262,5 @@ func TestDefaultSupportLinks(t *testing.T) {
|
||||
|
||||
appr, err := anotherClient.Appearance(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, appearance.DefaultSupportLinks, appr.SupportLinks)
|
||||
require.Equal(t, appearance.DefaultSupportLinks(""), appr.SupportLinks)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/coder/coder/v2/buildinfo"
|
||||
"github.com/coder/coder/v2/coderd/appearance"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
agplportsharing "github.com/coder/coder/v2/coderd/portsharing"
|
||||
@@ -791,10 +792,13 @@ func (api *API) updateEntitlements(ctx context.Context) error {
|
||||
f := newAppearanceFetcher(
|
||||
api.Database,
|
||||
api.DeploymentValues.Support.Links.Value,
|
||||
api.DeploymentValues.DocsURL.String(),
|
||||
buildinfo.Version(),
|
||||
)
|
||||
api.AGPL.AppearanceFetcher.Store(&f)
|
||||
} else {
|
||||
api.AGPL.AppearanceFetcher.Store(&appearance.DefaultFetcher)
|
||||
f := appearance.NewDefaultFetcher(api.DeploymentValues.DocsURL.String())
|
||||
api.AGPL.AppearanceFetcher.Store(&f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -84,7 +84,8 @@ type Options struct {
|
||||
func New(opts *Options) *Handler {
|
||||
if opts.AppearanceFetcher == nil {
|
||||
daf := atomic.Pointer[appearance.Fetcher]{}
|
||||
daf.Store(&appearance.DefaultFetcher)
|
||||
f := appearance.NewDefaultFetcher(opts.DocsURL)
|
||||
daf.Store(&f)
|
||||
opts.AppearanceFetcher = &daf
|
||||
}
|
||||
handler := &Handler{
|
||||
|
||||
@@ -93,7 +93,7 @@ export const UserDropdownContent: FC<UserDropdownContentProps> = ({
|
||||
<Divider />
|
||||
{supportLinks.map((link) => (
|
||||
<a
|
||||
href={includeBuildInfo(link.target, buildInfo)}
|
||||
href={link.target}
|
||||
key={link.name}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
@@ -177,18 +177,6 @@ export const GithubStar: FC<SvgIconProps> = (props) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
const includeBuildInfo = (
|
||||
href: string,
|
||||
buildInfo?: TypesGen.BuildInfoResponse,
|
||||
): string => {
|
||||
return href.replace(
|
||||
"{CODER_BUILD_INFO}",
|
||||
`${encodeURIComponent(
|
||||
`Version: [\`${buildInfo?.version}\`](${buildInfo?.external_url})`,
|
||||
)}`,
|
||||
);
|
||||
};
|
||||
|
||||
const styles = {
|
||||
info: (theme) => [
|
||||
theme.typography.body2 as CSSObject,
|
||||
|
||||
Reference in New Issue
Block a user