view 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
line wrap: on
line source

/*
 * page-index.c -- page /
 *
 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <errno.h>
#include <string.h>

#include "log.h"
#include "config.h"
#include "db.h"
#include "page.h"
#include "types.h"
#include "util.h"

/*
 * Document we create for templatize.
 *
 * {
 *   "projects: [
 *     {
 *       "name": "project name",
 *       "description": "project short description",
 *       "url": "project URL or homepage",
 *       "jobs": [
 *         {
 *           "job": job-id,
 *           "tag": "job tag / revision",
 *           "success": true,                   // on success (absent otherwise)
 *           "failed: true                      // on failure (absent otherwise)
 *         }
 *       ]
 *     }
 *   ]
 * }
 */

static json_t *
make_job(const struct job *job)
{
	struct jobresult res[SCI_WORKER_MAX];
	ssize_t resz;
	json_t *doc = NULL;

	doc = json_pack("{sI ss}",
		"id",   (json_int_t)job->id,
		"tag",  job->tag
        );

        /* Find every job result associated to see if there are failures. */
	resz = db_jobresult_list_by_job_group(res, UTIL_SIZE(res), job->id);

	for (ssize_t i = 0; i < resz; ++i)
		if (res[i].exitcode)
			json_object_set_new(doc, "failed", json_true());

	if (!json_object_get(doc, "failed"))
		json_object_set_new(doc, "success", json_true());

	return doc;
}

static json_t *
make_jobs(const char *project)
{
	struct job jobs[10];
	ssize_t jobsz;
	json_t *array = NULL, *obj;

	if ((jobsz = db_job_list(jobs, UTIL_SIZE(jobs), project)) >= 0) {
		if (!(array = json_array()))
			return NULL;
		for (ssize_t i = 0; i < jobsz; ++i)
			if ((obj = make_job(&jobs[i])))
				json_array_append(array, obj);
	}

	return array;
}

static json_t *
make_project(const struct project *project)
{
	return json_pack("{ss ss ss so*}",
		"name",         project->name,
		"description",  project->desc,
		"url",          project->url,
		"jobs",         make_jobs(project->name)
	);
}

static void
get(struct kreq *r)
{
	(void)r;
	struct project projects[SCI_PROJECT_MAX] = {0};
	ssize_t projectsz = 0;
	json_t *array;

        /* 'projects' array. */
        if (!(array = json_array()))
		log_die("page-index: %s", strerror(ENOMEM));

        projectsz = db_project_list(projects, UTIL_SIZE(projects));

        for (ssize_t i = 0; i < projectsz; ++i)
                json_array_append(array, make_project(&projects[i]));

	page(r, KHTTP_200, KMIME_TEXT_HTML, "pages/index.html", json_pack("{so}",
		"projects", array
	));
}

void
page_index(struct kreq *r)
{
	switch (r->method) {
	case KMETHOD_GET:
		get(r);
		break;
	default:
		page(r, KHTTP_400, KMIME_TEXT_HTML, "pages/400.html", NULL);
		break;
	}
}