1
0
mirror of https://github.com/ohwgiles/laminar.git synced 2024-10-27 20:34:20 +00:00

webui may be modified with custom style.css

This commit is contained in:
Oliver Giles 2017-12-29 11:14:10 +02:00
parent 6919a74d0a
commit 93b428529e
6 changed files with 45 additions and 16 deletions

View File

@ -66,7 +66,7 @@ For Apache, see [Apache Reverse Proxy](https://httpd.apache.org/docs/2.4/howto/r
#### Set the page title #### Set the page title
Change `LAMINAR_TITLE` in `/etc/laminar.conf` to your preferred page title. Change `LAMINAR_TITLE` in `/etc/laminar.conf` to your preferred page title. For further WebUI customization, consider using a [custom style sheet](#customizing-the-webui).
#### More configuration options #### More configuration options
@ -483,6 +483,11 @@ cmake src
make make
``` ```
### Customizing the WebUI
If it exists, the file `/var/lib/laminar/custom/style.css` will be served by laminar and may be used to change the appearance of Laminar's WebUI.
This directory is also a good place to add any extra assets needed for this customization, but note that in this case you will need to serve this directory directly from your [HTTP reverse proxy](#service-configuration) (highly recommended).
## Reference ## Reference

View File

@ -120,6 +120,11 @@ struct LaminarInterface {
// $LAMINAR_HOME/archive. This shouldn't be used, because the sysadmin // $LAMINAR_HOME/archive. This shouldn't be used, because the sysadmin
// should have configured a real webserver to serve these things. // should have configured a real webserver to serve these things.
virtual bool getArtefact(std::string path, std::string& result) = 0; virtual bool getArtefact(std::string path, std::string& result) = 0;
// Fetches the content of $LAMINAR_HOME/custom/style.css or an empty
// string. This shouldn't be used, because the sysadmin should have
// configured a real webserver to serve these things.
virtual std::string getCustomCss() = 0;
}; };
#endif // LAMINAR_INTERFACE_H_ #endif // LAMINAR_INTERFACE_H_

View File

@ -795,25 +795,38 @@ void Laminar::runFinished(Run * r) {
} }
} }
// Small helper function to return the full contents of a file given its path.
// It reads in the whole file into the given string reference.
// This is a terrible way to serve files (especially large ones). Hopefully
// no-one uses this function and configures their webservers appropriately.
static bool slurp(fs::path path, std::string& output) {
if(!fs::is_regular_file(path))
return false;
std::ifstream fstr(path.string());
fstr.seekg(0, std::ios::end);
ssize_t sz = fstr.tellg();
if(fstr.good()) {
output.resize(static_cast<size_t>(sz));
fstr.seekg(0);
fstr.read(&output[0], sz);
return true;
}
return false;
}
bool Laminar::getArtefact(std::string path, std::string& result) { bool Laminar::getArtefact(std::string path, std::string& result) {
if(archiveUrl != ARCHIVE_URL_DEFAULT) { if(archiveUrl != ARCHIVE_URL_DEFAULT) {
// we shouldn't have got here. Probably an invalid link. // we shouldn't have got here. Probably an invalid link.
return false; return false;
} }
// Reads in the whole file into the given string reference.
// This is a terrible way to serve files (especially large ones).
fs::path file(fs::path(homeDir)/"archive"/path); fs::path file(fs::path(homeDir)/"archive"/path);
// no support for browsing archived directories return slurp(file, result);
if(fs::is_directory(file)) }
return false;
std::ifstream fstr(file.string()); std::string Laminar::getCustomCss()
fstr.seekg(0, std::ios::end); {
ssize_t sz = fstr.tellg(); fs::path file(fs::path(homeDir)/"custom"/"style.css");
if(fstr.good()) { std::string result;
result.resize(static_cast<size_t>(sz)); slurp(file, result);
fstr.seekg(0); return result;
fstr.read(&result[0], sz);
return true;
}
return false;
} }

View File

@ -56,6 +56,7 @@ public:
void sendStatus(LaminarClient* client) override; void sendStatus(LaminarClient* client) override;
bool setParam(std::string job, uint buildNum, std::string param, std::string value) override; bool setParam(std::string job, uint buildNum, std::string param, std::string value) override;
bool getArtefact(std::string path, std::string& result) override; bool getArtefact(std::string path, std::string& result) override;
std::string getCustomCss() override;
private: private:
bool loadConfiguration(); bool loadConfiguration();

View File

@ -14,6 +14,7 @@
<script src="/js/Chart.min.js"></script> <script src="/js/Chart.min.js"></script>
<script src="/js/Chart.HorizontalBar.js"></script> <script src="/js/Chart.HorizontalBar.js"></script>
<link href="/css/bootstrap.min.css" rel="stylesheet"> <link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/custom/style.css" rel="stylesheet">
<script src="/js/app.js" defer></script> <script src="/js/app.js" defer></script>
<style> <style>
body, html { height: 100%; } body, html { height: 100%; }

View File

@ -210,6 +210,10 @@ public:
} else { } else {
c->set_status(websocketpp::http::status_code::not_found); c->set_status(websocketpp::http::status_code::not_found);
} }
} else if(resource.compare("/custom/style.css") == 0) {
c->set_status(websocketpp::http::status_code::ok);
c->append_header("Content-Transfer-Encoding", "binary");
c->set_body(laminar.getCustomCss());
} else if(resources.handleRequest(resource, &start, &end, &content_type)) { } else if(resources.handleRequest(resource, &start, &end, &content_type)) {
c->set_status(websocketpp::http::status_code::ok); c->set_status(websocketpp::http::status_code::ok);
c->append_header("Content-Type", content_type); c->append_header("Content-Type", content_type);