Add air for auto reloading on save
spc
- commit
- 3278bce52fd6c7c5d4b3916523a388d28e6fae0c
- author
- bnema · · 2023-09-03 05:20 UTC
- committer
- bnema · · 2023-09-04 06:59 UTC
- parent
- 58590c5
- signature
- unsigned
15 files · +137 -21
A .air.toml +44 -0
| @@ -0,0 +1,44 @@ | |||
| 1 | + | root = "." | |
| 2 | + | testdata_dir = "testdata" | |
| 3 | + | tmp_dir = "tmp" | |
| 4 | + | ||
| 5 | + | [build] | |
| 6 | + | args_bin = [] | |
| 7 | + | bin = "./tmp/main" | |
| 8 | + | cmd = "go build -o ./tmp/main cmd/main.go" | |
| 9 | + | delay = 0 | |
| 10 | + | exclude_dir = ["assets", "tmp", "vendor", "testdata"] | |
| 11 | + | exclude_file = [] | |
| 12 | + | exclude_regex = ["_test.go"] | |
| 13 | + | exclude_unchanged = false | |
| 14 | + | follow_symlink = false | |
| 15 | + | full_bin = "./tmp/main" | |
| 16 | + | include_dir = [] | |
| 17 | + | include_ext = ["go", "tpl", "tmpl", "html", "gohtml", "css"] | |
| 18 | + | include_file = [] | |
| 19 | + | kill_delay = "0s" | |
| 20 | + | log = "build-errors.log" | |
| 21 | + | poll = false | |
| 22 | + | poll_interval = 0 | |
| 23 | + | rerun = false | |
| 24 | + | rerun_delay = 500 | |
| 25 | + | send_interrupt = false | |
| 26 | + | stop_on_error = false | |
| 27 | + | ||
| 28 | + | [color] | |
| 29 | + | app = "" | |
| 30 | + | build = "yellow" | |
| 31 | + | main = "magenta" | |
| 32 | + | runner = "green" | |
| 33 | + | watcher = "cyan" | |
| 34 | + | ||
| 35 | + | [log] | |
| 36 | + | main_only = false | |
| 37 | + | time = false | |
| 38 | + | ||
| 39 | + | [misc] | |
| 40 | + | clean_on_exit = false | |
| 41 | + | ||
| 42 | + | [screen] | |
| 43 | + | clear_on_rebuild = false | |
| 44 | + | keep_scroll = true | |
| @@ -0,0 +1,44 @@ | |||||
| 1 | + | root = "." | |||
| 2 | + | testdata_dir = "testdata" | |||
| 3 | + | tmp_dir = "tmp" | |||
| 4 | + | ||||
| 5 | + | [build] | |||
| 6 | + | args_bin = [] | |||
| 7 | + | bin = "./tmp/main" | |||
| 8 | + | cmd = "go build -o ./tmp/main cmd/main.go" | |||
| 9 | + | delay = 0 | |||
| 10 | + | exclude_dir = ["assets", "tmp", "vendor", "testdata"] | |||
| 11 | + | exclude_file = [] | |||
| 12 | + | exclude_regex = ["_test.go"] | |||
| 13 | + | exclude_unchanged = false | |||
| 14 | + | follow_symlink = false | |||
| 15 | + | full_bin = "./tmp/main" | |||
| 16 | + | include_dir = [] | |||
| 17 | + | include_ext = ["go", "tpl", "tmpl", "html", "gohtml", "css"] | |||
| 18 | + | include_file = [] | |||
| 19 | + | kill_delay = "0s" | |||
| 20 | + | log = "build-errors.log" | |||
| 21 | + | poll = false | |||
| 22 | + | poll_interval = 0 | |||
| 23 | + | rerun = false | |||
| 24 | + | rerun_delay = 500 | |||
| 25 | + | send_interrupt = false | |||
| 26 | + | stop_on_error = false | |||
| 27 | + | ||||
| 28 | + | [color] | |||
| 29 | + | app = "" | |||
| 30 | + | build = "yellow" | |||
| 31 | + | main = "magenta" | |||
| 32 | + | runner = "green" | |||
| 33 | + | watcher = "cyan" | |||
| 34 | + | ||||
| 35 | + | [log] | |||
| 36 | + | main_only = false | |||
| 37 | + | time = false | |||
| 38 | + | ||||
| 39 | + | [misc] | |||
| 40 | + | clean_on_exit = false | |||
| 41 | + | ||||
| 42 | + | [screen] | |||
| 43 | + | clear_on_rebuild = false | |||
| 44 | + | keep_scroll = true | |||
M internal/http/handlers/htmx.go +1 -0
| @@ -44,6 +44,7 @@ func htmxFragmentHandler(c echo.Context, logger *utils.Logger) error { | |||
| 44 | 44 | lang := c.Get(middlewares.LangKey).(string) | |
| 45 | 45 | staticData, err := utils.PopulateDataFromYAML(lang) | |
| 46 | 46 | if err != nil { | |
| 47 | + | logger.Error().Err(err).Msg("Failed to populate data from YAML") | |
| 47 | 48 | return err | |
| 48 | 49 | } | |
| 49 | 50 | ||
| @@ -44,6 +44,7 @@ func htmxFragmentHandler(c echo.Context, logger *utils.Logger) error { | |||||
| 44 | lang := c.Get(middlewares.LangKey).(string) | 44 | lang := c.Get(middlewares.LangKey).(string) | ||
| 45 | staticData, err := utils.PopulateDataFromYAML(lang) | 45 | staticData, err := utils.PopulateDataFromYAML(lang) | ||
| 46 | if err != nil { | 46 | if err != nil { | ||
| 47 | + | logger.Error().Err(err).Msg("Failed to populate data from YAML") | |||
| 47 | return err | 48 | return err | ||
| 48 | } | 49 | } | ||
| 49 | 50 | ||||
A internal/ui/public/android-chrome-192x192.png +0 -0 binary file: no text diff
binary file: no text diff
A internal/ui/public/android-chrome-512x512.png +0 -0 binary file: no text diff
binary file: no text diff
A internal/ui/public/apple-touch-icon.png +0 -0 binary file: no text diff
binary file: no text diff
M internal/ui/public/assets/css/custom.css +20 -0
| @@ -35,3 +35,23 @@ | |||
| 35 | 35 | animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, | |
| 36 | 36 | 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right; | |
| 37 | 37 | } | |
| 38 | + | ||
| 39 | + | ||
| 40 | + | .circle-shadow { | |
| 41 | + | width: 100%; | |
| 42 | + | position: relative; | |
| 43 | + | } | |
| 44 | + | ||
| 45 | + | .circle-shadow::after { | |
| 46 | + | position: absolute; | |
| 47 | + | width: 50%; | |
| 48 | + | height: 0.4rem; | |
| 49 | + | margin: auto; | |
| 50 | + | background: rgba(0, 0, 0, 0.1); | |
| 51 | + | border-radius: 50%; | |
| 52 | + | z-index: -1; | |
| 53 | + | bottom: 2%; | |
| 54 | + | content: ""; | |
| 55 | + | box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1); | |
| 56 | + | ||
| 57 | + | }⏎̸ | |
| @@ -35,3 +35,23 @@ | |||||
| 35 | animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, | 35 | animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, | ||
| 36 | 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right; | 36 | 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right; | ||
| 37 | } | 37 | } | ||
| 38 | + | ||||
| 39 | + | ||||
| 40 | + | .circle-shadow { | |||
| 41 | + | width: 100%; | |||
| 42 | + | position: relative; | |||
| 43 | + | } | |||
| 44 | + | ||||
| 45 | + | .circle-shadow::after { | |||
| 46 | + | position: absolute; | |||
| 47 | + | width: 50%; | |||
| 48 | + | height: 0.4rem; | |||
| 49 | + | margin: auto; | |||
| 50 | + | background: rgba(0, 0, 0, 0.1); | |||
| 51 | + | border-radius: 50%; | |||
| 52 | + | z-index: -1; | |||
| 53 | + | bottom: 2%; | |||
| 54 | + | content: ""; | |||
| 55 | + | box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1); | |||
| 56 | + | ||||
| 57 | + | }⏎̸ | |||
A internal/ui/public/assets/imgs/gordon-mascot-hq-trsp.png +0 -0 binary file: no text diff
binary file: no text diff
A internal/ui/public/assets/imgs/gordon-mascot-mq-trsp.png +0 -0 binary file: no text diff
binary file: no text diff
A internal/ui/public/favicon-16x16.png +0 -0 binary file: no text diff
binary file: no text diff
A internal/ui/public/favicon-32x32.png +0 -0 binary file: no text diff
binary file: no text diff
A internal/ui/public/favicon.ico +0 -0 binary file: no text diff
binary file: no text diff
M internal/ui/public/index.gohtml +55 -20
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | <head> | |
| 6 | 6 | <meta charset="UTF-8" /> | |
| 7 | 7 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| 8 | - | <title>{{ .Header.Meta.Title }}</title> | |
| 8 | + | <title>{{ .header.meta.title }}</title> | |
| 9 | 9 | <meta name="description" content="{{ .Header.Meta.Description }}" /> | |
| 10 | 10 | <meta name="keywords" content="{{ .Header.Meta.Keywords }}" /> | |
| 11 | 11 | <!-- Custom CSS from assets/css --> | |
| @@ -20,24 +20,59 @@ | |||
| 20 | 20 | <!-- Custom JS from assets/js --> | |
| 21 | 21 | <script src="assets/js/custom.js"></script> | |
| 22 | 22 | </head> | |
| 23 | + | <body class="bg-zinc-200 md:p-8 flex"> | |
| 24 | + | ||
| 25 | + | <!-- Left Menu (Navigation) --> | |
| 26 | + | <div class="w-1/5 flex flex-col space-evenly"> | |
| 27 | + | ||
| 28 | + | <!-- Logo --> | |
| 29 | + | <div id="logo-mascot-leftnav" class="flex justify-center h-30 mb-4"> | |
| 30 | + | <div class="circle-shadow flex justify-center sd:hidden"> | |
| 31 | + | <img src="assets/imgs/gordon-mascot-hq-trsp.png" alt="logo" class=""> | |
| 32 | + | </div> | |
| 33 | + | </div> | |
| 34 | + | <div class="p-4 flex flex-col bg-white rounded-3 shadow space-y-4"> | |
| 35 | + | <div class="w-full h-24 bg-gray-300 rounded-2 "></div> <!-- Mock menu item --> | |
| 36 | + | <div class="w-full h-24 bg-gray-300 rounded-2 "></div> <!-- Mock menu item --> | |
| 37 | + | <div class="w-full h-24 bg-gray-300 rounded-2 "></div> <!-- Mock menu item --> | |
| 38 | + | </div> | |
| 39 | + | </div> | |
| 40 | + | ||
| 41 | + | <!-- Main Content --> | |
| 42 | + | <div class="flex-1 flex flex-col md:pt-10 space-y-4 ml-4"> | |
| 43 | + | <!-- Search Nav within the main content --> | |
| 44 | + | <div class="bg-white p-4 rounded-3 shadow mb-4 flex justify-between"> | |
| 45 | + | <div class="w-24 h-8 bg-gray-300 rounded-2 "></div> <!-- Mock search or other element --> | |
| 46 | + | </div> | |
| 47 | + | ||
| 48 | + | <!-- Cards section --> | |
| 49 | + | <div class="flex space-x-4 flex-grow"> | |
| 50 | + | <!-- Main Card on the Left --> | |
| 51 | + | <div class="w-4/6 bg-white p-4 rounded-3 shadow mb-4"> | |
| 52 | + | <div class="w-full rounded-2 bg-gray-300"></div> <!-- Mock main card --> | |
| 53 | + | </div> | |
| 54 | + | ||
| 55 | + | <!-- Two Cards on the Right --> | |
| 56 | + | <div class="w-2/6 flex flex-col flex-justify-start"> | |
| 57 | + | <div class="bg-white p-4 rounded-3 shadow mb-4"> | |
| 58 | + | <div class="w-full h-44 rounded-2 bg-gray-300"></div> <!-- Mock card --> | |
| 59 | + | </div> | |
| 60 | + | <div class="bg-white p-4 rounded-3 shadow mb-4"> | |
| 61 | + | <div class="w-full h-44 rounded-2 bg-gray-300"></div> <!-- Mock card --> | |
| 62 | + | </div> | |
| 63 | + | <div class="bg-white p-4 rounded-3 shadow mb-4"> | |
| 64 | + | <div class="w-full h-44 rounded-2 bg-gray-300"></div> <!-- Mock card --> | |
| 65 | + | </div> | |
| 66 | + | </div> | |
| 67 | + | </div> | |
| 68 | + | </div> | |
| 69 | + | ||
| 70 | + | </body> | |
| 71 | + | </html> | |
| 72 | + | ||
| 73 | + | ||
| 74 | + | ||
| 75 | + | ||
| 76 | + | </html> | |
| 23 | 77 | ||
| 24 | - | <body class="bg-gray-100 flex flex-col min-h-screen"> | |
| 25 | - | <!-- Header Fragment --> | |
| 26 | - | <div | |
| 27 | - | id="header" | |
| 28 | - | hx-get="/htmx" | |
| 29 | - | hx-headers='{"HX-Fragment": "header"}' | |
| 30 | - | hx-trigger="load" | |
| 31 | - | hx-swap="outerHTML" | |
| 32 | - | ></div> | |
| 33 | - | ||
| 34 | - | <!-- App Fragment --> | |
| 35 | - | <div | |
| 36 | - | id="app" | |
| 37 | - | hx-get="/htmx" | |
| 38 | - | hx-headers='{"HX-Fragment": "hello"}' | |
| 39 | - | hx-trigger="load" | |
| 40 | - | hx-swap="outerHTML" | |
| 41 | - | ></div> | |
| 42 | - | </body> | |
| 43 | 78 | </html> | |
| @@ -5,7 +5,7 @@ | |||||
| 5 | <head> | 5 | <head> | ||
| 6 | <meta charset="UTF-8" /> | 6 | <meta charset="UTF-8" /> | ||
| 7 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | 7 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| 8 | - | <title>{{ .Header.Meta.Title }}</title> | 8 | + | <title>{{ .header.meta.title }}</title> |
| 9 | <meta name="description" content="{{ .Header.Meta.Description }}" /> | 9 | <meta name="description" content="{{ .Header.Meta.Description }}" /> | ||
| 10 | <meta name="keywords" content="{{ .Header.Meta.Keywords }}" /> | 10 | <meta name="keywords" content="{{ .Header.Meta.Keywords }}" /> | ||
| 11 | <!-- Custom CSS from assets/css --> | 11 | <!-- Custom CSS from assets/css --> | ||
| @@ -20,24 +20,59 @@ | |||||
| 20 | <!-- Custom JS from assets/js --> | 20 | <!-- Custom JS from assets/js --> | ||
| 21 | <script src="assets/js/custom.js"></script> | 21 | <script src="assets/js/custom.js"></script> | ||
| 22 | </head> | 22 | </head> | ||
| 23 | + | <body class="bg-zinc-200 md:p-8 flex"> | |||
| 24 | + | ||||
| 25 | + | <!-- Left Menu (Navigation) --> | |||
| 26 | + | <div class="w-1/5 flex flex-col space-evenly"> | |||
| 27 | + | ||||
| 28 | + | <!-- Logo --> | |||
| 29 | + | <div id="logo-mascot-leftnav" class="flex justify-center h-30 mb-4"> | |||
| 30 | + | <div class="circle-shadow flex justify-center sd:hidden"> | |||
| 31 | + | <img src="assets/imgs/gordon-mascot-hq-trsp.png" alt="logo" class=""> | |||
| 32 | + | </div> | |||
| 33 | + | </div> | |||
| 34 | + | <div class="p-4 flex flex-col bg-white rounded-3 shadow space-y-4"> | |||
| 35 | + | <div class="w-full h-24 bg-gray-300 rounded-2 "></div> <!-- Mock menu item --> | |||
| 36 | + | <div class="w-full h-24 bg-gray-300 rounded-2 "></div> <!-- Mock menu item --> | |||
| 37 | + | <div class="w-full h-24 bg-gray-300 rounded-2 "></div> <!-- Mock menu item --> | |||
| 38 | + | </div> | |||
| 39 | + | </div> | |||
| 40 | + | ||||
| 41 | + | <!-- Main Content --> | |||
| 42 | + | <div class="flex-1 flex flex-col md:pt-10 space-y-4 ml-4"> | |||
| 43 | + | <!-- Search Nav within the main content --> | |||
| 44 | + | <div class="bg-white p-4 rounded-3 shadow mb-4 flex justify-between"> | |||
| 45 | + | <div class="w-24 h-8 bg-gray-300 rounded-2 "></div> <!-- Mock search or other element --> | |||
| 46 | + | </div> | |||
| 47 | + | ||||
| 48 | + | <!-- Cards section --> | |||
| 49 | + | <div class="flex space-x-4 flex-grow"> | |||
| 50 | + | <!-- Main Card on the Left --> | |||
| 51 | + | <div class="w-4/6 bg-white p-4 rounded-3 shadow mb-4"> | |||
| 52 | + | <div class="w-full rounded-2 bg-gray-300"></div> <!-- Mock main card --> | |||
| 53 | + | </div> | |||
| 54 | + | ||||
| 55 | + | <!-- Two Cards on the Right --> | |||
| 56 | + | <div class="w-2/6 flex flex-col flex-justify-start"> | |||
| 57 | + | <div class="bg-white p-4 rounded-3 shadow mb-4"> | |||
| 58 | + | <div class="w-full h-44 rounded-2 bg-gray-300"></div> <!-- Mock card --> | |||
| 59 | + | </div> | |||
| 60 | + | <div class="bg-white p-4 rounded-3 shadow mb-4"> | |||
| 61 | + | <div class="w-full h-44 rounded-2 bg-gray-300"></div> <!-- Mock card --> | |||
| 62 | + | </div> | |||
| 63 | + | <div class="bg-white p-4 rounded-3 shadow mb-4"> | |||
| 64 | + | <div class="w-full h-44 rounded-2 bg-gray-300"></div> <!-- Mock card --> | |||
| 65 | + | </div> | |||
| 66 | + | </div> | |||
| 67 | + | </div> | |||
| 68 | + | </div> | |||
| 69 | + | ||||
| 70 | + | </body> | |||
| 71 | + | </html> | |||
| 72 | + | ||||
| 73 | + | ||||
| 74 | + | ||||
| 75 | + | ||||
| 76 | + | </html> | |||
| 23 | 77 | ||||
| 24 | - | <body class="bg-gray-100 flex flex-col min-h-screen"> | |||
| 25 | - | <!-- Header Fragment --> | |||
| 26 | - | <div | |||
| 27 | - | id="header" | |||
| 28 | - | hx-get="/htmx" | |||
| 29 | - | hx-headers='{"HX-Fragment": "header"}' | |||
| 30 | - | hx-trigger="load" | |||
| 31 | - | hx-swap="outerHTML" | |||
| 32 | - | ></div> | |||
| 33 | - | ||||
| 34 | - | <!-- App Fragment --> | |||
| 35 | - | <div | |||
| 36 | - | id="app" | |||
| 37 | - | hx-get="/htmx" | |||
| 38 | - | hx-headers='{"HX-Fragment": "hello"}' | |||
| 39 | - | hx-trigger="load" | |||
| 40 | - | hx-swap="outerHTML" | |||
| 41 | - | ></div> | |||
| 42 | - | </body> | |||
| 43 | </html> | 78 | </html> | ||
A internal/ui/public/site.webmanifest +1 -0
| @@ -0,0 +1,1 @@ | |||
| 1 | + | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}⏎̸ | |
| @@ -0,0 +1,1 @@ | |||||
| 1 | + | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}⏎̸ | |||
M internal/ui/templates/components.gohtml +16 -0
| @@ -15,3 +15,19 @@ | |||
| 15 | 15 | {{ .body.div.hello }} | |
| 16 | 16 | </h1> | |
| 17 | 17 | </div> | |
| 18 | + | <div | |
| 19 | + | id="header" | |
| 20 | + | hx-get="/htmx" | |
| 21 | + | hx-headers='{"HX-Fragment": "header"}' | |
| 22 | + | hx-trigger="load" | |
| 23 | + | hx-swap="outerHTML" | |
| 24 | + | ></div> | |
| 25 | + | ||
| 26 | + | <!-- App Fragment --> | |
| 27 | + | <div | |
| 28 | + | id="app" | |
| 29 | + | hx-get="/htmx" | |
| 30 | + | hx-headers='{"HX-Fragment": "hello"}' | |
| 31 | + | hx-trigger="load" | |
| 32 | + | hx-swap="outerHTML" | |
| 33 | + | ></div> | |
| @@ -15,3 +15,19 @@ | |||||
| 15 | {{ .body.div.hello }} | 15 | {{ .body.div.hello }} | ||
| 16 | </h1> | 16 | </h1> | ||
| 17 | </div> | 17 | </div> | ||
| 18 | + | <div | |||
| 19 | + | id="header" | |||
| 20 | + | hx-get="/htmx" | |||
| 21 | + | hx-headers='{"HX-Fragment": "header"}' | |||
| 22 | + | hx-trigger="load" | |||
| 23 | + | hx-swap="outerHTML" | |||
| 24 | + | ></div> | |||
| 25 | + | ||||
| 26 | + | <!-- App Fragment --> | |||
| 27 | + | <div | |||
| 28 | + | id="app" | |||
| 29 | + | hx-get="/htmx" | |||
| 30 | + | hx-headers='{"HX-Fragment": "hello"}' | |||
| 31 | + | hx-trigger="load" | |||
| 32 | + | hx-swap="outerHTML" | |||
| 33 | + | ></div> | |||
M pkg/utils/parser.go +0 -1
| @@ -37,7 +37,6 @@ func ReadDataFromYAML() (YamlData, error) { | |||
| 37 | 37 | if err := yaml.Unmarshal(content, &data); err != nil { | |
| 38 | 38 | return data, fmt.Errorf("failed to unmarshal strings.yaml: %w", err) | |
| 39 | 39 | } | |
| 40 | - | fmt.Println(data) | |
| 41 | 40 | ||
| 42 | 41 | return data, nil | |
| 43 | 42 | } | |
| @@ -37,7 +37,6 @@ func ReadDataFromYAML() (YamlData, error) { | |||||
| 37 | if err := yaml.Unmarshal(content, &data); err != nil { | 37 | if err := yaml.Unmarshal(content, &data); err != nil { | ||
| 38 | return data, fmt.Errorf("failed to unmarshal strings.yaml: %w", err) | 38 | return data, fmt.Errorf("failed to unmarshal strings.yaml: %w", err) | ||
| 39 | } | 39 | } | ||
| 40 | - | fmt.Println(data) | |||
| 41 | 40 | ||||
| 42 | return data, nil | 41 | return data, nil | ||
| 43 | } | 42 | } | ||