tangled
alpha
login
or
join now
willdot.net
/
tangled-fork
forked from
tangled.org/core
Monorepo for Tangled
0
fork
atom
overview
issues
pulls
pipelines
Compare changes
Choose any two refs to compare.
base:
txns
two-way-comms
tracing
three-easy-steps
test-pr-link
test-ci
tags-and-releases
summarize-rounds
stars
stacked-prs
spindle
sl/wnrvrwyvrlzo
sl/uvpzuszrulvq
sl/spindle-rewrite
sl/rusppvknyzsy
sl/okmkyytolvko
sl/kzmmroxoztll
sl/git-objects
settings-router
session-refresh
revert-telemetry
repotab-icons
repo-deletion
render-markup
remove-set-repo-at
release-artifacts
refactor-ks-client
reduce-dids
push-zxovstvplnok
push-zwoymssunvsp
push-zvuqkxuqzmlx
push-zvtqtworuppk
push-zvkrywwskknq
push-zunxqvqoqmoq
push-zrvypwzlqtvz
push-zrkqwwrtxvzn
push-zqrmrxxvrylu
push-zqqvxroypxvy
push-zomkuzmzokvl
push-znrkktvllqsp
push-znlsowpxwvvq
push-zlzkyrrnylxr
push-zklmrltkvxkq
push-yytstxoqlwmx
push-yynslowxntql
push-ywynwzosnrox
push-yuwoytzsmkvm
push-yulzrzunkznl
push-ytzxyplmvunn
push-ytpxvpknlxun
push-ytkuzknmmrmn
push-yssxzpkyorwv
push-yqnqquktxqpx
push-ylvkxyvlmkyq
push-ykxtvrlpxwrl
push-ykwytywspowp
push-xwxnuorpzwsu
push-xwotmtuuvokm
push-xvuvxolnykpl
push-xvrvnuvsmslv
push-xvnwyvuwwylt
push-xtzkpqpkmvvr
push-xtuxqqlytkws
push-xttmuzqzktwv
push-xsmwulupylxx
push-xpolynpvotzt
push-xopyykmxuqzw
push-xmplzvpqtnru
push-xlupzwtslltp
push-wzlvlnywrxrs
push-wzkqymznotmx
push-wyonpyyzurwl
push-wykupplnxytq
push-wxwpnnytwxsq
push-wxvwuxxzswmv
push-wvywrqlppxqo
push-wvwxxlyxrxlm
push-wukyptkosoux
push-wtmrprmomuus
push-wsxnywmtsnrp
push-wqzwpukkvnuw
push-wpkykovtqxnx
push-wnwpznvpzwqu
push-wnotmtoqlnvl
push-wmkmzrsvlkmk
push-wkwyolovuxvq
push-vyyrpsmynrwo
push-vyusnwqnmxwy
push-vynsusnqpmus
push-vwyomovpppwp
push-vwuuzxwwsvow
push-vvluoqoywsvp
push-vuzywsvmkwqn
push-vtunvupqotuo
push-vssvkowylwvx
push-vquoltwpkuny
push-vnxxyxursomy
push-vmxtqnzznxvk
push-vkywmxzkrnqx
push-uylxxnsupvlk
push-uwuymmkuwsrs
push-uwotwontksrz
push-uuyqkqmkmlsn
push-uruyyqupsmro
push-upnknovvnoqr
push-uotxnqrqnlyl
push-ummlkpsrvrvn
push-ukznmmplmlul
push-ukmxnzrlrpuo
push-tzyltlmtsznq
push-tyxzqwosmzuv
push-twskywooslyl
push-twnpklmstzor
push-twlxnytrpyuk
push-tvvnxqyykkwr
push-tvtwutsrtoxt
push-tultwuoxrmun
push-ttyzwxqtkpsl
push-tnwwtqxpoqpk
push-tlxunysxvxwk
push-tkxmuvxkylmy
push-tkusxvwknltw
push-synlttxvkzox
push-svxqqzsxxkor
push-svtkmrzmrwky
push-stktrzvlltpw
push-sssuxsytslts
push-spvnpqlqqpkw
push-snyqozvrosmk
push-snktzuwttuvu
push-smsrusztuvwt
push-rvtqynpmozzy
push-rurrtsvmnvku
push-ruoqnsmttnxx
push-rtwrkkyllvkm
push-rtvxspsprvuv
push-rsrowlxunurk
push-rrsulrtnsmtw
push-rqzvvtnzkzvq
push-rqxyyurmpkps
push-rnztkppsvskw
push-rlorkkyzokzr
push-rlktrmqtttnn
push-qwnqkqnmovyn
push-qtrkvornpykm
push-qsmrouptzqkq
push-qruszvywputp
push-qrltzqmlrlln
push-qqwquvlysrxt
push-qqsspmnuxqwk
push-qqrowoolzppw
push-qoplqnlvlqqo
push-qnstkrpltlqu
push-qlzpkvltqlzm
push-qkpqsrknozxs
push-qkkmntrmxqly
push-pzwzzlwkkpnw
push-pzrysszkwwtk
push-pymywyqyumlo
push-pyllqzrprrny
push-pwqwlvnsqtqr
push-pvpnsqvvzuky
push-ptrrwwvnkmxq
push-psqwruuwvwlo
push-prszwlupsoqz
push-ppstsspzpxrx
push-potvrpwlpwsl
push-pnknzwntuuwx
push-pmtpswykplzr
push-plpuqtyrprou
push-plmznxvyqrqw
push-pkyzqzmqunnl
push-pkqzkqmxotyz
push-pkklqwlqwoml
push-owwtwvxyzowl
push-ovsuzpqkpmlt
push-ovrqrxnpvroz
push-ossmlnsnvstq
push-ormxrmmzomqu
push-oovokvlkywly
push-okymwlupkook
push-nwslswprzvmx
push-nwrnkztxkovl
push-nupxprsykpzq
push-nsolyvvsyvzw
push-nqrqutkzxskl
push-nozqtwvsrvkx
push-nnuvlyptxsqy
push-nmwononozzxz
push-nlvzxwtrmryl
push-nlnnyywnokyn
push-mzupsvxpvqvx
push-mzsvpkottnnt
push-myqmppunmplu
push-mwkwusmyymno
push-mvmrzuxwmzvs
push-mutuoxwuokqw
push-mtsxyxnkznyy
push-mtqkyzxrqnnn
push-msvlvnlwuyxy
push-mrwusmywonor
push-mqkxnymrqmzz
push-mozrrovxmlou
push-mopllyvuuuls
push-monplorvolvl
push-momltwttmuyq
push-mntstlmzqrvs
push-mmxkmyvyuzlk
push-mmrtnyoskwoo
push-mmnuoyuqplyk
push-mlxxvvqpzvlw
push-mllunlokmuxp
push-lzkzortpuyyq
push-lyrpkknpnrus
push-lxxtrqtnnoxy
push-lvuknrupsyox
push-lstutzylzylk
push-lrzzmtxokrxw
push-lnvnxmxlqkux
push-lnupvsypkuow
push-llqkvunvvzyv
push-ktsnmppqsnls
push-kstnoynmspqp
push-ksrsmmytwuul
push-kslplloylmlp
push-kpmvvnzwyosv
push-kltomzxpyoxq
punchcard-did
pull-from-fork-pill
profile-timeline
profile-customizations
pr-page
pr-actions
patch-requests
paginate-issues
packages-small
packages
oplog
opengraph
op/zxpquyouulmx
op/vyrymqtwolsn
op/lrpyxormllvp
oauth
more-diff-stats
master
local-fragments
knot-xrpc
knot-local-clone
knot-cli
issues-edit
interdiff
improve-styling
improve-repo-name-checks
icy/tolqpt
icy/pwvyvo
group-profile-timeline
format-patch
fork-repo
fork-pulls
fix-tw-dark
fix-resubmit
fix-refresh-issues
fix-knot-forks
fix-jetstream-bugs
fix-env-test
file-tree
fast-dev
enable-html
drop-at
disable-punchcard
diff-improvements
did-email-assoc
default-knot
crash-repro-knot
consolidate-syntax-styles
compare-merge-base
commits-page
commit-verification
ci-statuses
ci
camo
cache-busting
branch-prs-2
branch-prs
branch-fmt-patch
atprotate-pubkeys
all-repositories-page
add-migrations
v1.11.0-alpha
v1.10.0-alpha
v1.9.1-alpha
v1.9.0-alpha
v1.8.1-alpha
v1.8.0-alpha
v1.7.0-alpha
v1.6.0-alpha
v1.5.0-alpha
v1.4.0-alpha
v1.3.0-alpha
v1.2.2-alpha
v1.2.1-alpha
v1.2.0-alpha
v1.1.2-alpha
v1.1.1-alpha
v1.1.0-alpha
v1.0.6-alpha
v1.0.5-alpha
v1.0.4-alpha
v1.0.3-alpha
v1.0.2-alpha
v1.0.1-alpha
v1.0.0-alpha
compare:
txns
two-way-comms
tracing
three-easy-steps
test-pr-link
test-ci
tags-and-releases
summarize-rounds
stars
stacked-prs
spindle
sl/wnrvrwyvrlzo
sl/uvpzuszrulvq
sl/spindle-rewrite
sl/rusppvknyzsy
sl/okmkyytolvko
sl/kzmmroxoztll
sl/git-objects
settings-router
session-refresh
revert-telemetry
repotab-icons
repo-deletion
render-markup
remove-set-repo-at
release-artifacts
refactor-ks-client
reduce-dids
push-zxovstvplnok
push-zwoymssunvsp
push-zvuqkxuqzmlx
push-zvtqtworuppk
push-zvkrywwskknq
push-zunxqvqoqmoq
push-zrvypwzlqtvz
push-zrkqwwrtxvzn
push-zqrmrxxvrylu
push-zqqvxroypxvy
push-zomkuzmzokvl
push-znrkktvllqsp
push-znlsowpxwvvq
push-zlzkyrrnylxr
push-zklmrltkvxkq
push-yytstxoqlwmx
push-yynslowxntql
push-ywynwzosnrox
push-yuwoytzsmkvm
push-yulzrzunkznl
push-ytzxyplmvunn
push-ytpxvpknlxun
push-ytkuzknmmrmn
push-yssxzpkyorwv
push-yqnqquktxqpx
push-ylvkxyvlmkyq
push-ykxtvrlpxwrl
push-ykwytywspowp
push-xwxnuorpzwsu
push-xwotmtuuvokm
push-xvuvxolnykpl
push-xvrvnuvsmslv
push-xvnwyvuwwylt
push-xtzkpqpkmvvr
push-xtuxqqlytkws
push-xttmuzqzktwv
push-xsmwulupylxx
push-xpolynpvotzt
push-xopyykmxuqzw
push-xmplzvpqtnru
push-xlupzwtslltp
push-wzlvlnywrxrs
push-wzkqymznotmx
push-wyonpyyzurwl
push-wykupplnxytq
push-wxwpnnytwxsq
push-wxvwuxxzswmv
push-wvywrqlppxqo
push-wvwxxlyxrxlm
push-wukyptkosoux
push-wtmrprmomuus
push-wsxnywmtsnrp
push-wqzwpukkvnuw
push-wpkykovtqxnx
push-wnwpznvpzwqu
push-wnotmtoqlnvl
push-wmkmzrsvlkmk
push-wkwyolovuxvq
push-vyyrpsmynrwo
push-vyusnwqnmxwy
push-vynsusnqpmus
push-vwyomovpppwp
push-vwuuzxwwsvow
push-vvluoqoywsvp
push-vuzywsvmkwqn
push-vtunvupqotuo
push-vssvkowylwvx
push-vquoltwpkuny
push-vnxxyxursomy
push-vmxtqnzznxvk
push-vkywmxzkrnqx
push-uylxxnsupvlk
push-uwuymmkuwsrs
push-uwotwontksrz
push-uuyqkqmkmlsn
push-uruyyqupsmro
push-upnknovvnoqr
push-uotxnqrqnlyl
push-ummlkpsrvrvn
push-ukznmmplmlul
push-ukmxnzrlrpuo
push-tzyltlmtsznq
push-tyxzqwosmzuv
push-twskywooslyl
push-twnpklmstzor
push-twlxnytrpyuk
push-tvvnxqyykkwr
push-tvtwutsrtoxt
push-tultwuoxrmun
push-ttyzwxqtkpsl
push-tnwwtqxpoqpk
push-tlxunysxvxwk
push-tkxmuvxkylmy
push-tkusxvwknltw
push-synlttxvkzox
push-svxqqzsxxkor
push-svtkmrzmrwky
push-stktrzvlltpw
push-sssuxsytslts
push-spvnpqlqqpkw
push-snyqozvrosmk
push-snktzuwttuvu
push-smsrusztuvwt
push-rvtqynpmozzy
push-rurrtsvmnvku
push-ruoqnsmttnxx
push-rtwrkkyllvkm
push-rtvxspsprvuv
push-rsrowlxunurk
push-rrsulrtnsmtw
push-rqzvvtnzkzvq
push-rqxyyurmpkps
push-rnztkppsvskw
push-rlorkkyzokzr
push-rlktrmqtttnn
push-qwnqkqnmovyn
push-qtrkvornpykm
push-qsmrouptzqkq
push-qruszvywputp
push-qrltzqmlrlln
push-qqwquvlysrxt
push-qqsspmnuxqwk
push-qqrowoolzppw
push-qoplqnlvlqqo
push-qnstkrpltlqu
push-qlzpkvltqlzm
push-qkpqsrknozxs
push-qkkmntrmxqly
push-pzwzzlwkkpnw
push-pzrysszkwwtk
push-pymywyqyumlo
push-pyllqzrprrny
push-pwqwlvnsqtqr
push-pvpnsqvvzuky
push-ptrrwwvnkmxq
push-psqwruuwvwlo
push-prszwlupsoqz
push-ppstsspzpxrx
push-potvrpwlpwsl
push-pnknzwntuuwx
push-pmtpswykplzr
push-plpuqtyrprou
push-plmznxvyqrqw
push-pkyzqzmqunnl
push-pkqzkqmxotyz
push-pkklqwlqwoml
push-owwtwvxyzowl
push-ovsuzpqkpmlt
push-ovrqrxnpvroz
push-ossmlnsnvstq
push-ormxrmmzomqu
push-oovokvlkywly
push-okymwlupkook
push-nwslswprzvmx
push-nwrnkztxkovl
push-nupxprsykpzq
push-nsolyvvsyvzw
push-nqrqutkzxskl
push-nozqtwvsrvkx
push-nnuvlyptxsqy
push-nmwononozzxz
push-nlvzxwtrmryl
push-nlnnyywnokyn
push-mzupsvxpvqvx
push-mzsvpkottnnt
push-myqmppunmplu
push-mwkwusmyymno
push-mvmrzuxwmzvs
push-mutuoxwuokqw
push-mtsxyxnkznyy
push-mtqkyzxrqnnn
push-msvlvnlwuyxy
push-mrwusmywonor
push-mqkxnymrqmzz
push-mozrrovxmlou
push-mopllyvuuuls
push-monplorvolvl
push-momltwttmuyq
push-mntstlmzqrvs
push-mmxkmyvyuzlk
push-mmrtnyoskwoo
push-mmnuoyuqplyk
push-mlxxvvqpzvlw
push-mllunlokmuxp
push-lzkzortpuyyq
push-lyrpkknpnrus
push-lxxtrqtnnoxy
push-lvuknrupsyox
push-lstutzylzylk
push-lrzzmtxokrxw
push-lnvnxmxlqkux
push-lnupvsypkuow
push-llqkvunvvzyv
push-ktsnmppqsnls
push-kstnoynmspqp
push-ksrsmmytwuul
push-kslplloylmlp
push-kpmvvnzwyosv
push-kltomzxpyoxq
punchcard-did
pull-from-fork-pill
profile-timeline
profile-customizations
pr-page
pr-actions
patch-requests
paginate-issues
packages-small
packages
oplog
opengraph
op/zxpquyouulmx
op/vyrymqtwolsn
op/lrpyxormllvp
oauth
more-diff-stats
master
local-fragments
knot-xrpc
knot-local-clone
knot-cli
issues-edit
interdiff
improve-styling
improve-repo-name-checks
icy/tolqpt
icy/pwvyvo
group-profile-timeline
format-patch
fork-repo
fork-pulls
fix-tw-dark
fix-resubmit
fix-refresh-issues
fix-knot-forks
fix-jetstream-bugs
fix-env-test
file-tree
fast-dev
enable-html
drop-at
disable-punchcard
diff-improvements
did-email-assoc
default-knot
crash-repro-knot
consolidate-syntax-styles
compare-merge-base
commits-page
commit-verification
ci-statuses
ci
camo
cache-busting
branch-prs-2
branch-prs
branch-fmt-patch
atprotate-pubkeys
all-repositories-page
add-migrations
v1.11.0-alpha
v1.10.0-alpha
v1.9.1-alpha
v1.9.0-alpha
v1.8.1-alpha
v1.8.0-alpha
v1.7.0-alpha
v1.6.0-alpha
v1.5.0-alpha
v1.4.0-alpha
v1.3.0-alpha
v1.2.2-alpha
v1.2.1-alpha
v1.2.0-alpha
v1.1.2-alpha
v1.1.1-alpha
v1.1.0-alpha
v1.0.6-alpha
v1.0.5-alpha
v1.0.4-alpha
v1.0.3-alpha
v1.0.2-alpha
v1.0.1-alpha
v1.0.0-alpha
go
+177
-39
9 changed files
expand all
collapse all
unified
split
appview
db
db.go
profile.go
models
profile.go
pages
pages.go
templates
layouts
profilebase.html
user
settings
profile.html
settings
settings.go
state
profile.go
router.go
+8
-1
appview/db/db.go
···
1078
1078
// transfer data, constructing pull_at from pulls table
1079
1079
_, err = tx.Exec(`
1080
1080
insert into pull_submissions_new (id, pull_at, round_number, patch, created)
1081
1081
-
select
1081
1081
+
select
1082
1082
ps.id,
1083
1083
'at://' || p.owner_did || '/sh.tangled.repo.pull/' || p.rkey,
1084
1084
ps.round_number,
···
1173
1173
return err
1174
1174
})
1175
1175
1176
1176
+
orm.RunMigration(conn, logger, "add-punchcard-setting-profile", func(tx *sql.Tx) error {
1177
1177
+
_, err := tx.Exec(`
1178
1178
+
alter table profile add column punchard_setting string;
1179
1179
+
`)
1180
1180
+
return err
1181
1181
+
})
1182
1182
+
1176
1183
return &DB{
1177
1184
db,
1178
1185
logger,
+31
-21
appview/db/profile.go
···
16
16
17
17
const TimeframeMonths = 7
18
18
19
19
-
func MakeProfileTimeline(e Execer, forDid string) (*models.ProfileTimeline, error) {
19
19
+
func MakeProfileTimeline(e Execer, forDid string, includePunchcard bool) (*models.ProfileTimeline, error) {
20
20
timeline := models.ProfileTimeline{
21
21
ByMonth: make([]models.ByMonth, TimeframeMonths),
22
22
}
···
98
98
})
99
99
}
100
100
101
101
-
punchcard, err := MakePunchcard(
102
102
-
e,
103
103
-
orm.FilterEq("did", forDid),
104
104
-
orm.FilterGte("date", time.Now().AddDate(0, -TimeframeMonths, 0)),
105
105
-
)
106
106
-
if err != nil {
107
107
-
return nil, fmt.Errorf("error getting commits by did: %w", err)
108
108
-
}
109
109
-
for _, punch := range punchcard.Punches {
110
110
-
if punch.Date.After(now) {
111
111
-
continue
101
101
+
if includePunchcard {
102
102
+
punchcard, err := MakePunchcard(
103
103
+
e,
104
104
+
orm.FilterEq("did", forDid),
105
105
+
orm.FilterGte("date", time.Now().AddDate(0, -TimeframeMonths, 0)),
106
106
+
)
107
107
+
if err != nil {
108
108
+
return nil, fmt.Errorf("error getting commits by did: %w", err)
112
109
}
110
110
+
for _, punch := range punchcard.Punches {
111
111
+
if punch.Date.After(now) {
112
112
+
continue
113
113
+
}
113
114
114
114
-
monthsAgo := monthsBetween(punch.Date, now)
115
115
-
if monthsAgo >= TimeframeMonths {
116
116
-
// shouldn't happen; but times are weird
117
117
-
continue
118
118
-
}
115
115
+
monthsAgo := monthsBetween(punch.Date, now)
116
116
+
if monthsAgo >= TimeframeMonths {
117
117
+
// shouldn't happen; but times are weird
118
118
+
continue
119
119
+
}
119
120
120
120
-
idx := monthsAgo
121
121
-
timeline.ByMonth[idx].Commits += punch.Count
121
121
+
idx := monthsAgo
122
122
+
timeline.ByMonth[idx].Commits += punch.Count
123
123
+
}
122
124
}
123
125
124
126
return &timeline, nil
···
353
355
includeBluesky := 0
354
356
355
357
err := e.QueryRow(
356
356
-
`select description, include_bluesky, location, pronouns from profile where did = ?`,
358
358
+
`select description, include_bluesky, location, pronouns, punchard_setting from profile where did = ?`,
357
359
did,
358
358
-
).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns)
360
360
+
).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns, &profile.PunchardSetting)
359
361
if err == sql.ErrNoRows {
360
362
profile := models.Profile{}
361
363
profile.Did = did
···
536
538
}
537
539
return nil
538
540
}
541
541
+
542
542
+
func SetProfilePunchcardStatus(e Execer, did string, punchcard models.ProfilePunchcardOption) error {
543
543
+
_, err := e.Exec(
544
544
+
`update profile set punchard_setting = ? where did = ?`,
545
545
+
punchcard, did,
546
546
+
)
547
547
+
return err
548
548
+
}
+26
-7
appview/models/profile.go
···
7
7
"tangled.org/core/api/tangled"
8
8
)
9
9
10
10
+
type ProfilePunchcardOption string
11
11
+
12
12
+
const (
13
13
+
ProfilePunchcardOptionHideMine ProfilePunchcardOption = "HIDE_MINE"
14
14
+
ProfilePunchcardOptionHideAll ProfilePunchcardOption = "HIDE_ALL"
15
15
+
)
16
16
+
17
17
+
func ProfilePunchcardFromString(s string) ProfilePunchcardOption {
18
18
+
switch s {
19
19
+
case "HIDE_MINE":
20
20
+
return ProfilePunchcardOptionHideMine
21
21
+
case "HIDE_ALL":
22
22
+
return ProfilePunchcardOptionHideAll
23
23
+
default:
24
24
+
return ""
25
25
+
}
26
26
+
}
27
27
+
10
28
type Profile struct {
11
29
// ids
12
30
ID int
13
31
Did string
14
32
15
33
// data
16
16
-
Description string
17
17
-
IncludeBluesky bool
18
18
-
Location string
19
19
-
Links [5]string
20
20
-
Stats [2]VanityStat
21
21
-
PinnedRepos [6]syntax.ATURI
22
22
-
Pronouns string
34
34
+
Description string
35
35
+
IncludeBluesky bool
36
36
+
Location string
37
37
+
Links [5]string
38
38
+
Stats [2]VanityStat
39
39
+
PinnedRepos [6]syntax.ATURI
40
40
+
Pronouns string
41
41
+
PunchardSetting ProfilePunchcardOption
23
42
}
24
43
25
44
func (p Profile) IsLinksEmpty() bool {
+5
-3
appview/pages/pages.go
···
337
337
}
338
338
339
339
type UserProfileSettingsParams struct {
340
340
-
LoggedInUser *oauth.MultiAccountUser
341
341
-
Tabs []map[string]any
342
342
-
Tab string
340
340
+
LoggedInUser *oauth.MultiAccountUser
341
341
+
Tabs []map[string]any
342
342
+
Tab string
343
343
+
PunchcardSetting models.ProfilePunchcardOption
343
344
}
344
345
345
346
func (p *Pages) UserProfileSettings(w io.Writer, params UserProfileSettingsParams) error {
···
537
538
ProfileTimeline *models.ProfileTimeline
538
539
Card *ProfileCard
539
540
Active string
541
541
+
ShowPunchcard bool
540
542
}
541
543
542
544
func (p *Pages) ProfileOverview(w io.Writer, params ProfileOverviewParams) error {
+4
-2
appview/pages/templates/layouts/profilebase.html
···
10
10
<meta property="og:image" content="{{ $avatarUrl }}" />
11
11
<meta property="og:image:width" content="512" />
12
12
<meta property="og:image:height" content="512" />
13
13
-
13
13
+
14
14
<meta name="twitter:card" content="summary" />
15
15
<meta name="twitter:title" content="{{ $handle }}" />
16
16
<meta name="twitter:description" content="{{ or .Card.Profile.Description $handle }}" />
···
28
28
<div class="{{ $style }} order-1 order-1">
29
29
<div class="flex flex-col gap-4">
30
30
{{ template "user/fragments/profileCard" .Card }}
31
31
-
{{ block "punchcard" .Card.Punchcard }} {{ end }}
31
31
+
{{ if .ShowPunchcard }}
32
32
+
{{ block "punchcard" .Card.Punchcard }} {{ end }}
33
33
+
{{ end }}
32
34
</div>
33
35
</div>
34
36
+31
appview/pages/templates/user/settings/profile.html
···
59
59
</div>
60
60
</div>
61
61
</div>
62
62
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 w-full">
63
63
+
<div class="flex items-center justify-between p-4">
64
64
+
<div class="hover:no-underline flex flex-col gap-1 min-w-0 max-w-[80%]">
65
65
+
<div class="flex flex-wrap text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
66
66
+
<span>Punchcard settings</span>
67
67
+
</div>
68
68
+
<form hx-post="/profile/punchcard" class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
69
69
+
<select
70
70
+
id="punchcard-setting"
71
71
+
name="punchcard-setting"
72
72
+
required
73
73
+
class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
74
74
+
{{/* For some reason, we can't use an empty string in a <select> in all scenarios unless it is preceded by a disabled select?? No idea, could just be a Firefox thing? */}}
75
75
+
<option value="[[none]]" class="py-1" {{ if not $.PunchcardSetting }}selected{{ end }}>
76
76
+
Show all
77
77
+
</option>
78
78
+
<option value="HIDE_MINE" class="py-1" {{ if eq "HIDE_MINE" $.PunchcardSetting }}selected{{ end }}>
79
79
+
Hide mine for others
80
80
+
</option>
81
81
+
<option value="HIDE_ALL" class="py-1" {{ if eq "HIDE_ALL" $.PunchcardSetting }}selected{{ end }}>
82
82
+
Hide everyones for me
83
83
+
</option>
84
84
+
</select>
85
85
+
<button class="btn flex gap-2 items-center" type="submit">
86
86
+
{{ i "check" "size-4" }}
87
87
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
88
88
+
</button>
89
89
+
</form>
90
90
+
</div>
91
91
+
</div>
92
92
+
</div>
62
93
{{ end }}
+11
-2
appview/settings/settings.go
···
82
82
83
83
func (s *Settings) profileSettings(w http.ResponseWriter, r *http.Request) {
84
84
user := s.OAuth.GetMultiAccountUser(r)
85
85
+
profile, err := db.GetProfile(s.Db, user.Did())
86
86
+
if err != nil {
87
87
+
log.Printf("failed to get profile to check punchcard settings: %s", err)
88
88
+
}
85
89
86
86
-
s.Pages.UserProfileSettings(w, pages.UserProfileSettingsParams{
90
90
+
params := pages.UserProfileSettingsParams{
87
91
LoggedInUser: user,
88
92
Tabs: settingsTabs,
89
93
Tab: "profile",
90
90
-
})
94
94
+
}
95
95
+
if profile != nil {
96
96
+
params.PunchcardSetting = profile.PunchardSetting
97
97
+
}
98
98
+
99
99
+
s.Pages.UserProfileSettings(w, params)
91
100
}
92
101
93
102
func (s *Settings) notificationsSettings(w http.ResponseWriter, r *http.Request) {
+60
-3
appview/state/profile.go
···
157
157
}
158
158
}
159
159
160
160
-
timeline, err := db.MakeProfileTimeline(s.db, profile.UserDid)
160
160
+
loggedInUser := s.oauth.GetMultiAccountUser(r)
161
161
+
162
162
+
forProfile, err := db.GetProfile(s.db, profile.UserDid)
163
163
+
if err != nil {
164
164
+
l.Error("failed to get for profile to check punchcard settings", "err", err)
165
165
+
}
166
166
+
requesterProfile, err := db.GetProfile(s.db, loggedInUser.Did())
167
167
+
if err != nil {
168
168
+
l.Error("failed to get requester profile to check punchcard settings", "err", err)
169
169
+
}
170
170
+
171
171
+
showPunchcard := true
172
172
+
if forProfile != nil && forProfile.PunchardSetting == models.ProfilePunchcardOptionHideMine {
173
173
+
showPunchcard = false
174
174
+
}
175
175
+
if requesterProfile != nil && requesterProfile.PunchardSetting == models.ProfilePunchcardOptionHideAll {
176
176
+
showPunchcard = false
177
177
+
}
178
178
+
179
179
+
timeline, err := db.MakeProfileTimeline(s.db, profile.UserDid, showPunchcard)
161
180
if err != nil {
162
181
l.Error("failed to create timeline", "err", err)
163
182
}
164
183
184
184
+
loggedInUserProfile, err := db.GetProfile(s.db, loggedInUser.Did())
185
185
+
if err != nil {
186
186
+
l.Error("failed to get logged in user profile to check punchcard settings", "err", err)
187
187
+
}
188
188
+
189
189
+
if loggedInUserProfile != nil && loggedInUserProfile.PunchardSetting == models.ProfilePunchcardOptionHideAll {
190
190
+
191
191
+
}
192
192
+
165
193
s.pages.ProfileOverview(w, pages.ProfileOverviewParams{
166
166
-
LoggedInUser: s.oauth.GetMultiAccountUser(r),
194
194
+
LoggedInUser: loggedInUser,
167
195
Card: profile,
168
196
Repos: pinnedRepos,
169
197
CollaboratingRepos: pinnedCollaboratingRepos,
170
198
ProfileTimeline: timeline,
199
199
+
ShowPunchcard: showPunchcard,
171
200
})
172
201
}
173
202
···
404
433
}
405
434
406
435
func (s *State) getProfileFeed(ctx context.Context, id *identity.Identity) (*feeds.Feed, error) {
407
407
-
timeline, err := db.MakeProfileTimeline(s.db, id.DID.String())
436
436
+
timeline, err := db.MakeProfileTimeline(s.db, id.DID.String(), false)
408
437
if err != nil {
409
438
return nil, err
410
439
}
···
728
757
AllRepos: allRepos,
729
758
})
730
759
}
760
760
+
761
761
+
func (s *State) UpdateProfilePunchcardSetting(w http.ResponseWriter, r *http.Request) {
762
762
+
err := r.ParseForm()
763
763
+
if err != nil {
764
764
+
log.Println("invalid profile update form", err)
765
765
+
return
766
766
+
}
767
767
+
user := s.oauth.GetUser(r)
768
768
+
769
769
+
profile, err := db.GetProfile(s.db, user.Did)
770
770
+
if err != nil {
771
771
+
log.Printf("getting profile data for %s: %s", user.Did, err)
772
772
+
}
773
773
+
774
774
+
if profile == nil {
775
775
+
return
776
776
+
}
777
777
+
778
778
+
punchcard := r.Form.Get("punchcard-setting")
779
779
+
780
780
+
err = db.SetProfilePunchcardStatus(s.db, profile.Did, models.ProfilePunchcardFromString(punchcard))
781
781
+
if err != nil {
782
782
+
log.Println("failed to update profile", err)
783
783
+
return
784
784
+
}
785
785
+
786
786
+
s.pages.HxRefresh(w)
787
787
+
}
+1
appview/state/router.go
···
165
165
r.Get("/edit-pins", s.EditPinsFragment)
166
166
r.Post("/bio", s.UpdateProfileBio)
167
167
r.Post("/pins", s.UpdateProfilePins)
168
168
+
r.Post("/punchcard", s.UpdateProfilePunchcardSetting)
168
169
})
169
170
170
171
r.Mount("/settings", s.SettingsRouter())