From 56f957b4e600f5fcba05037e41c0f627f71d22c9 Mon Sep 17 00:00:00 2001 From: Anbraten Date: Wed, 8 Dec 2021 13:58:00 +0100 Subject: [PATCH] Improve favicons (#576) - dark-mode favicon variants - favicons based on pipeline state if opened build page Co-authored-by: 6543 <6543@obermui.de> --- server/web/web.go | 15 ++++- web/index.html | 3 +- web/public/favicons/favicon-dark-default.png | Bin 0 -> 655 bytes web/public/favicons/favicon-dark-default.svg | 1 + web/public/favicons/favicon-dark-error.png | Bin 0 -> 687 bytes web/public/favicons/favicon-dark-error.svg | 1 + web/public/favicons/favicon-dark-pending.png | Bin 0 -> 719 bytes web/public/favicons/favicon-dark-pending.svg | 1 + web/public/favicons/favicon-dark-success.png | Bin 0 -> 766 bytes web/public/favicons/favicon-dark-success.svg | 1 + web/public/favicons/favicon-light-default.png | Bin 0 -> 659 bytes .../favicon-light-default.svg} | 0 web/public/favicons/favicon-light-error.png | Bin 0 -> 714 bytes web/public/favicons/favicon-light-error.svg | 1 + web/public/favicons/favicon-light-pending.png | Bin 0 -> 738 bytes web/public/favicons/favicon-light-pending.svg | 1 + web/public/favicons/favicon-light-success.png | Bin 0 -> 771 bytes web/public/favicons/favicon-light-success.svg | 1 + web/src/App.vue | 2 +- web/src/compositions/useFavicon.ts | 54 ++++++++++++++++++ web/src/main.ts | 1 + web/src/views/repo/RepoBuild.vue | 9 ++- 22 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 web/public/favicons/favicon-dark-default.png create mode 100644 web/public/favicons/favicon-dark-default.svg create mode 100644 web/public/favicons/favicon-dark-error.png create mode 100644 web/public/favicons/favicon-dark-error.svg create mode 100644 web/public/favicons/favicon-dark-pending.png create mode 100644 web/public/favicons/favicon-dark-pending.svg create mode 100644 web/public/favicons/favicon-dark-success.png create mode 100644 web/public/favicons/favicon-dark-success.svg create mode 100644 web/public/favicons/favicon-light-default.png rename web/public/{favicon.svg => favicons/favicon-light-default.svg} (100%) create mode 100644 web/public/favicons/favicon-light-error.png create mode 100644 web/public/favicons/favicon-light-error.svg create mode 100644 web/public/favicons/favicon-light-pending.png create mode 100644 web/public/favicons/favicon-light-pending.svg create mode 100644 web/public/favicons/favicon-light-success.png create mode 100644 web/public/favicons/favicon-light-success.svg create mode 100644 web/src/compositions/useFavicon.ts diff --git a/server/web/web.go b/server/web/web.go index 14fa98bb8..898c013fe 100644 --- a/server/web/web.go +++ b/server/web/web.go @@ -37,7 +37,8 @@ func New() *gin.Engine { e.Use(setupCache) h := http.FileServer(web.HTTPFS()) - e.GET("/favicon.svg", gin.WrapH(h)) + e.GET("/favicon.svg", redirect("/favicons/favicon-light-default.svg", http.StatusPermanentRedirect)) + e.GET("/favicons/*filepath", gin.WrapH(h)) e.GET("/assets/*filepath", gin.WrapH(h)) e.NoRoute(handleIndex) @@ -45,6 +46,18 @@ func New() *gin.Engine { return e } +// redirect return gin helper to redirect a request +func redirect(location string, status ...int) func(ctx *gin.Context) { + return func(ctx *gin.Context) { + code := http.StatusFound + if len(status) == 1 { + code = status[0] + } + + http.Redirect(ctx.Writer, ctx.Request, location, code) + } +} + func handleIndex(c *gin.Context) { rw := c.Writer data := web.MustLookup("index.html") diff --git a/web/index.html b/web/index.html index 263a92f7a..fecf3cb87 100644 --- a/web/index.html +++ b/web/index.html @@ -2,7 +2,8 @@ - + + Woodpecker diff --git a/web/public/favicons/favicon-dark-default.png b/web/public/favicons/favicon-dark-default.png new file mode 100644 index 0000000000000000000000000000000000000000..b3a29a2eebb93f53d582182228147396c175b2b3 GIT binary patch literal 655 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|3?#2~eYgdr%mREuT!Hj|(!s~%V}F1;1xteb zf*BO$5N6&@$X-{ALo1XhR z=z1T+!|A@_b3@~FdJ`oM^wnM>yOZ<%u$UpMF+pLFGD>G8RyN7hD^&t9Bx=i!bC^-9tCD--o+rf>1_ zt*W1T{f*YMMHjww@|#SCRio# zcHI-1RsVI<9oQl#gjQVK1l;6>4(`V(}g9okV?oIn7$Z}csk;=~H zi8kpw)y%Co`hmdK II;Vst0GB5|e*gdg literal 0 HcmV?d00001 diff --git a/web/public/favicons/favicon-dark-default.svg b/web/public/favicons/favicon-dark-default.svg new file mode 100644 index 000000000..79b2d60f8 --- /dev/null +++ b/web/public/favicons/favicon-dark-default.svg @@ -0,0 +1 @@ + diff --git a/web/public/favicons/favicon-dark-error.png b/web/public/favicons/favicon-dark-error.png new file mode 100644 index 0000000000000000000000000000000000000000..f83f4a374e2abe18fd2bf3236b06eae81e97a2d7 GIT binary patch literal 687 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|3?#2~eYgdrJOX?|T!Hj!uc%j^k^e~nK=qGZ zLV!A6c|}1;jfhE}K(oY3g8YIR-Ww>~-|vvn@LnKb{rm|92Iuz+EI6OWaIcMlfr-J> z#W5t}@Z0I9r!^}GxOi4HFM8Ja|NrvIhYLEQ6bkN~Ny^In()Mm$mhh+b`}L(;oI3QUrDd~TLid$i6GwVvRg3%s0{6*%V|tNv^p=)#lu zL#3YUqR1Uq<&(ij*4)oJA)cHdC$G8e=bTl4x-J%(pN*WlH7UoUqavVH+7%mwES1fUwk+|%@3W1K6+(sUi1V77_1`Q0m!zXe* z?r~65jARqqAS!xndV|yk(Gv_zyPV=2JqldY6(ij1tyi{NS+#eS_N=-b_2YBe$93l) z7++bqCp^}$c*AEOhq9Kr4-Y-Mmwjtvk%9cegL{%crj~8zyz=d<^y`MuU0e3E6zvPD qU4J~rjwNDWTf&d;90ybXGE7_+av`%mQ3RM;7(8A5T-G@yGywpga979x literal 0 HcmV?d00001 diff --git a/web/public/favicons/favicon-dark-error.svg b/web/public/favicons/favicon-dark-error.svg new file mode 100644 index 000000000..334808ae2 --- /dev/null +++ b/web/public/favicons/favicon-dark-error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/public/favicons/favicon-dark-pending.png b/web/public/favicons/favicon-dark-pending.png new file mode 100644 index 0000000000000000000000000000000000000000..02576c9bc60b748a25906c630ac9222c86655697 GIT binary patch literal 719 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|3?#2~eYgdr`~rMJT!Hj|yx`|ip|evkgQJZ#FcZ`R4!si~Al2iEq%mp*~x0Rj6Om6l)Ko zv-N*|CkXnAu1T?<;PC}E|Ft0`L$%KE^d`~lV?iWjh zS@Am-+2njI@~v8SHEU+;%4ajS?<%c2@OR~!wX@nRO5T~BFV{`tWU!OHK)AmWdlIq`a#;kDeE%!S- zDV^*W`uZO|FX7=W{K>n{Nlfzl#ONTEZp;108)k3Jl(){vJ2Gq6AMSH6GNV?Vo+MJV zF(ar{GOA5n$>Zho2d{rl@#A(Bb;|hSZY(A{_1&DO+*hW5XPz&vzVvqM%t#}yR*fTO z_B-`+1S@Smo>jEuh>SL!qc&+uDC07@!rtF!H!l;*KK;CT>8$(*ldc-to&P85biH4= z(nY;c$*0z%B3R|{)l%cK#P+-+%a0so{l}wj^U%=weF=|bfUNf3%PUW7S{d-WEIYc-o5&yR2iK z-xg{#JM@^>ZmAL%nUS=sa&P62pUWnjZ<=BCtbg66n{!g<^-d8@dtRBq`JQ)m$DBLz zg$EWX{ctF|E&Te+J*MCZD)b$h{4m<&t;ucLK6Tj+h=?L literal 0 HcmV?d00001 diff --git a/web/public/favicons/favicon-dark-pending.svg b/web/public/favicons/favicon-dark-pending.svg new file mode 100644 index 000000000..efa389fa1 --- /dev/null +++ b/web/public/favicons/favicon-dark-pending.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/public/favicons/favicon-dark-success.png b/web/public/favicons/favicon-dark-success.png new file mode 100644 index 0000000000000000000000000000000000000000..2b7c9e9a4c3ab1241d3e45b0059c3c9c19ed287b GIT binary patch literal 766 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|3?#2~eYgdrVgr0aT!Hj|yukQEgu(d;h!T?v zPzI1|d?C{0Lb$>C0H6Zni{U`F@%eD0^N}VOf#M)#Kyte18Z)2;vL!)&!3+xb_d6ss zycd`sa9?5lgoXlx^Y70KZ0j#@Gl*YsRyf_Bfq}``)5S3);_%zB*y)QEc-A)5-0-@3 zt?U-xzyI@hzAAF@C^$TGdhLwgSCSvjdh$$dUfsw4i=zU|+`FIlWn^VWEt|vsIOu}r zjMEKQpIn%EdXh;9-_uPKT=*W=oePvND6xMY5YnnW@2P}IWX#sPhMV5$gddf;c3gKm zH}7|uWha3R^5S3Be(r)H)!ZxFLO2CizR^|c zs6BNps7Za@{Q6wkQ(>)pRC>{3|%h37cy%WKRtjun31{6``y{G)$`NK?uk#;8g8 zV%c}(bm#T(Rk3(1tJt3^d0DRz%$4~wU2;KIY!Kan`(B`%L2Y-E;!qfCX(8=SC zt6093!QGFmiVkppW8NIA?6O%pZ56XfK`Cp!#76!#j|*%J-wSm3M8DqUt0iRB-M30^ zPmklzS0P>Z45TAhO=0jl|Kj=ap z%D13Wf>Y)rN6{p^e75w)3FrME>1J%SnrAPxCHR9_3#+mJ@})oHESe-3c=&YY)%@u% zpQ3nEVZi|zi9e;M7-!y<+ORL*(QnQng~cTu^J<#r2t>r6-1N2Mr}LDxqB*^pp_`Ka aGw7brPW_elV*@aqF?hQAxvX_^ literal 0 HcmV?d00001 diff --git a/web/public/favicons/favicon-dark-success.svg b/web/public/favicons/favicon-dark-success.svg new file mode 100644 index 000000000..92b8b6a1d --- /dev/null +++ b/web/public/favicons/favicon-dark-success.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/public/favicons/favicon-light-default.png b/web/public/favicons/favicon-light-default.png new file mode 100644 index 0000000000000000000000000000000000000000..d55a0bf2d3dcf782e829ea928fa45062140d7187 GIT binary patch literal 659 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|3?#2~eYgdrECYN(T!A!sU{6_qEl{UWNswPK zgTnp&?;RQv1m*`!IB&4NAb$hXoM>$Z2FCB6E{-7)hu?;sE;?+$(Q_es)7+5%|2O8w zzS^kcP*L=9VfCpaLTS@k|NJ<9zx`(6d%sWj%WFCn^B+ht<$U-ha6!T$WI10ivq&z_ z^$3d1Y=7+Z^Q_MOpu=TnxTDg% ztLm?6@8;d9VRBZYvGPKK)ZssKykps(-EmsCV#MZWHD_*$hU!@AH&MR0|9=&h1FCG5sx1|7c{U#+f) z_d9&Xwq4-Kt4%BB+pB-u^tgiQ%>==owZV7vx)yBS(X>wG=#CooOR_4y&zErSOIs1^ zZCjx`?KscU{L)>CsVoQQIBt(Hf9dMDHDc|LdAHhBByawlxa~p0+;efpKRKFS@)b_H zbJ^rmPj*p-(=(|jt4?Q0*4X(jKDR_5@Tu|aMQ`HHU3s`ika1F+VC=$#q^~x4c~Y0z zDeEvak!7hSHL%ERh-bKAr$r|w3zsZ0rBk_8Xz7Cb&(lvjS($Cg1+K;YNm4}TBF z@f;WaD%*7GMpXC1DS{HT%d_`f`uSbx#p>w}r@}wo`a0tkKi{JYD@<);T3K0RXjLDp~*l literal 0 HcmV?d00001 diff --git a/web/public/favicons/favicon-light-error.svg b/web/public/favicons/favicon-light-error.svg new file mode 100644 index 000000000..6bedff96e --- /dev/null +++ b/web/public/favicons/favicon-light-error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/public/favicons/favicon-light-pending.png b/web/public/favicons/favicon-light-pending.png new file mode 100644 index 0000000000000000000000000000000000000000..80fc2119b57ac700be85d292aab93dd5b9bcc355 GIT binary patch literal 738 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|3?#2~eYgdr!UKFlT!A!x@bjn;Pyvwqepmpm z^4C#eAp83f;h#rA2+00_Sm4J|;orw0iiQ7rwb}qhrAvbRf*BOA_Z^KTOH5>4-yq__5P4D0T_itWXY9sBL zus^2i#hgz<#uMF)jjr1NvwPLBDZS@Mom<4pS$&z?n+jDwY0gkSkW%*Y%tRHl>CV0w+98b8%-4jTGsZyDeH1bpSyTku|%@X&s|zauWT^v4Ef5J zBUIY)JbP#5eZ9X9a)DDUncI%$?+8}8d$IKLb~~rrkC*>A$olV-^_~mKv*u;KXWU?= zR<+ETTQkaq-!s2^xBCVG?#9Kg6(asM-?f4`JG2d~=T2Z<9>KLFqp(ZbK \ No newline at end of file diff --git a/web/public/favicons/favicon-light-success.png b/web/public/favicons/favicon-light-success.png new file mode 100644 index 0000000000000000000000000000000000000000..fb0ba77b5997794640cb871bc6e7b126cba6d270 GIT binary patch literal 771 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|3?#2~eYgdr5(0ceT!A!xV0gljLB?nOhA@gNswPKgTnp& z4haqK1?C6bS6Dxxp}^q$`||=T`wI->9rg#LuG{U)z`$hU>Eaj?arkZ6?XYG8fir*8 z7CLlq4L$t-|5Dasjzr-*GVwJ9a#dBH%WlrR$@@gUUcSWfuAK5S+e4nI(#vWY9(z5| zoT1;~`Q_qF{Ye%&?cZEARN6o6e?DPf&%5t3vy#3(aP2#|;Oy1ca;sCW7sZ~v*jBu{ zwE1!4;jonlC!dP#@JasgGwb_R(}iL!%ghoP>?^)0v;U1tpCo)CmpijP$Vo-7T}<%A zoK3D?A9~-@kjS@-ux;VHH5$C`G_vbXi?%z9|%dpY~uAHLHC^X6Gh7TI;| z^7)w$w|!rB?DFNOCkxKrQhrePlgVdSXPx9qgN-8%_U|+f8+^_qMb4^Qo3Zs{3|4=*~$_R9hs<*xIy@Ph4BwDiOOo7_3r)VMsw}Cj%a=pbKy>#*Ez-TN?<4l8@t$j z+duu+jhy#5HXM*K`C+Z8XuO*@VQ+kpwPNepo=b{9pB1X5J}FxIYTfae`i@=Ms^z_s dvBgL07;o>$TgtiP+g(sH^>p=fS?83{1OS#RPt*Va literal 0 HcmV?d00001 diff --git a/web/public/favicons/favicon-light-success.svg b/web/public/favicons/favicon-light-success.svg new file mode 100644 index 000000000..e2932a2e0 --- /dev/null +++ b/web/public/favicons/favicon-light-success.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/App.vue b/web/src/App.vue index d1b49080d..960bde1fa 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -39,7 +39,7 @@ export default defineComponent({ const notifications = useNotifications(); // eslint-disable-next-line promise/prefer-await-to-callbacks apiClient.setErrorHandler((err) => { - notifications.notify({ title: err.message || 'An unkown error occurred', type: 'error' }); + notifications.notify({ title: err.message || 'An unknown error occurred', type: 'error' }); }); const blank = computed(() => route.meta.blank); diff --git a/web/src/compositions/useFavicon.ts b/web/src/compositions/useFavicon.ts new file mode 100644 index 000000000..e3271caba --- /dev/null +++ b/web/src/compositions/useFavicon.ts @@ -0,0 +1,54 @@ +import { computed, ref, watch } from 'vue'; + +import { useDarkMode } from '~/compositions/useDarkMode'; +import { BuildStatus } from '~/lib/api/types'; + +const darkMode = computed(() => (useDarkMode().darkMode.value ? 'dark' : 'light')); + +type Status = 'default' | 'success' | 'pending' | 'error'; +const faviconStatus = ref('default'); + +watch( + [darkMode, faviconStatus], + () => { + const faviconPNG = document.getElementById('favicon-png'); + if (faviconPNG) { + (faviconPNG as HTMLLinkElement).href = `/favicons/favicon-${darkMode.value}-${faviconStatus.value}.png`; + } + + const faviconSVG = document.getElementById('favicon-svg'); + if (faviconSVG) { + (faviconSVG as HTMLLinkElement).href = `/favicons/favicon-${darkMode.value}-${faviconStatus.value}.svg`; + } + }, + { immediate: true }, +); + +function convertStatus(status: BuildStatus): Status { + if (['blocked', 'declined', 'error', 'failure', 'killed'].includes(status)) { + return 'error'; + } + + if (['started', 'running', 'pending'].includes(status)) { + return 'pending'; + } + + if (['success', 'declined', 'error', 'failure', 'killed'].includes(status)) { + return 'success'; + } + + // skipped + return 'default'; +} + +export function useFavicon() { + return { + updateStatus(status?: BuildStatus | 'default') { + if (status === undefined || status === 'default') { + faviconStatus.value = 'default'; + } else { + faviconStatus.value = convertStatus(status); + } + }, + }; +} diff --git a/web/src/main.ts b/web/src/main.ts index 61cbb2e17..69fc06ced 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -1,4 +1,5 @@ import 'windi.css'; +import '~/compositions/useFavicon'; import { createPinia } from 'pinia'; import { createApp } from 'vue'; diff --git a/web/src/views/repo/RepoBuild.vue b/web/src/views/repo/RepoBuild.vue index 298f98c7d..6002b4e2f 100644 --- a/web/src/views/repo/RepoBuild.vue +++ b/web/src/views/repo/RepoBuild.vue @@ -69,7 +69,7 @@