midr @ 90d9d819b70f68e10482954cfc461737c0165f8a

feat: Add custom css
  1diff --git a/.gitignore b/.gitignore
  2index 329aa21294f047bbbe577a5f5fbeba71cbcf00db..579c7ac6e983bae789f2d307a00f5c19a8e476a5 100644
  3--- a/.gitignore
  4+++ b/.gitignore
  5@@ -3,3 +3,4 @@ midr
  6 __debug_bin
  7 
  8 .cache/
  9+.nenv/
 10diff --git a/assets/style.css b/assets/style.css
 11new file mode 100644
 12index 0000000000000000000000000000000000000000..7f524b9e18950647ef523c4edca09cc03477d870
 13--- /dev/null
 14+++ b/assets/style.css
 15@@ -0,0 +1,100 @@
 16+html, body, div, h1, header,section, table, th, td, tr{
 17+	margin: 0;
 18+	padding: 0;
 19+	border: 0;
 20+}
 21+
 22+body {
 23+    font-family: sans-serif;
 24+    margin: 0 auto;
 25+    background-color: #f4f4f4;
 26+}
 27+
 28+header {
 29+    background-color: #0062cc;
 30+    padding: .5em;
 31+    margin: 0 auto;
 32+}
 33+
 34+header h1 {
 35+    font-size: large;
 36+    text-transform: uppercase;
 37+}
 38+
 39+header > h1 > a {
 40+    color: white;
 41+    text-decoration: none;
 42+}
 43+
 44+main {
 45+    margin: 1em;
 46+}
 47+
 48+table {
 49+    display: block;
 50+    border-spacing: 0;
 51+    width: 100%;
 52+    overflow:auto;
 53+    margin-top: 1em;
 54+}
 55+
 56+th.fixed, td.fixed {
 57+  width: 100px;
 58+  overflow: hidden;
 59+}
 60+
 61+th {
 62+    padding: 1em;
 63+    text-align: left;
 64+}
 65+
 66+td {
 67+    padding: 1em;
 68+    overflow: hidden;
 69+    white-space: nowrap;
 70+    border-top: 1px solid #ccc;
 71+}
 72+
 73+form {
 74+    width: 70%;
 75+    max-width: 500px;
 76+}
 77+
 78+form input {
 79+    width: 100%
 80+}
 81+
 82+form label {
 83+    display: block;
 84+}
 85+
 86+.container {
 87+    display: flex;
 88+    flex-direction: column;
 89+    justify-content: center;
 90+    align-items: center;
 91+}
 92+
 93+.field {
 94+    margin-bottom: 1em;
 95+}
 96+
 97+a.button, button  {
 98+  display: inline-block;
 99+  padding: .1rem .75rem;
100+  background: #e9ecef;
101+  border: #343a40 1px solid;
102+  font-size: .9rem;
103+  font-weight: 400;
104+  line-height: 1.5;
105+  cursor: pointer;
106+  color: #000;
107+  border-radius: 0;
108+  text-decoration: none;
109+  transition: 0.5s all;
110+  align-self: flex-start;
111+}
112+
113+a.button:hover {
114+    background-color: #fff;
115+}
116diff --git a/controller/controller.go b/controller/controller.go
117index e381bf81c9f1386fcbdb5ad9f45629b5bd1890d9..c7f41454059c3dfad7a8239ab948eb0779ba3f2e 100644
118--- a/controller/controller.go
119+++ b/controller/controller.go
120@@ -2,6 +2,7 @@ package controller
121 
122 import (
123 	"net/http"
124+	"strconv"
125 	"time"
126 
127 	"git.sr.ht/~gabrielgio/midr/db"
128@@ -40,7 +41,7 @@ func (e *Env) CreateEntry(c *gin.Context) {
129 	var entry db.Entry
130 	c.ShouldBind(&entry)
131 	e.Entries.Create(&entry)
132-	e.Worker.SpawnWorker(entry.ID, entry.Link, entry.OutputFolder)
133+	e.Worker.SpawnWorker(&entry)
134 	c.Redirect(http.StatusFound, "/")
135 }
136 
137@@ -48,6 +49,8 @@ func (e *Env) DeleteEntry(c *gin.Context) {
138 	var entry db.Entry
139 	id := c.Param("id")
140 	e.Entries.Delete(id)
141+	u64, _ := strconv.ParseUint(id, 10, 32)
142+	e.Worker.RemoveJob(uint(u64))
143 	c.HTML(http.StatusOK, "entry", entry)
144 }
145 
146@@ -59,13 +62,13 @@
147 func (e *Env) StartScheduler() {
148 	e.Worker.StartReader()
149 	go func() {
150-		for true {
151+		for {
152 			entries := e.Entries.All()
153 
154 			for _, entry := range entries {
155-				e.Worker.SpawnWorker(entry.ID, entry.Link, entry.OutputFolder)
156+				e.Worker.SpawnWorker(&entry)
157 			}
158-			time.Sleep(30 * time.Minute)
159+			time.Sleep(30 * time.Second)
160 		}
161 	}()
162 }
163diff --git a/db/model.go b/db/model.go
164index 0a5ca98a33c029aa1291ab7bced124f13273c95b..0d5cb47996c2813d2c47e83a088c5fa778553d04 100644
165--- a/db/model.go
166+++ b/db/model.go
167@@ -9,6 +9,7 @@ 	gorm.Model
168 	Title        string
169 	Link         string
170 	Format       string
171+	DateAfter    string
172 	OutputFolder string
173 }
174 
175diff --git a/templates/_footer.tmpl b/templates/_footer.tmpl
176index 97a5bf86321cb9dfb79e36f15c192f3bb67392ba..b72953bfe205e50078ddbd7e2cf27b23ab0596ab 100644
177--- a/templates/_footer.tmpl
178+++ b/templates/_footer.tmpl
179@@ -1,6 +1,5 @@
180 {{ define "_footer" }}
181     </main>
182-    </section>
183 <script>
184   function deleteEntry(id) {
185     fetch("/entries/"+id, { method: 'DELETE' })
186@@ -20,7 +19,7 @@             }
187           });
188     }
189 
190-setInterval(getStatus, 1000);
191+setInterval(getStatus, 5000);
192 
193 </script>
194   </body>
195diff --git a/templates/_head.tmpl b/templates/_head.tmpl
196index b99510f9b7ebbd4035848c4735481ebd55ee3a5c..11a4aa80c3bfb9eb7394dc8b50c920e476174831 100644
197--- a/templates/_head.tmpl
198+++ b/templates/_head.tmpl
199@@ -3,12 +3,11 @@ <!DOCTYPE html>
200 <html>
201   <head>
202     <meta name="viewport" content="width=device-width, initial-scale=1">
203-    <link rel="stylesheet" href="/assets/bulma.min.css">
204+    <link rel="stylesheet" href="/assets/style.css">
205   </head>
206   <body>
207-      <section class="section">
208-          <div class="container">
209-              <h1><a href="/"><strong>Home</strong></a></h1>
210-          </div>
211+      <header>
212+          <h1><a href="/">midr</a></h1>
213+      </header>
214           <main class="container">
215 {{ end }}
216diff --git a/templates/entry.tmpl b/templates/entry.tmpl
217index 9f1181fdb5ad5771b731713f7b50b35f3bff9fb7..9edd5cdd0d0ce85251cbec5fc3f64230de0df150 100644
218--- a/templates/entry.tmpl
219+++ b/templates/entry.tmpl
220@@ -1,6 +1,5 @@
221 {{ define "entry" }}
222 {{ template "_head" }}
223-<div class="container">
224 {{ if (eq .ID 0) }}
225 <form action="/entries" method="POST">
226 {{ else }}
227@@ -16,11 +15,14 @@       <label for="link">Link</label>
228       <input class="input" type="text" id="Link" name="Link" value="{{ .Link }}" placeholder="Paste a valid youtube-dl link" required>
229   </div>
230   <div class="field">
231+      <label for="DateAfter">Date after</label>
232+      <input class="input" type="text" id="DateAfter" name="DateAfter" value="{{ .DateAfter }}" placeholder="Select the start date" required>
233+  </div>
234+  <div class="field">
235       <label for="output">Output folder</label>
236       <input class="input" type="text" id="OutputFolder" name="OutputFolder" value="{{ .OutputFolder }}" placeholder="Select a ralative folder" required>
237   </div>
238   <button type="submit">Submit</button>
239 </form>
240-  </div>
241 {{ template "_footer" }}
242 {{ end }}
243diff --git a/templates/index.tmpl b/templates/index.tmpl
244index ae7f6747e8f506135ea1732727f54b8ab1886e4c..14cb420741e73d970f6161b700904b603c339c53 100644
245--- a/templates/index.tmpl
246+++ b/templates/index.tmpl
247@@ -1,14 +1,13 @@
248 {{ define "index" }}
249 {{ template "_head" }}
250-<div class="container">
251-<table class="table">
252+<table>
253   <thead>
254     <tr>
255       <th scope="col">ID</th>
256       <th scope="col">Title</th>
257       <th scope="col">Link</th>
258       <th scope="col">Output</th>
259-      <th scope="col">Status</th>
260+      <th class="fixed" scope="col">Status</th>
261       <th scope="col"></th>
262     </tr>
263   </thead>
264@@ -19,19 +18,18 @@       <td>{{ .ID }}</td>
265       <td>{{ .Title }}</td>
266       <td>{{ .Link }}</td>
267       <td>{{ .OutputFolder }}</td>
268-      <td>
269+      <td class="fixed">
270           <span id="status_{{ .ID }}" class="tag is-primary is-light"></span>
271       </td>
272       <td>
273         <a href="entries/{{ .ID }}" >Edit</a>
274         </span>
275-        <a  onclick="deleteEntry({{ .ID }})">Delete</a>
276+        <a href="#delete/{{ .ID }}" onclick="deleteEntry({{ .ID }})">Delete</a>
277       </td>
278     </tr>
279     {{ end }}
280   </tbody>
281 </table>
282-</div>
283 <a href="/entries/createEntry" class="button">Create</a>
284 {{ template "_footer" }}
285 {{ end }}
286diff --git a/worker/worker.go b/worker/worker.go
287index a8f15180e1093473163b8eb4ccf274786ea6d380..2444e892278f1547dd820ac6e664107b158acdb0 100644
288--- a/worker/worker.go
289+++ b/worker/worker.go
290@@ -3,6 +3,7 @@
291 import (
292 	"context"
293 
294+	"git.sr.ht/~gabrielgio/midr/db"
295 	"git.sr.ht/~gabrielgio/midr/yt"
296 	work "git.sr.ht/~sircmpwn/dowork"
297 )
298@@ -34,7 +35,7 @@ }
299 
300 func NewWorkder() Worker {
301 	return Worker{
302-		c:    make(chan command, 10),
303+		c:    make(chan command),
304 		jobs: make(map[uint]string),
305 	}
306 }
307@@ -44,26 +45,31 @@ 	v, found := w.jobs[index]
308 	return !found || v == statusNotQueued
309 }
310 
311-func (w *Worker) SpawnWorker(index uint, link string, output string) {
312+func (w *Worker) RemoveJob(id uint) {
313+	delete(w.jobs, id)
314+}
315 
316-	if !w.CanEnqueue(index) {
317+func (w *Worker) SpawnWorker(entry *db.Entry) {
318+
319+	if !w.CanEnqueue(entry.ID) {
320 		return
321 	}
322 
323-	w.c <- command{action: commandEnqueue, index: index}
324+	w.c <- command{action: commandEnqueue, index: entry.ID}
325 	task := work.NewTask(func(ctx context.Context) error {
326-		w.c <- command{action: commandStart, index: index}
327-		yt.RunYtDlpProcess(link, output)
328+
329+		w.c <- command{action: commandStart, index: entry.ID}
330+		yt.RunYtDlpProcess(entry)
331 		return nil
332 	}).After(func(ctx context.Context, task *work.Task) {
333-		w.c <- command{action: commandDequeue, index: index}
334+		w.c <- command{action: commandDequeue, index: entry.ID}
335 	})
336 
337 	work.Enqueue(task)
338 }
339 
340 func (w *Worker) startReader() {
341-	for true {
342+	for {
343 		command := <-w.c
344 
345 		if command.action == commandEnqueue {
346diff --git a/yt/manager.go b/yt/manager.go
347index c0cf6cb7eef0168a5f79c944625d9862aa76c7c9..b9dc3336f203538ef073730e34f044a3eccdf409 100644
348--- a/yt/manager.go
349+++ b/yt/manager.go
350@@ -3,11 +3,23 @@
351 import (
352 	"fmt"
353 	"os/exec"
354+
355+	"git.sr.ht/~gabrielgio/midr/db"
356 )
357 
358-func RunYtDlpProcess(link string, output string) {
359-	output_template := fmt.Sprintf("%s/%%(title)s.%%(ext)s", output)
360-	downloaded_txt := fmt.Sprintf("%s/downloaded.txt", output)
361-	cmd := exec.Command("yt-dlp", link, "-o", output_template, "--download-archive", downloaded_txt)
362-	cmd.Run()
363+func RunYtDlpProcess(entry *db.Entry) error {
364+	args := []string{entry.Link}
365+
366+	output_template := fmt.Sprintf("%s/%%(title)s.%%(ext)s", entry.OutputFolder)
367+	args = append(args, "-o", output_template)
368+
369+	downloaded_txt := fmt.Sprintf("%s/downloaded.txt", entry.OutputFolder)
370+	args = append(args, "--download-archive", downloaded_txt)
371+
372+	if len(entry.DateAfter) > 0 {
373+		args = append(args, "--dateafter", entry.DateAfter)
374+	}
375+
376+	cmd := exec.Command("yt-dlp", args...)
377+	return cmd.Run()
378 }