Skip to content

Commit

Permalink
Merge pull request #4 from brackendawson/webui
Browse files Browse the repository at this point in the history
Add a web UI
  • Loading branch information
brackendawson authored Sep 27, 2024
2 parents 07236fd + fe09bd1 commit 9774c3c
Show file tree
Hide file tree
Showing 47 changed files with 3,266 additions and 397 deletions.
32 changes: 27 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
[![Go workflow](https://github.com/brackendawson/webcal-proxy/actions/workflows/go.yml/badge.svg)](https://github.com/brackendawson/webcal-proxy/actions/workflows/go.yml)

# webcal-proxy
A simple server to proxy and filter webcal links.
# ![wp logo](assets/img/favicon.ico) webcal-proxy
A simple server to filter events from webcal feeds.

[![Try it out](doc/try-it-out.png)](https://bracken.cc/webcal-proxy)

## Usage
### Server
#### Arguments
Usage of webcal-proxy:
* -addr string
local address:port to bind to (default ":80")
local address:port to bind to (default ":8080")
* -logfile string
File to log to
* -loglevel string
* -log-level string
log level (default "info")
* -max-conns maximum total upstream connections
* -dev disables security policies that prevent http://localhost from working

#### TLS
The server should be run behind a reverse proxy which terminates TLS because the webcal:// protocol requires valid TLS. The web interface will also not function on http without the -dev argument, even then some things will not work, such as clipboard interaction.

#### Proxy Path
If the reverse proxy uses a path then provide it in the `X-Forwarded-URI` header. Example nginx config:
```nginx
location /webcal-proxy/ {
proxy_pass http://127.0.0.1:8080;
rewrite ^/webcal-proxy/(.*)$ /$1 break;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-URI /webcal-proxy;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_buffering off;
}
```

### Client
Enter the URL into your webcal client:
Expand All @@ -27,5 +49,5 @@ Where:

eg:
```
webcal://example.com/webcal-proxy?cal=webcal://example.com/my/calendar&exc=SUMMARY=Boring%20Events
webcal://webcal-proxy.example.com/webcal-proxy?cal=webcal://example.com/my/calendar&exc=SUMMARY=Boring%20Events
```
40 changes: 40 additions & 0 deletions assets/assets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package assets

import (
"embed"
"fmt"
"html/template"
)

var (
//go:embed js css img webfonts
Assets embed.FS
//go:embed html
templates embed.FS

funcs template.FuncMap = template.FuncMap{
"errorf": func(format string, args ...any) (any, error) {
return nil, fmt.Errorf(format, args...)
},
"dict": dict,
}
)

func Templates() *template.Template {
return template.Must(template.New("_all").Funcs(funcs).ParseFS(templates, "html/*.html"))
}

func dict(kv ...any) (map[string]any, error) {
if len(kv)%2 != 0 {
return nil, fmt.Errorf("dict must have even number arguments, got: %d", len(kv))
}
m := make(map[string]any, len(kv)/2)
for i := 0; i < len(kv); i += 2 {
k, ok := kv[i].(string)
if !ok {
return nil, fmt.Errorf("dict argument %d must be string, got %T", i, kv[i])
}
m[k] = kv[i+1]
}
return m, nil
}
6 changes: 6 additions & 0 deletions assets/css/bootstrap.min.css

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions assets/css/fontawesome.min.css

Large diffs are not rendered by default.

256 changes: 256 additions & 0 deletions assets/css/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
:root {
--max-width: 60rem;
--min-width: 20rem;
--light-bg: #ffaa00;
--dark-bg: #ff6600;
--light-grey: #eeeeee;
--med-grey: #cccccc;
--light-blue: #6599ff;
--med-blue: #0066ff;
--light-red: #ffaacc;
--light-green: #92fe92;
}


html,
body {
height: 100%;
}

body {
display: flex;
flex-direction: column;
align-items: center;
min-width: var(--min-width);
}

header {
width: 100%;
padding: 2rem;
padding-bottom: 1rem;
text-align: center;
color: white;
background: var(--light-bg);
background-image: linear-gradient(var(--light-bg), var(--dark-bg) 100%);
}

main {
flex-grow: 1;
padding: 1rem;
max-width: var(--max-width);
width: 100%;
}

footer {
width: 100%;
box-sizing: border-box;
padding-inline: calc(50% - var(--max-width) / 2);
padding-block: 1rem;
color: white;
background: var(--light-bg);
background-image: linear-gradient(var(--dark-bg), var(--light-bg) 100%);
}

footer span {
padding-left: 1rem;
}

footer a {
text-decoration: inherit;
color: inherit;
}

#calendar {
display: flex;
flex-wrap: wrap;
margin-block: 1rem;
font-size: 0.8rem;
}

#calendar * {
overflow: hidden;
text-overflow: ellipsis;
}

.calendar-title {
width: 100%;
text-align: center;
}

.calendar-dow {
width: calc(100%/7);
text-align: center;
}

.day {
position: relative;
min-height: 6.3em;
width: calc(100%/7);
border: solid 0.05rem;
border-color: var(--light-grey);
}

.day > a {
text-decoration: inherit;
color: inherit;
}

.day-head {
background: var(--light-grey);
padding-left: 0.25em;
}

.day-event {
white-space: nowrap;
border-radius: 0.25em;
background: var(--med-blue);
padding-left: 0.25em;
margin-bottom: 0.1em;
}

.day-event > .event-end-time,
.day-event > .event-location,
.day-event > .event-description {
display: none;
}

.event-start-time-continued:after {
content: "...";
}

.modal-body > p {
margin-block: 0;
}

.event-modal-start-time:before {
content: "Start: ";
color: grey;
font-style: italic;
}

.event-modal-end-time:before {
content: "End: ";
color: grey;
font-style: italic;
}

.event-modal-location:before {
content: "Location: ";
color: grey;
font-style: italic;
}

.event-modal-description:before {
content: "Description: ";
color: grey;
font-style: italic;
}

.day-saturday .day-head,
.day-sunday .day-head {
background: var(--med-grey);
}

.day-today .day-head {
background: var(--light-bg);
color: white;
}

.day-spill .day-event,
.day-spill .day-head {
opacity: 25%;
}

.input-group {
margin-block: 1rem;
}

#url-label {
background: var(--light-green);
}

#loading {
display: none;
}

.htmx-request #loading {
display: flex;
animation: pulse 1s linear 0s infinite;
}

.htmx-request #notification {
display: none;
}

@keyframes pulse {
50% {
opacity: 0%;
}

100% {
opacity: 100%;
}
}

.property-select {
text-align: right;
}

.match-select {
text-align: center;
}

.input-group > .matcher-property {
flex: 0 0 fit-content;
}

.input-group > .matcher-operator {
flex: 0 0 fit-content;
}

.input-group > .matcher-value {
flex: 1 0 auto;
}

.del-matcher > * {
pointer-events: none;
}

.matcher-group:nth-child(1 of .matcher-group) .del-matcher {
display: none;
}

#date-picker {
width: auto;
justify-content: center;
}

#date-picker * {
flex: 0 0 fit-content;
}

#date-pick-year {
flex: 0 0;
min-width: 4em;
}

#date-pick-prev-month::after {
content: '<';
}

#date-pick-next-month:after {
content: '>';
}

#date-pick-prev-year:after {
content: '-';
}

#date-pick-next-year:after {
content: '+';
}

.alert {
margin-block: 1rem;
padding-block: 0.38rem;
}
Loading

0 comments on commit 9774c3c

Please sign in to comment.