comparison scid/page-index.c @ 26:7e10cace67a3

scid: add basic mustache support
author David Demelier <markand@malikania.fr>
date Tue, 02 Aug 2022 13:24:13 +0200
parents 600204c31bf0
children dae2de19ca5d
comparison
equal deleted inserted replaced
25:c40f98360ac9 26:7e10cace67a3
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19 #include <sys/types.h> 19 #include <errno.h>
20 #include <assert.h> 20 #include <string.h>
21 #include <stdarg.h>
22 #include <stdint.h>
23 21
24 #include <kcgi.h> 22 #include "log.h"
25 23 #include "config.h"
26 #include "database.h" 24 #include "db.h"
27 #include "fragment-paste.h"
28 #include "page-index.h"
29 #include "page.h" 25 #include "page.h"
30 #include "paste.h" 26 #include "types.h"
31 #include "util.h" 27 #include "util.h"
32 28
33 struct template { 29 /*
34 struct kreq *req; 30 * Document we create for templatize.
35 const struct paste *pastes; 31 *
36 size_t pastesz; 32 * {
37 }; 33 * "projects: [
34 * {
35 * "name": "project name",
36 * "description": "project short description",
37 * "url": "project URL or homepage",
38 * "jobs": [
39 * {
40 * "job": job-id,
41 * "tag": "job tag / revision",
42 * "success": true, // on success (absent otherwise)
43 * "failed: true // on failure (absent otherwise)
44 * }
45 * ]
46 * }
47 * ]
48 * }
49 */
38 50
39 static const char *keywords[] = { 51 static json_t *
40 "pastes" 52 make_job(const struct job *job)
41 }; 53 {
54 struct jobresult res[SCI_WORKER_MAX];
55 ssize_t resz;
56 json_t *doc = NULL;
42 57
43 static int 58 doc = json_pack("{sI ss}",
44 template(size_t keyword, void *arg) 59 "id", (json_int_t)job->id,
60 "tag", job->tag
61 );
62
63 /* Find every job result associated to see if there are failures. */
64 resz = db_jobresult_list_by_job_group(res, UTIL_SIZE(res), job->id);
65
66 for (ssize_t i = 0; i < resz; ++i)
67 if (res[i].exitcode)
68 json_object_set_new(doc, "failed", json_true());
69
70 if (!json_object_get(doc, "failed"))
71 json_object_set_new(doc, "success", json_true());
72
73 return doc;
74 }
75
76 static json_t *
77 make_jobs(const char *project)
45 { 78 {
46 struct template *tp = arg; 79 struct job jobs[10];
80 ssize_t jobsz;
81 json_t *array = NULL, *obj;
47 82
48 switch (keyword) { 83 if ((jobsz = db_job_list(jobs, UTIL_SIZE(jobs), project)) >= 0) {
49 case 0: 84 if (!(array = json_array()))
50 for (size_t i = 0; i < tp->pastesz; ++i) 85 return NULL;
51 fragment_paste(tp->req, &tp->pastes[i]); 86 for (ssize_t i = 0; i < jobsz; ++i)
52 break; 87 if ((obj = make_job(&jobs[i])))
53 default: 88 json_array_append(array, obj);
54 break;
55 } 89 }
56 90
57 return 1; 91 return array;
92 }
93
94 static json_t *
95 make_project(const struct project *project)
96 {
97 return json_pack("{ss ss ss so*}",
98 "name", project->name,
99 "description", project->desc,
100 "url", project->url,
101 "jobs", make_jobs(project->name)
102 );
58 } 103 }
59 104
60 static void 105 static void
61 get(struct kreq *r) 106 get(struct kreq *r)
62 { 107 {
63 struct paste pastes[10] = {0}; 108 (void)r;
64 size_t pastesz = NELEM(pastes); 109 struct project projects[SCI_PROJECT_MAX] = {0};
110 ssize_t projectsz = 0;
111 json_t *array;
65 112
66 if (!database_recents(pastes, &pastesz)) 113 /* 'projects' array. */
67 page(r, NULL, KHTTP_500, "pages/500.html"); 114 if (!(array = json_array()))
68 else 115 log_die("page-index: %s", strerror(ENOMEM));
69 page_index_render(r, pastes, pastesz);
70 116
71 for (size_t i = 0; i < pastesz; ++i) 117 projectsz = db_project_list(projects, UTIL_SIZE(projects));
72 paste_finish(&pastes[i]);
73 }
74 118
75 void 119 for (ssize_t i = 0; i < projectsz; ++i)
76 page_index_render(struct kreq *r, const struct paste *pastes, size_t pastesz) 120 json_array_append(array, make_project(&projects[i]));
77 {
78 struct template data = {
79 .req = r,
80 .pastes = pastes,
81 .pastesz = pastesz
82 };
83 121
84 struct ktemplate kt = { 122 page(r, KHTTP_200, KMIME_TEXT_HTML, "pages/index.html", json_pack("{so}",
85 .key = keywords, 123 "projects", array
86 .keysz = NELEM(keywords), 124 ));
87 .arg = &data,
88 .cb = template
89 };
90
91 page(r, &kt, KHTTP_200, "pages/index.html");
92 } 125 }
93 126
94 void 127 void
95 page_index(struct kreq *r) 128 page_index(struct kreq *r)
96 { 129 {
97 switch (r->method) { 130 switch (r->method) {
98 case KMETHOD_GET: 131 case KMETHOD_GET:
99 get(r); 132 get(r);
100 break; 133 break;
101 default: 134 default:
102 page(r, NULL, KHTTP_400, "400.html"); 135 page(r, KHTTP_400, KMIME_TEXT_HTML, "pages/400.html", NULL);
103 break; 136 break;
104 } 137 }
105 } 138 }