mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
Password reset functionality, ZWave switch schedule improvement, support zwave controller on pi, support relay switches and security sensors.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||
<artifactId>lantern-currentmonitor</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.2</version>
|
||||
<version>1.0.4</version>
|
||||
<name>lantern-currentmonitor</name>
|
||||
|
||||
<properties>
|
||||
@@ -25,7 +25,7 @@
|
||||
<dependency>
|
||||
<groupId>com.pi4j</groupId>
|
||||
<artifactId>pi4j-gpio-extension</artifactId>
|
||||
<version>1.2</version>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.hypfvieh</groupId>
|
||||
|
||||
@@ -178,14 +178,14 @@ public class MonitorApp {
|
||||
return new byte[]{NetworkMonitor.getNetworkStatus().toMask()};
|
||||
if (HubConfigCharacteristic.NetworkDetails == ch) {
|
||||
NetworkStatus status = NetworkMonitor.getNetworkStatus();
|
||||
DaoEntity meta = DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version")));
|
||||
DaoEntity meta = (host == null)?null:DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version")));
|
||||
status.setPingSuccessful(CollectionUtils.isNotEmpty(meta));
|
||||
return DaoSerializer.toZipBson(status);
|
||||
}
|
||||
if (HubConfigCharacteristic.Log == ch) {
|
||||
String[] log = NullUtils.cleanSplit(ResourceLoader.loadFileAsString(WORKING_DIR + "log/log.txt"), "\n");
|
||||
if (log.length > 10)
|
||||
log = Arrays.copyOfRange(log, log.length-10, log.length);
|
||||
if (log.length > 15)
|
||||
log = Arrays.copyOfRange(log, log.length-15, log.length);
|
||||
return ZipUtils.zip(NullUtils.toByteArray(CollectionUtils.delimit(Arrays.asList(log), "\n")));
|
||||
}
|
||||
return null;
|
||||
@@ -341,7 +341,7 @@ public class MonitorApp {
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
payload = ResourceLoader.loadFile(file.getAbsolutePath());
|
||||
if (post(payload, file.getName().endsWith("dat") ? "power/batch" : "power/hub"))
|
||||
if (post(payload, "power/hub"))
|
||||
file.delete();
|
||||
else
|
||||
break;
|
||||
@@ -401,7 +401,7 @@ public class MonitorApp {
|
||||
private static final class UpdateChecker implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
if (NullUtils.isNotEmpty(host)) {
|
||||
if (NullUtils.isNotEmpty(host) && config.isAutoUpdate()) {
|
||||
DaoEntity meta = DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version")));
|
||||
String newVersion = DaoSerializer.getString(meta, "version");
|
||||
if (NullUtils.isNotEqual(newVersion, version)) {
|
||||
|
||||
@@ -17,6 +17,7 @@ public class MonitorConfig {
|
||||
private int connectTimeout;
|
||||
private int socketTimeout;
|
||||
private int updateInterval;
|
||||
private boolean autoUpdate;
|
||||
private float autoCalibrationVoltage;
|
||||
private boolean needsCalibration;
|
||||
private String mqttBrokerUrl;
|
||||
@@ -107,6 +108,14 @@ public class MonitorConfig {
|
||||
updateInterval = _updateInterval;
|
||||
}
|
||||
|
||||
public boolean isAutoUpdate() {
|
||||
return autoUpdate;
|
||||
}
|
||||
|
||||
public void setAutoUpdate(boolean _autoUpdate) {
|
||||
autoUpdate = _autoUpdate;
|
||||
}
|
||||
|
||||
public float getAutoCalibrationVoltage() {
|
||||
return autoCalibrationVoltage;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ public class MonitorConfigSerializer extends AbstractDaoSerializer<MonitorConfig
|
||||
d.put("connect_timeout", _o.getConnectTimeout());
|
||||
d.put("socket_timeout", _o.getSocketTimeout());
|
||||
d.put("update_interval", _o.getUpdateInterval());
|
||||
d.put("auto_update", _o.isAutoUpdate());
|
||||
d.put("auto_calibration_voltage", _o.getAutoCalibrationVoltage());
|
||||
d.put("needs_calibration", _o.isNeedsCalibration());
|
||||
d.put("mqtt_broker_url", _o.getMqttBrokerUrl());
|
||||
@@ -60,6 +61,7 @@ public class MonitorConfigSerializer extends AbstractDaoSerializer<MonitorConfig
|
||||
o.setConnectTimeout(DaoSerializer.getInteger(_d, "connect_timeout"));
|
||||
o.setSocketTimeout(DaoSerializer.getInteger(_d, "socket_timeout"));
|
||||
o.setUpdateInterval(DaoSerializer.getInteger(_d, "update_interval"));
|
||||
o.setAutoUpdate(DaoSerializer.getBoolean(_d, "auto_update"));
|
||||
o.setAutoCalibrationVoltage(DaoSerializer.getFloat(_d, "auto_calibration_voltage"));
|
||||
o.setNeedsCalibration(DaoSerializer.getBoolean(_d, "needs_calibration"));
|
||||
o.setMqttBrokerUrl(DaoSerializer.getString(_d, "mqtt_broker_url"));
|
||||
|
||||
@@ -32,6 +32,9 @@ public interface CurrentMonitorDao {
|
||||
|
||||
void updateSummaries(BreakerGroup _rootGroup, Set<Date> _daysToSummarize, TimeZone _tz);
|
||||
|
||||
String addPasswordResetKey(String _email);
|
||||
String getEmailForResetKey(String _key);
|
||||
boolean resetPassword(String _key, String _password);
|
||||
String authenticateAccount(String _username, String _password);
|
||||
String getAuthCodeForEmail(String _email, TimeZone _tz);
|
||||
Account authCodeToAccount(String _authCode);
|
||||
|
||||
@@ -296,6 +296,32 @@ public class MongoCurrentMonitorDao implements CurrentMonitorDao {
|
||||
return _account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addPasswordResetKey(String _email) {
|
||||
String key = aes.encryptToBase64(_email);
|
||||
proxy.saveEntity("password_reset", new DaoEntity("_id", key));
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmailForResetKey(String _key) {
|
||||
DaoEntity entity = proxy.queryForEntity("password_reset", new DaoQuery("_id", _key));
|
||||
if (entity == null)
|
||||
return null;
|
||||
return aes.decryptFromBase64ToString(_key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetPassword(String _key, String _password) {
|
||||
DaoEntity entity = proxy.queryForEntity("password_reset", new DaoQuery("_id", _key));
|
||||
if (entity == null)
|
||||
return false;
|
||||
Account acct = getAccountByUsername(aes.decryptFromBase64ToString(_key));
|
||||
acct.setPassword(_password);
|
||||
putAccount(acct);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoProxy getProxy() {
|
||||
return proxy;
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sendgrid</groupId>
|
||||
<artifactId>sendgrid-java</artifactId>
|
||||
<version>4.7.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
@@ -76,11 +81,25 @@
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<webResources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<directory>src/main/webapp</directory>
|
||||
<includes>
|
||||
<include>versioninfo</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
|
||||
<addClasspath>true</addClasspath>
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Build-Time>${maven.build.timestamp}</Build-Time>
|
||||
<Build-OS>${os.name}</Build-OS>
|
||||
<Implementation-Version>${project.version}</Implementation-Version>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.lanternsoftware.currentmonitor.servlet;
|
||||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
|
||||
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -10,8 +13,13 @@ import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/config/*")
|
||||
public class ConfigServlet extends SecureServlet {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigServlet.class);
|
||||
|
||||
@Override
|
||||
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
|
||||
if (_authCode.getAccountId() == 100) {
|
||||
logger.error("my ip: " + _req.getRemoteAddr());
|
||||
}
|
||||
if (isPath(_req, 0, "bin"))
|
||||
zipBsonResponse(_rep, Globals.dao.getMergedConfig(_authCode));
|
||||
else
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.lanternsoftware.currentmonitor.servlet;
|
||||
|
||||
import com.lanternsoftware.currentmonitor.context.Globals;
|
||||
import com.lanternsoftware.util.LanternFiles;
|
||||
import com.lanternsoftware.util.NullUtils;
|
||||
import com.lanternsoftware.util.ResourceLoader;
|
||||
import com.lanternsoftware.util.dao.DaoEntity;
|
||||
import com.lanternsoftware.util.dao.DaoSerializer;
|
||||
import com.lanternsoftware.util.email.EmailValidator;
|
||||
import com.lanternsoftware.util.servlet.FreemarkerConfigUtil;
|
||||
import com.lanternsoftware.util.servlet.FreemarkerServlet;
|
||||
import com.sendgrid.Method;
|
||||
import com.sendgrid.Request;
|
||||
import com.sendgrid.Response;
|
||||
import com.sendgrid.SendGrid;
|
||||
import com.sendgrid.helpers.mail.Mail;
|
||||
import com.sendgrid.helpers.mail.objects.Content;
|
||||
import com.sendgrid.helpers.mail.objects.Email;
|
||||
import freemarker.template.Configuration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.io.IOException;
|
||||
|
||||
@WebServlet("/resetPassword/*")
|
||||
public class ResetPasswordServlet extends FreemarkerServlet {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(ResetPasswordServlet.class);
|
||||
protected static final Configuration CONFIG = FreemarkerConfigUtil.createConfig(ResetPasswordServlet.class, "/templates", 100);
|
||||
protected static final String api_key = ResourceLoader.loadFileAsString(LanternFiles.OPS_PATH + "sendgrid.txt");
|
||||
|
||||
@Override
|
||||
protected Configuration getFreemarkerConfig() {
|
||||
return CONFIG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest _req, HttpServletResponse _resp) {
|
||||
String[] path = getPath(_req);
|
||||
String email = Globals.dao.getEmailForResetKey(path[1]);
|
||||
if (EmailValidator.getInstance().isValid(email)) {
|
||||
render(_resp, "passwordReset.ftl", model(_req, "key", path[1]));
|
||||
} else {
|
||||
render(_resp, "passwordResetMsg.ftl", model(_req, "msg", "This password reset code is no longer valid. Please try sending a new code from the Lantern Power Monitor application."));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest _req, HttpServletResponse _resp) {
|
||||
if (NullUtils.isEqual(_req.getContentType(), MediaType.APPLICATION_FORM_URLENCODED)) {
|
||||
String key = _req.getParameter("reset_key");
|
||||
String password = _req.getParameter("password");
|
||||
if (NullUtils.length(password) < 8) {
|
||||
render(_resp, "passwordReset.ftl", model(_req, "key", key).and("error", "Your password must be at least 8 characters."));
|
||||
return;
|
||||
}
|
||||
Globals.dao.resetPassword(key, password);
|
||||
render(_resp, "passwordResetMsg.ftl", model(_req, "msg", "Your password has been changed."));
|
||||
} else {
|
||||
DaoEntity payload = getRequestZipBson(_req);
|
||||
String email = DaoSerializer.getString(payload, "email");
|
||||
if (NullUtils.isNotEmpty(email)) {
|
||||
String key = Globals.dao.addPasswordResetKey(email);
|
||||
Email from = new Email("info@lanternsoftware.com");
|
||||
String subject = "Password Reset - Lantern Power Monitor";
|
||||
Email to = new Email(email);
|
||||
Content content = new Content("text/plain", "Reset your password using this link:\nhttps://lanternsoftware.com/currentmonitor/resetPassword/" + key);
|
||||
Mail mail = new Mail(from, subject, to, content);
|
||||
SendGrid sg = new SendGrid(api_key);
|
||||
Request request = new Request();
|
||||
try {
|
||||
request.setMethod(Method.POST);
|
||||
request.setEndpoint("mail/send");
|
||||
request.setBody(mail.build());
|
||||
Response response = sg.api(request);
|
||||
zipBsonResponse(_resp, new DaoEntity("success", response.getStatusCode() == 200));
|
||||
} catch (IOException ex) {
|
||||
LOG.error("Failed to send password reset email", ex);
|
||||
zipBsonResponse(_resp, new DaoEntity("success", false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Lantern | Reset Password</title>
|
||||
<link href="${context}/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section id="reset" class="container features" style="margin-top:40px;margin-bottom:40px;">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="navy-line"></div>
|
||||
<h4><img class="mr-1" src="${context}/img/logo_40.png">Reset Password</h4>
|
||||
<form class="ml-2" method="POST">
|
||||
<input type="hidden" name="reset_key" value="${key}"/>
|
||||
<div>New Password:</div>
|
||||
<input type="password" name="password"/>
|
||||
<input type="submit" class="btn-primary" value="Submit"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Lantern | Reset Password</title>
|
||||
<link href="${context}/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section id="reset" class="container features" style="margin-top:40px;margin-bottom:40px;">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="navy-line"></div>
|
||||
<h4><img class="mr-1" src="${context}/img/logo_40.png">Reset Password</h4>
|
||||
<div class="ml-2">${msg}</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
3904
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/css/bootstrap-grid.css
vendored
Normal file
3904
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/css/bootstrap-grid.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
325
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/css/bootstrap-reboot.css
vendored
Normal file
325
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/css/bootstrap-reboot.css
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
[tabindex="-1"]:focus:not(:focus-visible) {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-original-title] {
|
||||
text-decoration: underline;
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
border-bottom: 0;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: .5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #0056b3;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:not([href]) {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([href]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
-ms-overflow-style: scrollbar;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
color: #6c757d;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
button:not(:disabled),
|
||||
[type="button"]:not(:disabled),
|
||||
[type="reset"]:not(:disabled),
|
||||
[type="submit"]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: .5rem;
|
||||
font-size: 1.5rem;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type="search"] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
||||
File diff suppressed because one or more lines are too long
10278
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/css/bootstrap.css
vendored
Normal file
10278
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7033
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/js/bootstrap.bundle.js
vendored
Normal file
7033
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/js/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4420
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/js/bootstrap.js
vendored
Normal file
4420
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
7
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/js/bootstrap.min.js
vendored
Normal file
7
currentmonitor/lantern-service-currentmonitor/src/main/webapp/bootstrap/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
Reference in New Issue
Block a user