Tag Server website works without data
This commit is contained in:
147
sampleData.py
147
sampleData.py
@@ -6,13 +6,13 @@ Created on April 7, 2016
|
||||
@author: Patrick McDonagh
|
||||
@description: Continuously loops through a list of tags to store values from a PLC into a MySQL database
|
||||
'''
|
||||
import mysql.connector as mysqlcon
|
||||
import pickle
|
||||
|
||||
from tag.tag_mysql import Tag
|
||||
import traceback
|
||||
import time
|
||||
import os
|
||||
import random
|
||||
import requests
|
||||
import json
|
||||
|
||||
|
||||
class Sample(Tag):
|
||||
@@ -48,86 +48,93 @@ class Sample(Tag):
|
||||
self.sendToDB()
|
||||
return self.value
|
||||
|
||||
def sendToDB(self):
|
||||
data = {}
|
||||
data['val'] = self.value
|
||||
data['tagID'] = self.db_id
|
||||
r = requests.post('http://localhost:1337/tag_val', data=data)
|
||||
resp = json.loads(r.text)
|
||||
print("Stored {} for {} at {}".format(resp['val'], self.name, resp['createdAt']))
|
||||
|
||||
with open(os.path.realpath('.') + '/mysql_cfg.pickle', 'rb') as pickleconfig:
|
||||
mysql_cfg = pickle.load(pickleconfig)
|
||||
|
||||
if mysql_cfg:
|
||||
db = mysqlcon.connect(**mysql_cfg)
|
||||
|
||||
|
||||
# with open(os.path.realpath('.') + '/mysql_cfg.pickle', 'rb') as pickleconfig:
|
||||
# mysql_cfg = pickle.load(pickleconfig)
|
||||
#
|
||||
# if mysql_cfg:
|
||||
# db = mysqlcon.connect(**mysql_cfg)
|
||||
|
||||
tag_store = {}
|
||||
configProperties = {}
|
||||
# configProperties = {}
|
||||
|
||||
def main():
|
||||
db.connect()
|
||||
cur = db.cursor()
|
||||
query = "SELECT * FROM tags WHERE class = 5 AND deleted = 0"
|
||||
cur.execute(query)
|
||||
tags = cur.fetchall()
|
||||
print tags
|
||||
# [(1, u'Century Counter Up', 5, u'Century_Counter_Up', u'REAL', 10.0, 3600, None, 0)]
|
||||
db.disconnect()
|
||||
|
||||
# Get tags stored in database
|
||||
get_tag_request_data = {'where':'{"tag_class":5}'}
|
||||
get_tag_request = requests.get('http://localhost:1337/tag', params=get_tag_request_data)
|
||||
tags = json.loads(get_tag_request.text)
|
||||
|
||||
configObj = {}
|
||||
db.connect()
|
||||
cur = db.cursor()
|
||||
query = "SELECT parameter, val FROM config GROUP BY parameter;"
|
||||
cur.execute(query)
|
||||
config = cur.fetchall()
|
||||
db.disconnect()
|
||||
for x in config:
|
||||
configObj[x[0]] = x[1]
|
||||
|
||||
try:
|
||||
configProperties['PLC_IP_ADDRESS'] = str(configObj['ip_address'])
|
||||
print("FYI, using PLC IP Address from the database {0}".format(configProperties['PLC_IP_ADDRESS']))
|
||||
except KeyError:
|
||||
print("FYI, there is no PLC IP Address stored in the database, defaulting to 192.168.1.10")
|
||||
configProperties['PLC_IP_ADDRESS'] = "192.168.1.10"
|
||||
|
||||
try:
|
||||
configProperties['plc_type'] = str(configObj['plc_type'])
|
||||
print("FYI, using PLC Type from the database {0}".format(configProperties['plc_type']))
|
||||
except KeyError:
|
||||
print("FYI, there is no PLC Type stored in the database, defaulting to CLX")
|
||||
configProperties['plc_type'] = "CLX"
|
||||
|
||||
try:
|
||||
configProperties['scan_rate'] = int(configObj['scan_rate'])
|
||||
print("FYI, using Scan Rate from the database {0}".format(configProperties['scan_rate']))
|
||||
except KeyError:
|
||||
print("FYI, there is no Scan Rate stored in the database, defaulting to 10 seconds")
|
||||
configProperties['scan_rate'] = 10
|
||||
|
||||
try:
|
||||
sa_test = str(configObj['save_all'])
|
||||
if sa_test.lower() == "true":
|
||||
configProperties['save_all'] = True
|
||||
elif sa_test.lower() == "false":
|
||||
configProperties['save_all'] = False
|
||||
else:
|
||||
configProperties['save_all'] = "test"
|
||||
print("FYI, value for save_all is {0}".format(configProperties['save_all']))
|
||||
except KeyError:
|
||||
print("FYI, there is no save_all value stored in the database, using 'test'")
|
||||
configProperties['save_all'] = 'test'
|
||||
# configObj = {}
|
||||
# db.connect()
|
||||
# cur = db.cursor()
|
||||
# query = "SELECT parameter, val FROM config GROUP BY parameter;"
|
||||
# cur.execute(query)
|
||||
# config = cur.fetchall()
|
||||
# db.disconnect()
|
||||
# for x in config:
|
||||
# configObj[x[0]] = x[1]
|
||||
#
|
||||
# try:
|
||||
# configProperties['PLC_IP_ADDRESS'] = str(configObj['ip_address'])
|
||||
# print("FYI, using PLC IP Address from the database {0}".format(configProperties['PLC_IP_ADDRESS']))
|
||||
# except KeyError:
|
||||
# print("FYI, there is no PLC IP Address stored in the database, defaulting to 192.168.1.10")
|
||||
# configProperties['PLC_IP_ADDRESS'] = "192.168.1.10"
|
||||
#
|
||||
# try:
|
||||
# configProperties['plc_type'] = str(configObj['plc_type'])
|
||||
# print("FYI, using PLC Type from the database {0}".format(configProperties['plc_type']))
|
||||
# except KeyError:
|
||||
# print("FYI, there is no PLC Type stored in the database, defaulting to CLX")
|
||||
# configProperties['plc_type'] = "CLX"
|
||||
#
|
||||
# try:
|
||||
# configProperties['scan_rate'] = int(configObj['scan_rate'])
|
||||
# print("FYI, using Scan Rate from the database {0}".format(configProperties['scan_rate']))
|
||||
# except KeyError:
|
||||
# print("FYI, there is no Scan Rate stored in the database, defaulting to 10 seconds")
|
||||
# configProperties['scan_rate'] = 10
|
||||
#
|
||||
# try:
|
||||
# sa_test = str(configObj['save_all'])
|
||||
# if sa_test.lower() == "true":
|
||||
# configProperties['save_all'] = True
|
||||
# elif sa_test.lower() == "false":
|
||||
# configProperties['save_all'] = False
|
||||
# else:
|
||||
# configProperties['save_all'] = "test"
|
||||
# print("FYI, value for save_all is {0}".format(configProperties['save_all']))
|
||||
# except KeyError:
|
||||
# print("FYI, there is no save_all value stored in the database, using 'test'")
|
||||
# configProperties['save_all'] = 'test'
|
||||
|
||||
|
||||
|
||||
|
||||
for t in tags:
|
||||
tag_store[t[1]] = Sample(t[1], t[3], t[0], t[5], t[6], t[7], mapFn=t[8], device_type=configProperties['plc_type'], ip_address=configProperties['PLC_IP_ADDRESS'])
|
||||
for t in tags:
|
||||
# name, tag, db_id, data_type, change_threshold, guarantee_sec, mapFn=None, device_type='CLX', ip_address='192.168.1.10'):
|
||||
tag_store[t['name']] = Sample(t['name'], t['tag'],t['id'], t['data_type'], t['change_threshold'], t['guarantee_sec'], mapFn=t['map_function'], ip_address=t['deviceID']['address'])
|
||||
|
||||
|
||||
while True:
|
||||
for tag in tag_store:
|
||||
try:
|
||||
tag_store[tag].read(configProperties['save_all'])
|
||||
except:
|
||||
print("ERROR EVALUATING {}".format(tag))
|
||||
traceback.print_exc()
|
||||
time.sleep(configProperties['scan_rate'])
|
||||
while True:
|
||||
for tag in tag_store:
|
||||
try:
|
||||
tag_store[tag].read('test')
|
||||
except:
|
||||
print("ERROR EVALUATING {}".format(tag))
|
||||
traceback.print_exc()
|
||||
time.sleep(10)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
main()
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
connection: 'mysqlDb',
|
||||
tableName: 'data_types',
|
||||
attributes: {
|
||||
id: {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
connection: 'mysqlDb',
|
||||
tableName: 'devices',
|
||||
attributes: {
|
||||
id: {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
connection: 'mysqlDb',
|
||||
tableName: 'device_types',
|
||||
attributes: {
|
||||
id: {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
connection: 'mysqlDb',
|
||||
tableName: 'tags',
|
||||
attributes: {
|
||||
id: {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
connection: 'mysqlDb',
|
||||
tableName: 'tag_classes',
|
||||
attributes: {
|
||||
id: {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
connection: 'mysqlDb',
|
||||
tableName: 'tag_vals',
|
||||
attributes: {
|
||||
id: {
|
||||
|
||||
BIN
tagserverApp/assets/images/loading.gif
Normal file
BIN
tagserverApp/assets/images/loading.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
BIN
tagserverApp/assets/images/logo.png
Normal file
BIN
tagserverApp/assets/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
629
tagserverApp/assets/js/controller.js
Normal file
629
tagserverApp/assets/js/controller.js
Normal file
@@ -0,0 +1,629 @@
|
||||
var tsCtrlrs = angular.module('tsCtrlrs', ['ngJustGage', 'n3-line-chart', "ngQuickDate"]);
|
||||
|
||||
function isValidDate(d) {
|
||||
if ( Object.prototype.toString.call(d) !== "[object Date]" )
|
||||
return false;
|
||||
return !isNaN(d.getTime());
|
||||
}
|
||||
|
||||
tsCtrlrs.config(function(ngQuickDateDefaultsProvider) {
|
||||
// Configure with icons from font-awesome
|
||||
return ngQuickDateDefaultsProvider.set({
|
||||
closeButtonHtml: "<i class='fa fa-times'></i>",
|
||||
buttonIconHtml: "<i class='fa fa-clock-o'></i>",
|
||||
nextLinkHtml: "<i class='fa fa-chevron-right'></i>",
|
||||
prevLinkHtml: "<i class='fa fa-chevron-left'></i>",
|
||||
// Take advantage of Sugar.js date parsing
|
||||
parseDateFunction: function(str) {
|
||||
d = Date.create(str);
|
||||
return d.isValid() ? d : null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var dString_to_sqlite = function(dString){
|
||||
/**
|
||||
* Takes a date string in the form YYYYMMDD_HHmmSS and returns it in SQLite format (YYYY-MM-DD HH:mm:SS)
|
||||
* @param {String} dString
|
||||
* @return {String} sqliteString
|
||||
*/
|
||||
var re = /(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})/;
|
||||
var fd = re.exec(dString);
|
||||
if (fd){
|
||||
var sqliteString = "";
|
||||
return sqliteString.concat(fd[1], "-", fd[2], "-", fd[3], " ", fd[4], ":", fd[5], ":", fd[6]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
var sqlite_to_dString = function(sqliteDate){
|
||||
/**
|
||||
* Takes a sqlite date string in the form YYYY-MM-DD HH:mm:SS and returns it in format YYYYMMDD_HHmmSS
|
||||
* @param {String} sqliteDate
|
||||
* @return {String} dString
|
||||
*/
|
||||
var re = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/;
|
||||
var fd = re.exec(sqliteDate);
|
||||
if (fd){
|
||||
var dString = "";
|
||||
return dString.concat(fd[1], fd[2], fd[3], "_", fd[4], fd[5], fd[6]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
var date_to_dString = function(inpDate){
|
||||
var year = inpDate.getFullYear().pad(4);
|
||||
var month = (inpDate.getMonth() + 1).pad(2);
|
||||
var day = inpDate.getDate().pad(2);
|
||||
var hour = inpDate.getHours().pad(2);
|
||||
var min = inpDate.getMinutes().pad(2);
|
||||
var sec = inpDate.getSeconds().pad(2);
|
||||
return "".concat(year, month, day, "_", hour, min, sec);
|
||||
};
|
||||
|
||||
tsCtrlrs.factory('Page', function($log) {
|
||||
var title = 'default';
|
||||
var page = 'default';
|
||||
return {
|
||||
title: function() {
|
||||
return title;
|
||||
},
|
||||
setTitle: function(newTitle) {
|
||||
title = newTitle;
|
||||
},
|
||||
page: function() {
|
||||
return page;
|
||||
},
|
||||
setPage: function(newPage) {
|
||||
page = newPage;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
tsCtrlrs.factory('Alerts', function($log) {
|
||||
var alerts = [];
|
||||
return {
|
||||
add: function(alt) {
|
||||
alerts.push(alt);
|
||||
},
|
||||
remove: function(indx) {
|
||||
alerts.splice(indx, 1);
|
||||
},
|
||||
clear: function() {
|
||||
alerts = [];
|
||||
},
|
||||
get: function() {
|
||||
return alerts;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
tsCtrlrs.factory('tags',function($q, $http, $log){
|
||||
var getTag = function(id) {
|
||||
var deferred = $q.defer();
|
||||
$http.get('/json/tag/' + id).success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
tag:data.tags[0],
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var getTagList = function() {
|
||||
var deferred = $q.defer();
|
||||
$http.get('/json/tag/').success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
tags:data.tags,
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var getTagHistory = function(id){
|
||||
var deferred = $q.defer();
|
||||
$http.get('/json/series/'+ id + "/24").success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
vals:data.vals,
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var getTagHistoryBetween = function(id, start, end){
|
||||
var deferred = $q.defer();
|
||||
var url = '/json/valBetween/'+ id + "/" + date_to_dString(start) + "/" + date_to_dString(end);
|
||||
$log.info("getting value for: " + url);
|
||||
$http.get(url).success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
vals:data.vals,
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var getCurrentValues = function(){
|
||||
var deferred = $q.defer();
|
||||
$http.get('/json/all').success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
vals:data.vals,
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var createTag = function(tag){
|
||||
$http.post('/json/tag/add', {
|
||||
tag: tag.tag,
|
||||
name: tag.name,
|
||||
units: tag.units,
|
||||
minExpected: tag.minExpected,
|
||||
maxExpected: tag.maxExpected,
|
||||
guarantee_sec: tag.guarantee_sec,
|
||||
change_threshold: tag.change_threshold,
|
||||
description: tag.description,
|
||||
data_type: tag.data_type
|
||||
}).success(function(data){
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
var updateTag = function(tag){
|
||||
$log.info("updateTag called with "+ JSON.stringify(tag));
|
||||
$http.post('/json/tag/update', {
|
||||
id: tag.id,
|
||||
tag: tag.tag,
|
||||
name: tag.name,
|
||||
units: tag.units,
|
||||
minExpected: tag.minExpected,
|
||||
maxExpected: tag.maxExpected,
|
||||
guarantee_sec: tag.guarantee_sec,
|
||||
change_threshold: tag.change_threshold,
|
||||
description: tag.description,
|
||||
data_type: tag.data_type
|
||||
}).success(function(data){
|
||||
return data;
|
||||
}).error(function(err){
|
||||
$log.warn("updateTag Error: " + err);
|
||||
});
|
||||
};
|
||||
|
||||
var deleteTag = function(id){
|
||||
var deferred = $q.defer();
|
||||
var url = '/json/tag/delete/' + id;
|
||||
$http.get(url).success(function(data) {
|
||||
deferred.resolve({
|
||||
status: data.status
|
||||
});
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var clearSingleTagData = function(id){
|
||||
var deferred = $q.defer();
|
||||
var url = '/json/clearDatabase/' + id;
|
||||
$http.get(url).success(function(data) {
|
||||
deferred.resolve({
|
||||
status: data.status
|
||||
});
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var clearAllTagData = function(){
|
||||
var deferred = $q.defer();
|
||||
var url = '/json/clearDatabase/all';
|
||||
$http.get(url).success(function(data) {
|
||||
deferred.resolve({
|
||||
status: data.status
|
||||
});
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
return {
|
||||
getTag: getTag,
|
||||
getTagList: getTagList,
|
||||
getTagHistory: getTagHistory,
|
||||
getTagHistoryBetween: getTagHistoryBetween,
|
||||
getCurrentValues: getCurrentValues,
|
||||
createTag: createTag,
|
||||
updateTag: updateTag,
|
||||
deleteTag: deleteTag,
|
||||
clearSingleTagData: clearSingleTagData,
|
||||
clearAllTagData: clearAllTagData
|
||||
};
|
||||
});
|
||||
|
||||
tsCtrlrs.factory('config',function($q, $http, $log){
|
||||
|
||||
var getConfig = function(){
|
||||
var deferred = $q.defer();
|
||||
$http.get('/json/config/').success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
config:data.config,
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var submitParameter = function(entry){
|
||||
$http.post('/json/config', {
|
||||
parameter: entry.parameter,
|
||||
val: entry.val
|
||||
}).success(function(data){
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
var getLoggerStatus = function(){
|
||||
var deferred = $q.defer();
|
||||
$http.get('/json/logger/status').success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
running:data.running,
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message,
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var restartLogger = function(){
|
||||
var deferred = $q.defer();
|
||||
$http.get('/json/logger/restart').success(function(data) {
|
||||
if(data.status == "OK"){
|
||||
deferred.resolve({
|
||||
status: data.status
|
||||
});
|
||||
} else {
|
||||
deferred.resolve({
|
||||
status:data.status,
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
getConfig:getConfig,
|
||||
submitParameter: submitParameter,
|
||||
getLoggerStatus: getLoggerStatus,
|
||||
restartLogger: restartLogger
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
tsCtrlrs.controller('mainCtrl', function($scope, Page, Alerts) {
|
||||
$scope.Page = Page;
|
||||
$scope.Alerts = Alerts;
|
||||
});
|
||||
|
||||
tsCtrlrs.controller('dashboardCtrl', function($scope, $route, $http, $routeParams, Page, Alerts, $log, tags) {
|
||||
Page.setTitle('Dashboard');
|
||||
Page.setPage('dashboard');
|
||||
$scope.loadDashboard = function(){
|
||||
$scope.loading = true;
|
||||
var getCurrentValues = tags.getCurrentValues();
|
||||
getCurrentValues.then(function(data) {
|
||||
$scope.loading = false;
|
||||
if (data.status == "OK"){
|
||||
$scope.vals = data.vals;
|
||||
$scope.error = false;
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.loadDashboard();
|
||||
});
|
||||
|
||||
tsCtrlrs.controller('tagsCtrl', function($scope, $route, $http, $routeParams, Page, Alerts, $log, tags) {
|
||||
Page.setTitle('Tags');
|
||||
Page.setPage('tags');
|
||||
$scope.loadTagList = function(){
|
||||
$scope.loading = true;
|
||||
var getTagList = tags.getTagList();
|
||||
getTagList.then(function(data) {
|
||||
$scope.loading = false;
|
||||
if (data.status == "OK"){
|
||||
$scope.tags = data.tags;
|
||||
$scope.error = false;
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.loadTagList();
|
||||
|
||||
$scope.submitAddTag = function(){
|
||||
var createStatus = tags.createTag($scope.newTag);
|
||||
$scope.createStatus = createStatus.status;
|
||||
$scope.loadTagList();
|
||||
};
|
||||
|
||||
$scope.openDeleteTag = function(id){
|
||||
var getTag = tags.getTag(id);
|
||||
getTag.then(function(data){
|
||||
if (data.status == "OK"){
|
||||
$scope.error = false;
|
||||
$scope.dTag = data.tag;
|
||||
$log.info("Thinking about deleting tag with parameters: "+ JSON.stringify($scope.dTag));
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteTag = function(id){
|
||||
var deleteTag = tags.deleteTag(id);
|
||||
deleteTag.then(function(data){
|
||||
$log.info("deleting tag "+ id + " status: " + data.status);
|
||||
if (data.status == "OK"){
|
||||
$scope.error = false;
|
||||
$scope.loadTagList();
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openClearTagData = function(id){
|
||||
var getTag = tags.getTag(id);
|
||||
getTag.then(function(data){
|
||||
if (data.status == "OK"){
|
||||
$scope.error = false;
|
||||
$scope.dTagValues = data.tag;
|
||||
$log.info("Thinking about deleting tag data with parameters: "+ JSON.stringify($scope.dTagValues));
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteTagValues = function(id){
|
||||
var clearSingleTagData = tags.clearSingleTagData(id);
|
||||
clearSingleTagData.then(function(data){
|
||||
$log.info("deleting tag "+ id + " status: " + data.status);
|
||||
if (data.status == "OK"){
|
||||
$scope.error = false;
|
||||
$scope.loadTagList();
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openEditTag = function(id){
|
||||
var getTag = tags.getTag(id);
|
||||
getTag.then(function(data){
|
||||
if (data.status == "OK"){
|
||||
$scope.error = false;
|
||||
$scope.editTag = data.tag;
|
||||
$log.info("Started editing tag with parameters: "+ JSON.stringify($scope.editTag));
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.submitEditTag = function(){
|
||||
var editStatus = tags.updateTag($scope.editTag);
|
||||
$log.info(editStatus);
|
||||
$scope.editStatus = editStatus.status;
|
||||
$scope.loadTagList();
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
tsCtrlrs.controller('tagValsCtrl', function($scope, $route, $http, $routeParams, Page, Alerts, $log, tags) {
|
||||
Page.setTitle('Tag Series');
|
||||
Page.setPage('tags');
|
||||
|
||||
if ($routeParams.endDatetime){
|
||||
$scope.endDatetime = Date.parse(dString_to_sqlite($routeParams.endDatetime));
|
||||
} else {
|
||||
$scope.endDatetime = new Date();
|
||||
}
|
||||
|
||||
if ($routeParams.startDatetime){
|
||||
$scope.startDatetime = Date.parse(dString_to_sqlite($routeParams.startDatetime));
|
||||
} else {
|
||||
$scope.startDatetime = new Date();
|
||||
$scope.startDatetime.setHours($scope.endDatetime.getHours() - 2);
|
||||
}
|
||||
|
||||
$scope.loadTagVals = function(sDTime, eDTime){
|
||||
$scope.loading = true;
|
||||
var getTag = tags.getTag($routeParams.tagID);
|
||||
getTag.then(function(tagData){
|
||||
if (tagData.status == "OK"){
|
||||
$scope.tag = tagData.tag;
|
||||
Page.setTitle('Tag Series: '+ tagData.tag.tagName);
|
||||
var getTagHistoryBetween = tags.getTagHistoryBetween($routeParams.tagID, sDTime, eDTime);
|
||||
getTagHistoryBetween.then(function(data) {
|
||||
$scope.loading = false;
|
||||
if (data.status == "OK"){
|
||||
$scope.data = data;
|
||||
$scope.data.vals = $scope.data.vals.map(function(x){
|
||||
return {id: x.id, tagID: x.tagID, val: x.val, dtime: new Date(x.dtime)};
|
||||
});
|
||||
$scope.error = false;
|
||||
|
||||
$scope.options = {
|
||||
series: [
|
||||
{
|
||||
axis: "y",
|
||||
dataset: "vals",
|
||||
key: "val",
|
||||
label: "Tag Value",
|
||||
color: "#1f77b4",
|
||||
type: ['line'],
|
||||
id: 'tagChart'
|
||||
}
|
||||
],
|
||||
axes: {
|
||||
x: {
|
||||
key: "dtime",
|
||||
type: "date"
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$scope.loading = false;
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.loadTagVals($scope.startDatetime, $scope.endDatetime);
|
||||
});
|
||||
|
||||
tsCtrlrs.controller('configCtrl', function($scope, Page, Alerts, $log, config) {
|
||||
Page.setTitle('Configuration');
|
||||
Page.setPage('configuration');
|
||||
|
||||
|
||||
|
||||
$scope.loadConfig = function(){
|
||||
$scope.loading = true;
|
||||
var getConfig = config.getConfig();
|
||||
getConfig.then(function(data) {
|
||||
$scope.loading = false;
|
||||
if (data.status == "OK"){
|
||||
$scope.config = data.config;
|
||||
$scope.error = false;
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.loadConfig();
|
||||
$scope.paramError = null;
|
||||
var selString = "Select a parameter...";
|
||||
$scope.newParam = {
|
||||
pSelected: selString,
|
||||
parameter: null,
|
||||
val: null
|
||||
};
|
||||
|
||||
$scope.addParameter = function(){
|
||||
if ($scope.newParam.pSelected == selString){
|
||||
$scope.paramError = "No parameter selected";
|
||||
} else {
|
||||
if ($scope.newParam.pSelected == "other") {
|
||||
$scope.newParam.parameter = $scope.newParam.pEntry;
|
||||
} else {
|
||||
$scope.newParam.parameter = $scope.newParam.pSelected;
|
||||
}
|
||||
config.submitParameter($scope.newParam);
|
||||
$scope.loadConfig();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.checkLogger = function(){
|
||||
$scope.loggerLoading = true;
|
||||
var checkLoggerStatus = config.getLoggerStatus();
|
||||
checkLoggerStatus.then(function(data){
|
||||
$scope.loggerLoading = false;
|
||||
if (data.status == "OK"){
|
||||
$scope.loggerRunning = data.running;
|
||||
$scope.error = false;
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.checkLogger();
|
||||
|
||||
$scope.restartLogger = function(){
|
||||
var restartLogger = config.restartLogger();
|
||||
restartLogger.then(function(data){
|
||||
if (data.status == "OK"){
|
||||
$scope.error = false;
|
||||
$scope.checkLogger();
|
||||
} else {
|
||||
$scope.error = data.message;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
//*---- FILTERS -----*//
|
||||
tsCtrlrs.filter('dString', function myDateFormat($filter){
|
||||
return function(text){
|
||||
var tempdate= new Date(text);
|
||||
return $filter('date')(tempdate, "yyyyMMdd'_'HHmmss");
|
||||
};
|
||||
});
|
||||
|
||||
tsCtrlrs.filter('sqlite_to_local', function sqliteformat($filter){
|
||||
return function(text){
|
||||
var utcdate= new Date(text + " UTC");
|
||||
return $filter('date')(utcdate, "yyyy-MM-dd hh:mm:ss a");
|
||||
};
|
||||
});
|
||||
132
tagserverApp/assets/js/dependencies/sugar.min.js
vendored
Normal file
132
tagserverApp/assets/js/dependencies/sugar.min.js
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Sugar Library v1.4.1
|
||||
*
|
||||
* Freely distributable and licensed under the MIT-style license.
|
||||
* Copyright (c) 2014 Andrew Plummer
|
||||
* http://sugarjs.com/
|
||||
*
|
||||
* ---------------------------- */
|
||||
(function(){function aa(a){return function(){return a}}
|
||||
var m=Object,p=Array,q=RegExp,r=Date,s=String,t=Number,u=Math,ba="undefined"!==typeof global?global:this,v=m.prototype.toString,da=m.prototype.hasOwnProperty,ea=m.defineProperty&&m.defineProperties,fa="function"===typeof q(),ga=!("0"in new s("a")),ia={},ja=/^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/,w="Boolean Number String Array Date RegExp Function".split(" "),la=ka("boolean",w[0]),y=ka("number",w[1]),z=ka("string",w[2]),A=ma(w[3]),C=ma(w[4]),D=ma(w[5]),F=ma(w[6]);
|
||||
function ma(a){var b="Array"===a&&p.isArray||function(b,d){return(d||v.call(b))==="[object "+a+"]"};return ia[a]=b}function ka(a,b){function c(c){return G(c)?v.call(c)==="[object "+b+"]":typeof c===a}return ia[b]=c}
|
||||
function na(a){a.SugarMethods||(oa(a,"SugarMethods",{}),H(a,!1,!0,{extend:function(b,c,d){H(a,!1!==d,c,b)},sugarRestore:function(){return pa(this,a,arguments,function(a,c,d){oa(a,c,d.method)})},sugarRevert:function(){return pa(this,a,arguments,function(a,c,d){d.existed?oa(a,c,d.original):delete a[c]})}}))}function H(a,b,c,d){var e=b?a.prototype:a;na(a);I(d,function(d,f){var h=e[d],l=J(e,d);F(c)&&h&&(f=qa(h,f,c));!1===c&&h||oa(e,d,f);a.SugarMethods[d]={method:f,existed:l,original:h,instance:b}})}
|
||||
function K(a,b,c,d,e){var g={};d=z(d)?d.split(","):d;d.forEach(function(a,b){e(g,a,b)});H(a,b,c,g)}function pa(a,b,c,d){var e=0===c.length,g=L(c),f=!1;I(b.SugarMethods,function(b,c){if(e||-1!==g.indexOf(b))f=!0,d(c.instance?a.prototype:a,b,c)});return f}function qa(a,b,c){return function(d){return c.apply(this,arguments)?b.apply(this,arguments):a.apply(this,arguments)}}function oa(a,b,c){ea?m.defineProperty(a,b,{value:c,configurable:!0,enumerable:!1,writable:!0}):a[b]=c}
|
||||
function L(a,b,c){var d=[];c=c||0;var e;for(e=a.length;c<e;c++)d.push(a[c]),b&&b.call(a,a[c],c);return d}function sa(a,b,c){var d=a[c||0];A(d)&&(a=d,c=0);L(a,b,c)}function ta(a){if(!a||!a.call)throw new TypeError("Callback is not callable");}function M(a){return void 0!==a}function N(a){return void 0===a}function J(a,b){return!!a&&da.call(a,b)}function G(a){return!!a&&("object"===typeof a||fa&&D(a))}function ua(a){var b=typeof a;return null==a||"string"===b||"number"===b||"boolean"===b}
|
||||
function va(a,b){b=b||v.call(a);try{if(a&&a.constructor&&!J(a,"constructor")&&!J(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}return!!a&&"[object Object]"===b&&"hasOwnProperty"in a}function I(a,b){for(var c in a)if(J(a,c)&&!1===b.call(a,c,a[c],a))break}function wa(a,b){for(var c=0;c<a;c++)b(c)}function xa(a,b){I(b,function(c){a[c]=b[c]});return a}function ya(a){ua(a)&&(a=m(a));if(ga&&z(a))for(var b=a,c=0,d;d=b.charAt(c);)b[c++]=d;return a}function O(a){xa(this,ya(a))}
|
||||
O.prototype.constructor=m;var P=u.abs,za=u.pow,Aa=u.ceil,Q=u.floor,R=u.round,Ca=u.min,S=u.max;function Da(a,b,c){var d=za(10,P(b||0));c=c||R;0>b&&(d=1/d);return c(a*d)/d}var Ea=48,Fa=57,Ga=65296,Ha=65305,Ia=".",Ja="",Ka={},La;function Ma(){return"\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u2028\u2029\u3000\ufeff"}function Na(a,b){var c="";for(a=a.toString();0<b;)if(b&1&&(c+=a),b>>=1)a+=a;return c}
|
||||
function Oa(a,b){var c,d;c=a.replace(La,function(a){a=Ka[a];a===Ia&&(d=!0);return a});return d?parseFloat(c):parseInt(c,b||10)}function T(a,b,c,d){d=P(a).toString(d||10);d=Na("0",b-d.replace(/\.\d+/,"").length)+d;if(c||0>a)d=(0>a?"-":"+")+d;return d}function Pa(a){if(11<=a&&13>=a)return"th";switch(a%10){case 1:return"st";case 2:return"nd";case 3:return"rd";default:return"th"}}
|
||||
function Qa(a,b){function c(a,c){if(a||-1<b.indexOf(c))d+=c}var d="";b=b||"";c(a.multiline,"m");c(a.ignoreCase,"i");c(a.global,"g");c(a.u,"y");return d}function Ra(a){z(a)||(a=s(a));return a.replace(/([\\/\'*+?|()\[\]{}.^$])/g,"\\$1")}function U(a,b){return a["get"+(a._utc?"UTC":"")+b]()}function Sa(a,b,c){return a["set"+(a._utc&&"ISOWeek"!=b?"UTC":"")+b](c)}
|
||||
function Ta(a,b){var c=typeof a,d,e,g,f,h,l,n;if("string"===c)return a;g=v.call(a);d=va(a,g);e=A(a,g);if(null!=a&&d||e){b||(b=[]);if(1<b.length)for(l=b.length;l--;)if(b[l]===a)return"CYC";b.push(a);d=a.valueOf()+s(a.constructor);f=e?a:m.keys(a).sort();l=0;for(n=f.length;l<n;l++)h=e?l:f[l],d+=h+Ta(a[h],b);b.pop()}else d=-Infinity===1/a?"-0":s(a&&a.valueOf?a.valueOf():a);return c+g+d}function Ua(a,b){return a===b?0!==a||1/a===1/b:Va(a)&&Va(b)?Ta(a)===Ta(b):!1}
|
||||
function Va(a){var b=v.call(a);return ja.test(b)||va(a,b)}function Wa(a,b,c){var d,e=a.length,g=b.length,f=!1!==b[g-1];if(!(g>(f?1:2)))return Xa(a,e,b[0],f,c);d=[];L(b,function(b){if(la(b))return!1;d.push(Xa(a,e,b,f,c))});return d}function Xa(a,b,c,d,e){d&&(c%=b,0>c&&(c=b+c));return e?a.charAt(c):a[c]}function Ya(a,b){K(b,!0,!1,a,function(a,b){a[b+("equal"===b?"s":"")]=function(){return m[b].apply(null,[this].concat(L(arguments)))}})}na(m);I(w,function(a,b){na(ba[b])});var Za,$a;
|
||||
for($a=0;9>=$a;$a++)Za=s.fromCharCode($a+Ga),Ja+=Za,Ka[Za]=s.fromCharCode($a+Ea);Ka[","]="";Ka["\uff0e"]=Ia;Ka[Ia]=Ia;La=q("["+Ja+"\uff0e,"+Ia+"]","g");
|
||||
"use strict";H(m,!1,!1,{keys:function(a){var b=[];if(!G(a)&&!D(a)&&!F(a))throw new TypeError("Object required");I(a,function(a){b.push(a)});return b}});
|
||||
function ab(a,b,c,d){var e=a.length,g=-1==d,f=g?e-1:0;c=isNaN(c)?f:parseInt(c>>0);0>c&&(c=e+c);if(!g&&0>c||g&&c>=e)c=f;for(;g&&0<=c||!g&&c<e;){if(a[c]===b)return c;c+=d}return-1}function bb(a,b,c,d){var e=a.length,g=0,f=M(c);ta(b);if(0!=e||f)f||(c=a[d?e-1:g],g++);else throw new TypeError("Reduce called on empty array with no initial value");for(;g<e;)f=d?e-g-1:g,f in a&&(c=b(c,a[f],f,a)),g++;return c}function cb(a){if(0===a.length)throw new TypeError("First argument must be defined");}H(p,!1,!1,{isArray:function(a){return A(a)}});
|
||||
H(p,!0,!1,{every:function(a,b){var c=this.length,d=0;for(cb(arguments);d<c;){if(d in this&&!a.call(b,this[d],d,this))return!1;d++}return!0},some:function(a,b){var c=this.length,d=0;for(cb(arguments);d<c;){if(d in this&&a.call(b,this[d],d,this))return!0;d++}return!1},map:function(a,b){b=arguments[1];var c=this.length,d=0,e=Array(c);for(cb(arguments);d<c;)d in this&&(e[d]=a.call(b,this[d],d,this)),d++;return e},filter:function(a){var b=arguments[1],c=this.length,d=0,e=[];for(cb(arguments);d<c;)d in
|
||||
this&&a.call(b,this[d],d,this)&&e.push(this[d]),d++;return e},indexOf:function(a,b){return z(this)?this.indexOf(a,b):ab(this,a,b,1)},lastIndexOf:function(a,b){return z(this)?this.lastIndexOf(a,b):ab(this,a,b,-1)},forEach:function(a,b){var c=this.length,d=0;for(ta(a);d<c;)d in this&&a.call(b,this[d],d,this),d++},reduce:function(a,b){return bb(this,a,b)},reduceRight:function(a,b){return bb(this,a,b,!0)}});
|
||||
H(Function,!0,!1,{bind:function(a){var b=this,c=L(arguments,null,1),d;if(!F(this))throw new TypeError("Function.prototype.bind called on a non-function");d=function(){return b.apply(b.prototype&&this instanceof b?this:a,c.concat(L(arguments)))};d.prototype=this.prototype;return d}});H(r,!1,!1,{now:function(){return(new r).getTime()}});
|
||||
(function(){var a=Ma().match(/^\s+$/);try{s.prototype.trim.call([1])}catch(b){a=!1}H(s,!0,!a,{trim:function(){return this.toString().trimLeft().trimRight()},trimLeft:function(){return this.replace(q("^["+Ma()+"]+"),"")},trimRight:function(){return this.replace(q("["+Ma()+"]+$"),"")}})})();
|
||||
(function(){var a=new r(r.UTC(1999,11,31)),a=a.toISOString&&"1999-12-31T00:00:00.000Z"===a.toISOString();K(r,!0,!a,"toISOString,toJSON",function(a,c){a[c]=function(){return T(this.getUTCFullYear(),4)+"-"+T(this.getUTCMonth()+1,2)+"-"+T(this.getUTCDate(),2)+"T"+T(this.getUTCHours(),2)+":"+T(this.getUTCMinutes(),2)+":"+T(this.getUTCSeconds(),2)+"."+T(this.getUTCMilliseconds(),3)+"Z"}})})();
|
||||
"use strict";function db(a){a=q(a);return function(b){return a.test(b)}}
|
||||
function eb(a){var b=a.getTime();return function(a){return!(!a||!a.getTime)&&a.getTime()===b}}function fb(a){return function(b,c,d){return b===a||a.call(this,b,c,d)}}function gb(a){return function(b,c,d){return b===a||a.call(d,c,b,d)}}function hb(a,b){var c={};return function(d,e,g){var f;if(!G(d))return!1;for(f in a)if(c[f]=c[f]||ib(a[f],b),!1===c[f].call(g,d[f],e,g))return!1;return!0}}function jb(a){return function(b){return b===a||Ua(b,a)}}
|
||||
function ib(a,b){if(!ua(a)){if(D(a))return db(a);if(C(a))return eb(a);if(F(a))return b?gb(a):fb(a);if(va(a))return hb(a,b)}return jb(a)}function kb(a,b,c,d){return b?b.apply?b.apply(c,d||[]):F(a[b])?a[b].call(a):a[b]:a}function V(a,b,c,d){var e=+a.length;0>c&&(c=a.length+c);c=isNaN(c)?0:c;for(!0===d&&(e+=c);c<e;){d=c%a.length;if(!(d in a)){lb(a,b,c);break}if(!1===b.call(a,a[d],d,a))break;c++}}
|
||||
function lb(a,b,c){var d=[],e;for(e in a)e in a&&(e>>>0==e&&4294967295!=e)&&e>=c&&d.push(parseInt(e));d.sort().each(function(c){return b.call(a,a[c],c,a)})}function mb(a,b,c,d,e,g){var f,h,l;0<a.length&&(l=ib(b),V(a,function(b,c){if(l.call(g,b,c,a))return f=b,h=c,!1},c,d));return e?h:f}function nb(a,b){var c=[],d={},e;V(a,function(g,f){e=b?kb(g,b,a,[g,f,a]):g;ob(d,e)||c.push(g)});return c}
|
||||
function pb(a,b,c){var d=[],e={};b.each(function(a){ob(e,a)});a.each(function(a){var b=Ta(a),h=!Va(a);if(qb(e,b,a,h)!==c){var l=0;if(h)for(b=e[b];l<b.length;)b[l]===a?b.splice(l,1):l+=1;else delete e[b];d.push(a)}});return d}function rb(a,b,c){b=b||Infinity;c=c||0;var d=[];V(a,function(a){A(a)&&c<b?d=d.concat(rb(a,b,c+1)):d.push(a)});return d}function sb(a){var b=[];L(a,function(a){b=b.concat(a)});return b}function qb(a,b,c,d){var e=b in a;d&&(a[b]||(a[b]=[]),e=-1!==a[b].indexOf(c));return e}
|
||||
function ob(a,b){var c=Ta(b),d=!Va(b),e=qb(a,c,b,d);d?a[c].push(b):a[c]=b;return e}function tb(a,b,c,d){var e,g,f,h=[],l="max"===c,n="min"===c,x=p.isArray(a);for(e in a)if(a.hasOwnProperty(e)){c=a[e];f=kb(c,b,a,x?[c,parseInt(e),a]:[]);if(N(f))throw new TypeError("Cannot compare with undefined");if(f===g)h.push(c);else if(N(g)||l&&f>g||n&&f<g)h=[c],g=f}x||(h=rb(h,1));return d?h:h[0]}
|
||||
function ub(a,b){var c,d,e,g,f=0,h=0;c=p[xb];d=p[yb];var l=p[zb],n=p[Ab],x=p[Bb];a=Cb(a,c,d);b=Cb(b,c,d);do c=a.charAt(f),e=l[c]||c,c=b.charAt(f),g=l[c]||c,c=e?n.indexOf(e):null,d=g?n.indexOf(g):null,-1===c||-1===d?(c=a.charCodeAt(f)||null,d=b.charCodeAt(f)||null,x&&((c>=Ea&&c<=Fa||c>=Ga&&c<=Ha)&&(d>=Ea&&d<=Fa||d>=Ga&&d<=Ha))&&(c=Oa(a.slice(f)),d=Oa(b.slice(f)))):(e=e!==a.charAt(f),g=g!==b.charAt(f),e!==g&&0===h&&(h=e-g)),f+=1;while(null!=c&&null!=d&&c===d);return c===d?h:c-d}
|
||||
function Cb(a,b,c){z(a)||(a=s(a));c&&(a=a.toLowerCase());b&&(a=a.replace(b,""));return a}var Ab="AlphanumericSortOrder",xb="AlphanumericSortIgnore",yb="AlphanumericSortIgnoreCase",zb="AlphanumericSortEquivalents",Bb="AlphanumericSortNatural";H(p,!1,!0,{create:function(){var a=[];L(arguments,function(b){if(!ua(b)&&"length"in b&&("[object Arguments]"===v.call(b)||b.callee)||!ua(b)&&"length"in b&&!z(b)&&!va(b))b=p.prototype.slice.call(b,0);a=a.concat(b)});return a}});
|
||||
H(p,!0,!1,{find:function(a,b){ta(a);return mb(this,a,0,!1,!1,b)},findIndex:function(a,b){var c;ta(a);c=mb(this,a,0,!1,!0,b);return N(c)?-1:c}});
|
||||
H(p,!0,!0,{findFrom:function(a,b,c){return mb(this,a,b,c)},findIndexFrom:function(a,b,c){b=mb(this,a,b,c,!0);return N(b)?-1:b},findAll:function(a,b,c){var d=[],e;0<this.length&&(e=ib(a),V(this,function(a,b,c){e(a,b,c)&&d.push(a)},b,c));return d},count:function(a){return N(a)?this.length:this.findAll(a).length},removeAt:function(a,b){if(N(a))return this;N(b)&&(b=a);this.splice(a,b-a+1);return this},include:function(a,b){return this.clone().add(a,b)},exclude:function(){return p.prototype.remove.apply(this.clone(),
|
||||
arguments)},clone:function(){return xa([],this)},unique:function(a){return nb(this,a)},flatten:function(a){return rb(this,a)},union:function(){return nb(this.concat(sb(arguments)))},intersect:function(){return pb(this,sb(arguments),!1)},subtract:function(a){return pb(this,sb(arguments),!0)},at:function(){return Wa(this,arguments)},first:function(a){if(N(a))return this[0];0>a&&(a=0);return this.slice(0,a)},last:function(a){return N(a)?this[this.length-1]:this.slice(0>this.length-a?0:this.length-a)},
|
||||
from:function(a){return this.slice(a)},to:function(a){N(a)&&(a=this.length);return this.slice(0,a)},min:function(a,b){return tb(this,a,"min",b)},max:function(a,b){return tb(this,a,"max",b)},least:function(a,b){return tb(this.groupBy.apply(this,[a]),"length","min",b)},most:function(a,b){return tb(this.groupBy.apply(this,[a]),"length","max",b)},sum:function(a){a=a?this.map(a):this;return 0<a.length?a.reduce(function(a,c){return a+c}):0},average:function(a){a=a?this.map(a):this;return 0<a.length?a.sum()/
|
||||
a.length:0},inGroups:function(a,b){var c=1<arguments.length,d=this,e=[],g=Aa(this.length/a);wa(a,function(a){a*=g;var h=d.slice(a,a+g);c&&h.length<g&&wa(g-h.length,function(){h=h.add(b)});e.push(h)});return e},inGroupsOf:function(a,b){var c=[],d=this.length,e=this,g;if(0===d||0===a)return e;N(a)&&(a=1);N(b)&&(b=null);wa(Aa(d/a),function(d){for(g=e.slice(a*d,a*d+a);g.length<a;)g.push(b);c.push(g)});return c},isEmpty:function(){return 0==this.compact().length},sortBy:function(a,b){var c=this.clone();
|
||||
c.sort(function(d,e){var g,f;g=kb(d,a,c,[d]);f=kb(e,a,c,[e]);return(z(g)&&z(f)?ub(g,f):g<f?-1:g>f?1:0)*(b?-1:1)});return c},randomize:function(){for(var a=this.concat(),b=a.length,c,d;b;)c=u.random()*b|0,d=a[--b],a[b]=a[c],a[c]=d;return a},zip:function(){var a=L(arguments);return this.map(function(b,c){return[b].concat(a.map(function(a){return c in a?a[c]:null}))})},sample:function(a){var b=this.randomize();return 0<arguments.length?b.slice(0,a):b[0]},each:function(a,b,c){V(this,a,b,c);return this},
|
||||
add:function(a,b){if(!y(t(b))||isNaN(b))b=this.length;p.prototype.splice.apply(this,[b,0].concat(a));return this},remove:function(){var a=this;L(arguments,function(b){var c=0;for(b=ib(b);c<a.length;)b(a[c],c,a)?a.splice(c,1):c++});return a},compact:function(a){var b=[];V(this,function(c){A(c)?b.push(c.compact()):a&&c?b.push(c):a||(null==c||c.valueOf()!==c.valueOf())||b.push(c)});return b},groupBy:function(a,b){var c=this,d={},e;V(c,function(b,f){e=kb(b,a,c,[b,f,c]);d[e]||(d[e]=[]);d[e].push(b)});
|
||||
b&&I(d,b);return d},none:function(){return!this.any.apply(this,arguments)}});H(p,!0,!0,{all:p.prototype.every,any:p.prototype.some,insert:p.prototype.add});function Db(a,b){K(m,!1,!0,a,function(a,d){a[d]=function(a,c,f){var h=m.keys(ya(a)),l;b||(l=ib(c,!0));f=p.prototype[d].call(h,function(d){var f=a[d];return b?kb(f,c,a,[d,f,a]):l(f,d,a)},f);A(f)&&(f=f.reduce(function(b,c){b[c]=a[c];return b},{}));return f}});Ya(a,O)}
|
||||
H(m,!1,!0,{map:function(a,b){var c={},d,e;for(d in a)J(a,d)&&(e=a[d],c[d]=kb(e,b,a,[d,e,a]));return c},reduce:function(a){var b=m.keys(ya(a)).map(function(b){return a[b]});return b.reduce.apply(b,L(arguments,null,1))},each:function(a,b){ta(b);I(a,b);return a},size:function(a){return m.keys(ya(a)).length}});var Eb="any all none count find findAll isEmpty".split(" "),Fb="sum average min max least most".split(" "),Gb=["map","reduce","size"],Hb=Eb.concat(Fb).concat(Gb);
|
||||
(function(){function a(){var a=arguments;return 0<a.length&&!F(a[0])}var b=p.prototype.map;K(p,!0,a,"every,all,some,filter,any,none,find,findIndex",function(a,b){var e=p.prototype[b];a[b]=function(a){var b=ib(a);return e.call(this,function(a,c){return b(a,c,this)})}});H(p,!0,a,{map:function(a){return b.call(this,function(b,e){return kb(b,a,this,[b,e,this])})}})})();
|
||||
(function(){p[Ab]="A\u00c1\u00c0\u00c2\u00c3\u0104BC\u0106\u010c\u00c7D\u010e\u00d0E\u00c9\u00c8\u011a\u00ca\u00cb\u0118FG\u011eH\u0131I\u00cd\u00cc\u0130\u00ce\u00cfJKL\u0141MN\u0143\u0147\u00d1O\u00d3\u00d2\u00d4PQR\u0158S\u015a\u0160\u015eT\u0164U\u00da\u00d9\u016e\u00db\u00dcVWXY\u00ddZ\u0179\u017b\u017d\u00de\u00c6\u0152\u00d8\u00d5\u00c5\u00c4\u00d6".split("").map(function(a){return a+a.toLowerCase()}).join("");var a={};V("A\u00c1\u00c0\u00c2\u00c3\u00c4 C\u00c7 E\u00c9\u00c8\u00ca\u00cb I\u00cd\u00cc\u0130\u00ce\u00cf O\u00d3\u00d2\u00d4\u00d5\u00d6 S\u00df U\u00da\u00d9\u00db\u00dc".split(" "),
|
||||
function(b){var c=b.charAt(0);V(b.slice(1).split(""),function(b){a[b]=c;a[b.toLowerCase()]=c.toLowerCase()})});p[Bb]=!0;p[yb]=!0;p[zb]=a})();Db(Eb);Db(Fb,!0);Ya(Gb,O);p.AlphanumericSort=ub;
|
||||
"use strict";
|
||||
var W,Ib,Jb="ampm hour minute second ampm utc offset_sign offset_hours offset_minutes ampm".split(" "),Kb="({t})?\\s*(\\d{1,2}(?:[,.]\\d+)?)(?:{h}([0-5]\\d(?:[,.]\\d+)?)?{m}(?::?([0-5]\\d(?:[,.]\\d+)?){s})?\\s*(?:({t})|(Z)|(?:([+-])(\\d{2,2})(?::?(\\d{2,2}))?)?)?|\\s*({t}))",Lb={},Mb,Nb,Ob,Pb=[],Qb={},X={yyyy:function(a){return U(a,"FullYear")},yy:function(a){return U(a,"FullYear")%100},ord:function(a){a=U(a,"Date");return a+Pa(a)},tz:function(a){return a.getUTCOffset()},isotz:function(a){return a.getUTCOffset(!0)},
|
||||
Z:function(a){return a.getUTCOffset()},ZZ:function(a){return a.getUTCOffset().replace(/(\d{2})$/,":$1")}},Rb=[{name:"year",method:"FullYear",k:!0,b:function(a){return 864E5*(365+(a?a.isLeapYear()?1:0:0.25))}},{name:"month",error:0.919,method:"Month",k:!0,b:function(a,b){var c=30.4375,d;a&&(d=a.daysInMonth(),b<=d.days()&&(c=d));return 864E5*c}},{name:"week",method:"ISOWeek",b:aa(6048E5)},{name:"day",error:0.958,method:"Date",k:!0,b:aa(864E5)},{name:"hour",method:"Hours",b:aa(36E5)},{name:"minute",
|
||||
method:"Minutes",b:aa(6E4)},{name:"second",method:"Seconds",b:aa(1E3)},{name:"millisecond",method:"Milliseconds",b:aa(1)}],Sb={};function Tb(a){xa(this,a);this.g=Pb.concat()}
|
||||
Tb.prototype={getMonth:function(a){return y(a)?a-1:this.months.indexOf(a)%12},getWeekday:function(a){return this.weekdays.indexOf(a)%7},addFormat:function(a,b,c,d,e){var g=c||[],f=this,h;a=a.replace(/\s+/g,"[,. ]*");a=a.replace(/\{([^,]+?)\}/g,function(a,b){var d,e,h,B=b.match(/\?$/);h=b.match(/^(\d+)\??$/);var k=b.match(/(\d)(?:-(\d))?/),E=b.replace(/[^a-z]+$/,"");h?d=f.tokens[h[1]]:f[E]?d=f[E]:f[E+"s"]&&(d=f[E+"s"],k&&(e=[],d.forEach(function(a,b){var c=b%(f.units?8:d.length);c>=k[1]&&c<=(k[2]||
|
||||
k[1])&&e.push(a)}),d=e),d=Ub(d));h?h="(?:"+d+")":(c||g.push(E),h="("+d+")");B&&(h+="?");return h});b?(b=Vb(f,e),e=["t","[\\s\\u3000]"].concat(f.timeMarker),h=a.match(/\\d\{\d,\d\}\)+\??$/),Wb(f,"(?:"+b+")[,\\s\\u3000]+?"+a,Jb.concat(g),d),Wb(f,a+"(?:[,\\s]*(?:"+e.join("|")+(h?"+":"*")+")"+b+")?",g.concat(Jb),d)):Wb(f,a,g,d)}};
|
||||
function Xb(a,b,c){var d,e,g=b[0],f=b[1],h=b[2];b=a[c]||a.relative;if(F(b))return b.call(a,g,f,h,c);e=a.units[8*(a.plural&&1<g?1:0)+f]||a.units[f];a.capitalizeUnit&&(e=Yb(e));d=a.modifiers.filter(function(a){return"sign"==a.name&&a.value==(0<h?1:-1)})[0];return b.replace(/\{(.*?)\}/g,function(a,b){switch(b){case "num":return g;case "unit":return e;case "sign":return d.src}})}function Zb(a,b){b=b||a.code;return"en"===b||"en-US"===b?!0:a.variant}
|
||||
function $b(a,b){return b.replace(q(a.num,"g"),function(b){return ac(a,b)||""})}function ac(a,b){var c;return y(b)?b:b&&-1!==(c=a.numbers.indexOf(b))?(c+1)%10:1}function Y(a,b){var c;z(a)||(a="");c=Sb[a]||Sb[a.slice(0,2)];if(!1===b&&!c)throw new TypeError("Invalid locale.");return c||Ib}
|
||||
function bc(a,b){function c(a){var b=h[a];z(b)?h[a]=b.split(","):b||(h[a]=[])}function d(a,b){a=a.split("+").map(function(a){return a.replace(/(.+):(.+)$/,function(a,b,c){return c.split("|").map(function(a){return b+a}).join("|")})}).join("|");a.split("|").forEach(b)}function e(a,b,c){var e=[];h[a].forEach(function(a,f){b&&(a+="+"+a.slice(0,3));d(a,function(a,b){e[b*c+f]=a.toLowerCase()})});h[a]=e}function g(a,b,c){a="\\d{"+a+","+b+"}";c&&(a+="|(?:"+Ub(h.numbers)+")+");return a}function f(a,b){h[a]=
|
||||
h[a]||b}var h,l;h=new Tb(b);c("modifiers");"months weekdays units numbers articles tokens timeMarker ampm timeSuffixes dateParse timeParse".split(" ").forEach(c);l=!h.monthSuffix;e("months",l,12);e("weekdays",l,7);e("units",!1,8);e("numbers",!1,10);f("code",a);f("date",g(1,2,h.digitDate));f("year","'\\d{2}|"+g(4,4));f("num",function(){var a=["-?\\d+"].concat(h.articles);h.numbers&&(a=a.concat(h.numbers));return Ub(a)}());(function(){var a=[];h.i={};h.modifiers.push({name:"day",src:"yesterday",value:-1});
|
||||
h.modifiers.push({name:"day",src:"today",value:0});h.modifiers.push({name:"day",src:"tomorrow",value:1});h.modifiers.forEach(function(b){var c=b.name;d(b.src,function(d){var e=h[c];h.i[d]=b;a.push({name:c,src:d,value:b.value});h[c]=e?e+"|"+d:d})});h.day+="|"+Ub(h.weekdays);h.modifiers=a})();h.monthSuffix&&(h.month=g(1,2),h.months="1 2 3 4 5 6 7 8 9 10 11 12".split(" ").map(function(a){return a+h.monthSuffix}));h.full_month=g(1,2)+"|"+Ub(h.months);0<h.timeSuffixes.length&&h.addFormat(Vb(h),!1,Jb);
|
||||
h.addFormat("{day}",!0);h.addFormat("{month}"+(h.monthSuffix||""));h.addFormat("{year}"+(h.yearSuffix||""));h.timeParse.forEach(function(a){h.addFormat(a,!0)});h.dateParse.forEach(function(a){h.addFormat(a)});return Sb[a]=h}function Wb(a,b,c,d){a.g.unshift({r:d,locale:a,q:q("^"+b+"$","i"),to:c})}function Yb(a){return a.slice(0,1).toUpperCase()+a.slice(1)}function Ub(a){return a.filter(function(a){return!!a}).join("|")}function cc(){var a=r.SugarNewDate;return a?a():new r}
|
||||
function dc(a,b){var c;if(G(a[0]))return a;if(y(a[0])&&!y(a[1]))return[a[0]];if(z(a[0])&&b)return[ec(a[0]),a[1]];c={};Nb.forEach(function(b,e){c[b.name]=a[e]});return[c]}function ec(a){var b,c={};if(a=a.match(/^(\d+)?\s?(\w+?)s?$/i))N(b)&&(b=parseInt(a[1])||1),c[a[2].toLowerCase()]=b;return c}function fc(a,b,c){var d;N(c)&&(c=Ob.length);for(b=b||0;b<c&&(d=Ob[b],!1!==a(d.name,d,b));b++);}
|
||||
function gc(a,b){var c={},d,e;b.forEach(function(b,f){d=a[f+1];N(d)||""===d||("year"===b&&(c.t=d.replace(/'/,"")),e=parseFloat(d.replace(/'/,"").replace(/,/,".")),c[b]=isNaN(e)?d.toLowerCase():e)});return c}function hc(a){a=a.trim().replace(/^just (?=now)|\.+$/i,"");return ic(a)}
|
||||
function ic(a){return a.replace(Mb,function(a,c,d){var e=0,g=1,f,h;if(c)return a;d.split("").reverse().forEach(function(a){a=Lb[a];var b=9<a;b?(f&&(e+=g),g*=a/(h||1),h=a):(!1===f&&(g*=10),e+=g*a);f=b});f&&(e+=g);return e})}
|
||||
function jc(a,b,c,d){function e(a){vb.push(a)}function g(){vb.forEach(function(a){a.call()})}function f(){var a=n.getWeekday();n.setWeekday(7*(k.num-1)+(a>Ba?Ba+7:Ba))}function h(){var a=B.i[k.edge];fc(function(a){if(M(k[a]))return E=a,!1},4);if("year"===E)k.e="month";else if("month"===E||"week"===E)k.e="day";n[(0>a.value?"endOf":"beginningOf")+Yb(E)]();-2===a.value&&n.reset()}function l(){var a;fc(function(b,c,d){"day"===b&&(b="date");if(M(k[b])){if(d>=wb)return n.setTime(NaN),!1;a=a||{};a[b]=k[b];
|
||||
delete k[b]}});a&&e(function(){n.set(a,!0)})}var n,x,ha,vb,B,k,E,wb,Ba,ra,ca;n=cc();vb=[];n.utc(d);C(a)?n.utc(a.isUTC()).setTime(a.getTime()):y(a)?n.setTime(a):G(a)?(n.set(a,!0),k=a):z(a)&&(ha=Y(b),a=hc(a),ha&&I(ha.o?[ha.o].concat(ha.g):ha.g,function(c,d){var g=a.match(d.q);if(g){B=d.locale;k=gc(g,d.to);B.o=d;k.utc&&n.utc();if(k.timestamp)return k=k.timestamp,!1;d.r&&(!z(k.month)&&(z(k.date)||Zb(ha,b)))&&(ca=k.month,k.month=k.date,k.date=ca);k.year&&2===k.t.length&&(k.year=100*R(U(cc(),"FullYear")/
|
||||
100)-100*R(k.year/100)+k.year);k.month&&(k.month=B.getMonth(k.month),k.shift&&!k.unit&&(k.unit=B.units[7]));k.weekday&&k.date?delete k.weekday:k.weekday&&(k.weekday=B.getWeekday(k.weekday),k.shift&&!k.unit&&(k.unit=B.units[5]));k.day&&(ca=B.i[k.day])?(k.day=ca.value,n.reset(),x=!0):k.day&&-1<(Ba=B.getWeekday(k.day))&&(delete k.day,k.num&&k.month?(e(f),k.day=1):k.weekday=Ba);k.date&&!y(k.date)&&(k.date=$b(B,k.date));k.ampm&&k.ampm===B.ampm[1]&&12>k.hour?k.hour+=12:k.ampm===B.ampm[0]&&12===k.hour&&
|
||||
(k.hour=0);if("offset_hours"in k||"offset_minutes"in k)n.utc(),k.offset_minutes=k.offset_minutes||0,k.offset_minutes+=60*k.offset_hours,"-"===k.offset_sign&&(k.offset_minutes*=-1),k.minute-=k.offset_minutes;k.unit&&(x=!0,ra=ac(B,k.num),wb=B.units.indexOf(k.unit)%8,E=W.units[wb],l(),k.shift&&(ra*=(ca=B.i[k.shift])?ca.value:0),k.sign&&(ca=B.i[k.sign])&&(ra*=ca.value),M(k.weekday)&&(n.set({weekday:k.weekday},!0),delete k.weekday),k[E]=(k[E]||0)+ra);k.edge&&e(h);"-"===k.year_sign&&(k.year*=-1);fc(function(a,
|
||||
b,c){b=k[a];var d=b%1;d&&(k[Ob[c-1].name]=R(d*("second"===a?1E3:60)),k[a]=Q(b))},1,4);return!1}}),k?x?n.advance(k):(n._utc&&n.reset(),kc(n,k,!0,!1,c)):("now"!==a&&(n=new r(a)),d&&n.addMinutes(-n.getTimezoneOffset())),g(),n.utc(!1));return{c:n,set:k}}function lc(a){var b,c=P(a),d=c,e=0;fc(function(a,f,h){b=Q(Da(c/f.b(),1));1<=b&&(d=b,e=h)},1);return[d,e,a]}
|
||||
function mc(a){var b=lc(a.millisecondsFromNow());if(6===b[1]||5===b[1]&&4===b[0]&&a.daysFromNow()>=cc().daysInMonth())b[0]=P(a.monthsFromNow()),b[1]=6;return b}function nc(a,b,c){function d(a,c){var d=U(a,"Month");return Y(c).months[d+12*b]}Z(a,d,c);Z(Yb(a),d,c,1)}function Z(a,b,c,d){X[a]=function(a,g){var f=b(a,g);c&&(f=f.slice(0,c));d&&(f=f.slice(0,d).toUpperCase()+f.slice(d));return f}}
|
||||
function oc(a,b,c){X[a]=b;X[a+a]=function(a,c){return T(b(a,c),2)};c&&(X[a+a+a]=function(a,c){return T(b(a,c),3)},X[a+a+a+a]=function(a,c){return T(b(a,c),4)})}function pc(a){var b=a.match(/(\{\w+\})|[^{}]+/g);Qb[a]=b.map(function(a){a.replace(/\{(\w+)\}/,function(b,e){a=X[e]||e;return e});return a})}
|
||||
function qc(a,b,c,d){var e;if(!a.isValid())return"Invalid Date";Date[b]?b=Date[b]:F(b)&&(e=mc(a),b=b.apply(a,e.concat(Y(d))));if(!b&&c)return e=e||mc(a),0===e[1]&&(e[1]=1,e[0]=1),a=Y(d),Xb(a,e,0<e[2]?"future":"past");b=b||"long";if("short"===b||"long"===b||"full"===b)b=Y(d)[b];Qb[b]||pc(b);var g,f;e="";b=Qb[b];g=0;for(c=b.length;g<c;g++)f=b[g],e+=F(f)?f(a,d):f;return e}
|
||||
function rc(a,b,c,d,e){var g,f,h,l=0,n=0,x=0;g=jc(b,c,null,e);0<d&&(n=x=d,f=!0);if(!g.c.isValid())return!1;if(g.set&&g.set.e){Rb.forEach(function(b){b.name===g.set.e&&(l=b.b(g.c,a-g.c)-1)});b=Yb(g.set.e);if(g.set.edge||g.set.shift)g.c["beginningOf"+b]();"month"===g.set.e&&(h=g.c.clone()["endOf"+b]().getTime());!f&&(g.set.sign&&"millisecond"!=g.set.e)&&(n=50,x=-50)}f=a.getTime();b=g.c.getTime();h=sc(a,b,h||b+l);return f>=b-n&&f<=h+x}
|
||||
function sc(a,b,c){b=new r(b);a=(new r(c)).utc(a.isUTC());23!==U(a,"Hours")&&(b=b.getTimezoneOffset(),a=a.getTimezoneOffset(),b!==a&&(c+=(a-b).minutes()));return c}
|
||||
function kc(a,b,c,d,e){function g(a){return M(b[a])?b[a]:b[a+"s"]}function f(a){return M(g(a))}var h;if(y(b)&&d)b={milliseconds:b};else if(y(b))return a.setTime(b),a;M(b.date)&&(b.day=b.date);fc(function(d,e,g){var l="day"===d;if(f(d)||l&&f("weekday"))return b.e=d,h=+g,!1;!c||("week"===d||l&&f("week"))||Sa(a,e.method,l?1:0)});Rb.forEach(function(c){var e=c.name;c=c.method;var h;h=g(e);N(h)||(d?("week"===e&&(h=(b.day||0)+7*h,c="Date"),h=h*d+U(a,c)):"month"===e&&f("day")&&Sa(a,"Date",15),Sa(a,c,h),
|
||||
d&&"month"===e&&(e=h,0>e&&(e=e%12+12),e%12!=U(a,"Month")&&Sa(a,"Date",0)))});d||(f("day")||!f("weekday"))||a.setWeekday(g("weekday"));var l;a:{switch(e){case -1:l=a>cc();break a;case 1:l=a<cc();break a}l=void 0}l&&fc(function(b,c){if((c.k||"week"===b&&f("weekday"))&&!(f(b)||"day"===b&&f("weekday")))return a[c.j](e),!1},h+1);return a}
|
||||
function Vb(a,b){var c=Kb,d={h:0,m:1,s:2},e;a=a||W;return c.replace(/{([a-z])}/g,function(c,f){var h=[],l="h"===f,n=l&&!b;if("t"===f)return a.ampm.join("|");l&&h.push(":");(e=a.timeSuffixes[d[f]])&&h.push(e+"\\s*");return 0===h.length?"":"(?:"+h.join("|")+")"+(n?"":"?")})}function tc(a,b,c){var d,e;y(a[1])?d=dc(a)[0]:(d=a[0],e=a[1]);return jc(d,e,b,c).c}
|
||||
H(r,!1,!0,{create:function(){return tc(arguments)},past:function(){return tc(arguments,-1)},future:function(){return tc(arguments,1)},addLocale:function(a,b){return bc(a,b)},setLocale:function(a){var b=Y(a,!1);Ib=b;a&&a!=b.code&&(b.code=a);return b},getLocale:function(a){return a?Y(a,!1):Ib},addFormat:function(a,b,c){Wb(Y(c),a,b)}});
|
||||
H(r,!0,!0,{set:function(){var a=dc(arguments);return kc(this,a[0],a[1])},setWeekday:function(a){if(!N(a))return Sa(this,"Date",U(this,"Date")+a-U(this,"Day"))},setISOWeek:function(a){var b=U(this,"Day")||7;if(!N(a))return this.set({month:0,date:4}),this.set({weekday:1}),1<a&&this.addWeeks(a-1),1!==b&&this.advance({days:b-1}),this.getTime()},getISOWeek:function(){var a;a=this.clone();var b=U(a,"Day")||7;a.addDays(4-b).reset();return 1+Q(a.daysSince(a.clone().beginningOfYear())/7)},beginningOfISOWeek:function(){var a=
|
||||
this.getDay();0===a?a=-6:1!==a&&(a=1);this.setWeekday(a);return this.reset()},endOfISOWeek:function(){0!==this.getDay()&&this.setWeekday(7);return this.endOfDay()},getUTCOffset:function(a){var b=this._utc?0:this.getTimezoneOffset(),c=!0===a?":":"";return!b&&a?"Z":T(Q(-b/60),2,!0)+c+T(P(b%60),2)},utc:function(a){oa(this,"_utc",!0===a||0===arguments.length);return this},isUTC:function(){return!!this._utc||0===this.getTimezoneOffset()},advance:function(){var a=dc(arguments,!0);return kc(this,a[0],a[1],
|
||||
1)},rewind:function(){var a=dc(arguments,!0);return kc(this,a[0],a[1],-1)},isValid:function(){return!isNaN(this.getTime())},isAfter:function(a,b){return this.getTime()>r.create(a).getTime()-(b||0)},isBefore:function(a,b){return this.getTime()<r.create(a).getTime()+(b||0)},isBetween:function(a,b,c){var d=this.getTime();a=r.create(a).getTime();var e=r.create(b).getTime();b=Ca(a,e);a=S(a,e);c=c||0;return b-c<d&&a+c>d},isLeapYear:function(){var a=U(this,"FullYear");return 0===a%4&&0!==a%100||0===a%400},
|
||||
daysInMonth:function(){return 32-U(new r(U(this,"FullYear"),U(this,"Month"),32),"Date")},format:function(a,b){return qc(this,a,!1,b)},relative:function(a,b){z(a)&&(b=a,a=null);return qc(this,a,!0,b)},is:function(a,b,c){var d,e;if(this.isValid()){if(z(a))switch(a=a.trim().toLowerCase(),e=this.clone().utc(c),!0){case "future"===a:return this.getTime()>cc().getTime();case "past"===a:return this.getTime()<cc().getTime();case "weekday"===a:return 0<U(e,"Day")&&6>U(e,"Day");case "weekend"===a:return 0===
|
||||
U(e,"Day")||6===U(e,"Day");case -1<(d=W.weekdays.indexOf(a)%7):return U(e,"Day")===d;case -1<(d=W.months.indexOf(a)%12):return U(e,"Month")===d}return rc(this,a,null,b,c)}},reset:function(a){var b={},c;a=a||"hours";"date"===a&&(a="days");c=Rb.some(function(b){return a===b.name||a===b.name+"s"});b[a]=a.match(/^days?/)?1:0;return c?this.set(b,!0):this},clone:function(){var a=new r(this.getTime());a.utc(!!this._utc);return a}});
|
||||
H(r,!0,!0,{iso:function(){return this.toISOString()},getWeekday:r.prototype.getDay,getUTCWeekday:r.prototype.getUTCDay});function uc(a,b){function c(){return R(this*b)}function d(){return tc(arguments)[a.j](this)}function e(){return tc(arguments)[a.j](-this)}var g=a.name,f={};f[g]=c;f[g+"s"]=c;f[g+"Before"]=e;f[g+"sBefore"]=e;f[g+"Ago"]=e;f[g+"sAgo"]=e;f[g+"After"]=d;f[g+"sAfter"]=d;f[g+"FromNow"]=d;f[g+"sFromNow"]=d;t.extend(f)}H(t,!0,!0,{duration:function(a){a=Y(a);return Xb(a,lc(this),"duration")}});
|
||||
W=Ib=r.addLocale("en",{plural:!0,timeMarker:"at",ampm:"am,pm",months:"January,February,March,April,May,June,July,August,September,October,November,December",weekdays:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",units:"millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s",numbers:"one,two,three,four,five,six,seven,eight,nine,ten",articles:"a,an,the",tokens:"the,st|nd|rd|th,of","short":"{Month} {d}, {yyyy}","long":"{Month} {d}, {yyyy} {h}:{mm}{tt}",full:"{Weekday} {Month} {d}, {yyyy} {h}:{mm}:{ss}{tt}",
|
||||
past:"{num} {unit} {sign}",future:"{num} {unit} {sign}",duration:"{num} {unit}",modifiers:[{name:"sign",src:"ago|before",value:-1},{name:"sign",src:"from now|after|from|in|later",value:1},{name:"edge",src:"last day",value:-2},{name:"edge",src:"end",value:-1},{name:"edge",src:"first day|beginning",value:1},{name:"shift",src:"last",value:-1},{name:"shift",src:"the|this",value:0},{name:"shift",src:"next",value:1}],dateParse:["{month} {year}","{shift} {unit=5-7}","{0?} {date}{1}","{0?} {edge} of {shift?} {unit=4-7?}{month?}{year?}"],
|
||||
timeParse:"{num} {unit} {sign};{sign} {num} {unit};{0} {num}{1} {day} of {month} {year?};{weekday?} {month} {date}{1?} {year?};{date} {month} {year};{date} {month};{shift} {weekday};{shift} week {weekday};{weekday} {2?} {shift} week;{num} {unit=4-5} {sign} {day};{0?} {date}{1} of {month};{0?}{month?} {date?}{1?} of {shift} {unit=6-7}".split(";")});Ob=Rb.concat().reverse();Nb=Rb.concat();Nb.splice(2,1);
|
||||
K(r,!0,!0,Rb,function(a,b,c){function d(a){a/=f;var c=a%1,d=b.error||0.999;c&&P(c%1)>d&&(a=R(a));return 0>a?Aa(a):Q(a)}var e=b.name,g=Yb(e),f=b.b(),h,l;b.j="add"+g+"s";h=function(a,b){return d(this.getTime()-r.create(a,b).getTime())};l=function(a,b){return d(r.create(a,b).getTime()-this.getTime())};a[e+"sAgo"]=l;a[e+"sUntil"]=l;a[e+"sSince"]=h;a[e+"sFromNow"]=h;a[b.j]=function(a,b){var c={};c[e]=a;return this.advance(c,b)};uc(b,f);3>c&&["Last","This","Next"].forEach(function(b){a["is"+b+g]=function(){return rc(this,
|
||||
b+" "+e,"en")}});4>c&&(a["beginningOf"+g]=function(){var a={};switch(e){case "year":a.year=U(this,"FullYear");break;case "month":a.month=U(this,"Month");break;case "day":a.day=U(this,"Date");break;case "week":a.weekday=0}return this.set(a,!0)},a["endOf"+g]=function(){var a={hours:23,minutes:59,seconds:59,milliseconds:999};switch(e){case "year":a.month=11;a.day=31;break;case "month":a.day=this.daysInMonth();break;case "week":a.weekday=6}return this.set(a,!0)})});
|
||||
W.addFormat("([+-])?(\\d{4,4})[-.]?{full_month}[-.]?(\\d{1,2})?",!0,["year_sign","year","month","date"],!1,!0);W.addFormat("(\\d{1,2})[-.\\/]{full_month}(?:[-.\\/](\\d{2,4}))?",!0,["date","month","year"],!0);W.addFormat("{full_month}[-.](\\d{4,4})",!1,["month","year"]);W.addFormat("\\/Date\\((\\d+(?:[+-]\\d{4,4})?)\\)\\/",!1,["timestamp"]);W.addFormat(Vb(W),!1,Jb);Pb=W.g.slice(0,7).reverse();W.g=W.g.slice(7).concat(Pb);oc("f",function(a){return U(a,"Milliseconds")},!0);
|
||||
oc("s",function(a){return U(a,"Seconds")});oc("m",function(a){return U(a,"Minutes")});oc("h",function(a){return U(a,"Hours")%12||12});oc("H",function(a){return U(a,"Hours")});oc("d",function(a){return U(a,"Date")});oc("M",function(a){return U(a,"Month")+1});(function(){function a(a,c){var d=U(a,"Hours");return Y(c).ampm[Q(d/12)]||""}Z("t",a,1);Z("tt",a);Z("T",a,1,1);Z("TT",a,null,2)})();
|
||||
(function(){function a(a,c){var d=U(a,"Day");return Y(c).weekdays[d]}Z("dow",a,3);Z("Dow",a,3,1);Z("weekday",a);Z("Weekday",a,null,1)})();nc("mon",0,3);nc("month",0);nc("month2",1);nc("month3",2);X.ms=X.f;X.milliseconds=X.f;X.seconds=X.s;X.minutes=X.m;X.hours=X.h;X["24hr"]=X.H;X["12hr"]=X.h;X.date=X.d;X.day=X.d;X.year=X.yyyy;K(r,!0,!0,"short,long,full",function(a,b){a[b]=function(a){return qc(this,b,!1,a)}});
|
||||
"\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07".split("").forEach(function(a,b){9<b&&(b=za(10,b-9));Lb[a]=b});xa(Lb,Ka);Mb=q("([\u671f\u9031\u5468])?([\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07"+Ja+"]+)(?!\u6628)","g");
|
||||
(function(){var a=W.weekdays.slice(0,7),b=W.months.slice(0,12);K(r,!0,!0,"today yesterday tomorrow weekday weekend future past".split(" ").concat(a).concat(b),function(a,b){a["is"+Yb(b)]=function(a){return this.is(b,0,a)}})})();r.utc||(r.utc={create:function(){return tc(arguments,0,!0)},past:function(){return tc(arguments,-1,!0)},future:function(){return tc(arguments,1,!0)}});
|
||||
H(r,!1,!0,{RFC1123:"{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}",RFC1036:"{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}",ISO8601_DATE:"{yyyy}-{MM}-{dd}",ISO8601_DATETIME:"{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}"});
|
||||
"use strict";function Range(a,b){this.start=vc(a);this.end=vc(b)}function vc(a){return C(a)?new r(a.getTime()):null==a?a:C(a)?a.getTime():a.valueOf()}function wc(a){a=null==a?a:C(a)?a.getTime():a.valueOf();return!!a||0===a}
|
||||
function xc(a,b){var c,d,e,g;if(y(b))return new r(a.getTime()+b);c=b[0];d=b[1];e=U(a,d);g=new r(a.getTime());Sa(g,d,e+c);return g}function yc(a,b){return s.fromCharCode(a.charCodeAt(0)+b)}function zc(a,b){return a+b}Range.prototype.toString=function(){return this.isValid()?this.start+".."+this.end:"Invalid Range"};
|
||||
H(Range,!0,!0,{isValid:function(){return wc(this.start)&&wc(this.end)&&typeof this.start===typeof this.end},span:function(){return this.isValid()?P((z(this.end)?this.end.charCodeAt(0):this.end)-(z(this.start)?this.start.charCodeAt(0):this.start))+1:NaN},contains:function(a){return null==a?!1:a.start&&a.end?a.start>=this.start&&a.start<=this.end&&a.end>=this.start&&a.end<=this.end:a>=this.start&&a<=this.end},every:function(a,b){var c,d=this.start,e=this.end,g=e<d,f=d,h=0,l=[];F(a)&&(b=a,a=null);a=
|
||||
a||1;y(d)?c=zc:z(d)?c=yc:C(d)&&(c=a,y(c)?a=c:(d=c.toLowerCase().match(/^(\d+)?\s?(\w+?)s?$/i),c=parseInt(d[1])||1,d=d[2].slice(0,1).toUpperCase()+d[2].slice(1),d.match(/hour|minute|second/i)?d+="s":"Year"===d?d="FullYear":"Day"===d&&(d="Date"),a=[c,d]),c=xc);for(g&&0<a&&(a*=-1);g?f>=e:f<=e;)l.push(f),b&&b(f,h),f=c(f,a),h++;return l},union:function(a){return new Range(this.start<a.start?this.start:a.start,this.end>a.end?this.end:a.end)},intersect:function(a){return a.start>this.end||a.end<this.start?
|
||||
new Range(NaN,NaN):new Range(this.start>a.start?this.start:a.start,this.end<a.end?this.end:a.end)},clone:function(){return new Range(this.start,this.end)},clamp:function(a){var b=this.start,c=this.end,d=c<b?c:b,b=b>c?b:c;return vc(a<d?d:a>b?b:a)}});[t,s,r].forEach(function(a){H(a,!1,!0,{range:function(b,c){a.create&&(b=a.create(b),c=a.create(c));return new Range(b,c)}})});
|
||||
H(t,!0,!0,{upto:function(a,b,c){return t.range(this,a).every(c,b)},clamp:function(a,b){return(new Range(a,b)).clamp(this)},cap:function(a){return this.clamp(void 0,a)}});H(t,!0,!0,{downto:t.prototype.upto});H(p,!1,function(a){return a instanceof Range},{create:function(a){return a.every()}});
|
||||
"use strict";function Ac(a,b,c,d,e){Infinity!==b&&(a.timers||(a.timers=[]),y(b)||(b=1),a.n=!1,a.timers.push(setTimeout(function(){a.n||c.apply(d,e||[])},b)))}
|
||||
H(Function,!0,!0,{lazy:function(a,b,c){function d(){g.length<c-(f&&b?1:0)&&g.push([this,arguments]);f||(f=!0,b?h():Ac(d,l,h));return x}var e=this,g=[],f=!1,h,l,n,x;a=a||1;c=c||Infinity;l=Aa(a);n=R(l/a)||1;h=function(){var a=g.length,b;if(0!=a){for(b=S(a-n,0);a>b;)x=Function.prototype.apply.apply(e,g.shift()),a--;Ac(d,l,function(){f=!1;h()})}};return d},throttle:function(a){return this.lazy(a,!0,1)},debounce:function(a){function b(){b.cancel();Ac(b,a,c,this,arguments)}var c=this;return b},delay:function(a){var b=
|
||||
L(arguments,null,1);Ac(this,a,this,this,b);return this},every:function(a){function b(){c.apply(c,d);Ac(c,a,b)}var c=this,d=arguments,d=1<d.length?L(d,null,1):[];Ac(c,a,b);return c},cancel:function(){var a=this.timers,b;if(A(a))for(;b=a.shift();)clearTimeout(b);this.n=!0;return this},after:function(a){var b=this,c=0,d=[];if(!y(a))a=1;else if(0===a)return b.call(),b;return function(){var e;d.push(L(arguments));c++;if(c==a)return e=b.call(this,d),c=0,d=[],e}},once:function(){return this.throttle(Infinity,
|
||||
!0)},fill:function(){var a=this,b=L(arguments);return function(){var c=L(arguments);b.forEach(function(a,b){(null!=a||b>=c.length)&&c.splice(b,0,a)});return a.apply(this,c)}}});
|
||||
"use strict";function Bc(a,b,c,d,e,g){var f=a.toFixed(20),h=f.search(/\./),f=f.search(/[1-9]/),h=h-f;0<h&&(h-=1);e=S(Ca(Q(h/3),!1===e?c.length:e),-d);d=c.charAt(e+d-1);-9>h&&(e=-3,b=P(h)-9,d=c.slice(0,1));c=g?za(2,10*e):za(10,3*e);return Da(a/c,b||0).format()+d.trim()}
|
||||
H(t,!1,!0,{random:function(a,b){var c,d;1==arguments.length&&(b=a,a=0);c=Ca(a||0,N(b)?1:b);d=S(a||0,N(b)?1:b)+1;return Q(u.random()*(d-c)+c)}});
|
||||
H(t,!0,!0,{log:function(a){return u.log(this)/(a?u.log(a):1)},abbr:function(a){return Bc(this,a,"kmbt",0,4)},metric:function(a,b){return Bc(this,a,"n\u03bcm kMGTPE",4,N(b)?1:b)},bytes:function(a,b){return Bc(this,a,"kMGTPE",0,N(b)?4:b,!0)+"B"},isInteger:function(){return 0==this%1},isOdd:function(){return!isNaN(this)&&!this.isMultipleOf(2)},isEven:function(){return this.isMultipleOf(2)},isMultipleOf:function(a){return 0===this%a},format:function(a,b,c){var d,e,g,f="";N(b)&&(b=",");N(c)&&(c=".");d=
|
||||
(y(a)?Da(this,a||0).toFixed(S(a,0)):this.toString()).replace(/^-/,"").split(".");e=d[0];g=d[1];for(d=e.length;0<d;d-=3)d<e.length&&(f=b+f),f=e.slice(S(0,d-3),d)+f;g&&(f+=c+Na("0",(a||0)-g.length)+g);return(0>this?"-":"")+f},hex:function(a){return this.pad(a||1,!1,16)},times:function(a){if(a)for(var b=0;b<this;b++)a.call(this,b);return this.toNumber()},chr:function(){return s.fromCharCode(this)},pad:function(a,b,c){return T(this,a,b,c)},ordinalize:function(){var a=P(this),a=parseInt(a.toString().slice(-2));
|
||||
return this+Pa(a)},toNumber:function(){return parseFloat(this,10)}});(function(){function a(a){return function(c){return c?Da(this,c,a):a(this)}}H(t,!0,!0,{ceil:a(Aa),round:a(R),floor:a(Q)});K(t,!0,!0,"abs,pow,sin,asin,cos,acos,tan,atan,exp,pow,sqrt",function(a,c){a[c]=function(a,b){return u[c](this,a,b)}})})();
|
||||
"use strict";var Cc=["isObject","isNaN"],Dc="keys values select reject each merge clone equal watch tap has toQueryString".split(" ");
|
||||
function Ec(a,b,c,d){var e,g,f;(g=b.match(/^(.+?)(\[.*\])$/))?(f=g[1],b=g[2].replace(/^\[|\]$/g,"").split("]["),b.forEach(function(b){e=!b||b.match(/^\d+$/);!f&&A(a)&&(f=a.length);J(a,f)||(a[f]=e?[]:{});a=a[f];f=b}),!f&&e&&(f=a.length.toString()),Ec(a,f,c,d)):a[b]=d&&"true"===c?!0:d&&"false"===c?!1:c}function Fc(a,b){var c;return A(b)||G(b)&&b.toString===v?(c=[],I(b,function(b,e){a&&(b=a+"["+b+"]");c.push(Fc(b,e))}),c.join("&")):a?Gc(a)+"="+(C(b)?b.getTime():Gc(b)):""}
|
||||
function Gc(a){return a||!1===a||0===a?encodeURIComponent(a).replace(/%20/g,"+"):""}function Hc(a,b,c){var d,e=a instanceof O?new O:{};I(a,function(a,f){d=!1;sa(b,function(b){(D(b)?b.test(a):G(b)?b[a]===f:a===s(b))&&(d=!0)},1);d===c&&(e[a]=f)});return e}H(m,!1,!0,{watch:function(a,b,c){if(ea){var d=a[b];m.defineProperty(a,b,{enumerable:!0,configurable:!0,get:function(){return d},set:function(e){d=c.call(a,b,d,e)}})}}});
|
||||
H(m,!1,function(){return 1<arguments.length},{keys:function(a,b){var c=m.keys(a);c.forEach(function(c){b.call(a,c,a[c])});return c}});
|
||||
H(m,!1,!0,{isObject:function(a){return va(a)},isNaN:function(a){return y(a)&&a.valueOf()!==a.valueOf()},equal:function(a,b){return Ua(a,b)},extended:function(a){return new O(a)},merge:function(a,b,c,d){var e,g,f,h,l,n,x;if(a&&"string"!==typeof b)for(e in b)if(J(b,e)&&a){h=b[e];l=a[e];n=M(l);g=G(h);f=G(l);x=n&&!1===d?l:h;n&&F(d)&&(x=d.call(b,e,l,h));if(c&&(g||f))if(C(h))x=new r(h.getTime());else if(D(h))x=new q(h.source,Qa(h));else{f||(a[e]=p.isArray(h)?[]:{});m.merge(a[e],h,c,d);continue}a[e]=x}return a},
|
||||
values:function(a,b){var c=[];I(a,function(d,e){c.push(e);b&&b.call(a,e)});return c},clone:function(a,b){var c;if(!G(a))return a;c=v.call(a);if(C(a,c)&&a.clone)return a.clone();if(C(a,c)||D(a,c))return new a.constructor(a);if(a instanceof O)c=new O;else if(A(a,c))c=[];else if(va(a,c))c={};else throw new TypeError("Clone must be a basic data type.");return m.merge(c,a,b)},fromQueryString:function(a,b){var c=m.extended();a=a&&a.toString?a.toString():"";a.replace(/^.*?\?/,"").split("&").forEach(function(a){a=
|
||||
a.split("=");2===a.length&&Ec(c,a[0],decodeURIComponent(a[1]),b)});return c},toQueryString:function(a,b){return Fc(b,a)},tap:function(a,b){var c=b;F(b)||(c=function(){if(b)a[b]()});c.call(a,a);return a},has:function(a,b){return J(a,b)},select:function(a){return Hc(a,arguments,!0)},reject:function(a){return Hc(a,arguments,!1)}});K(m,!1,!0,w,function(a,b){var c="is"+b;Cc.push(c);a[c]=ia[b]});
|
||||
H(m,!1,function(){return 0===arguments.length},{extend:function(){var a=Cc.concat(Dc);"undefined"!==typeof Hb&&(a=a.concat(Hb));Ya(a,m)}});Ya(Dc,O);
|
||||
"use strict";H(q,!1,!0,{escape:function(a){return Ra(a)}});H(q,!0,!0,{getFlags:function(){return Qa(this)},setFlags:function(a){return q(this.source,a)},addFlag:function(a){return this.setFlags(Qa(this,a))},removeFlag:function(a){return this.setFlags(Qa(this).replace(a,""))}});
|
||||
"use strict";
|
||||
function Ic(a){a=+a;if(0>a||Infinity===a)throw new RangeError("Invalid number");return a}function Jc(a,b){return Na(M(b)?b:" ",a)}function Kc(a,b,c,d,e){var g;if(a.length<=b)return a.toString();d=N(d)?"...":d;switch(c){case "left":return a=e?Lc(a,b,!0):a.slice(a.length-b),d+a;case "middle":return c=Aa(b/2),g=Q(b/2),b=e?Lc(a,c):a.slice(0,c),a=e?Lc(a,g,!0):a.slice(a.length-g),b+d+a;default:return b=e?Lc(a,b):a.slice(0,b),b+d}}
|
||||
function Lc(a,b,c){if(c)return Lc(a.reverse(),b).reverse();c=q("(?=["+Ma()+"])");var d=0;return a.split(c).filter(function(a){d+=a.length;return d<=b}).join("")}function Mc(a,b,c){z(b)&&(b=a.indexOf(b),-1===b&&(b=c?a.length:0));return b}var Nc,Oc;H(s,!0,!1,{repeat:function(a){a=Ic(a);return Na(this,a)}});
|
||||
H(s,!0,function(a){return D(a)||2<arguments.length},{startsWith:function(a){var b=arguments,c=b[1],b=b[2],d=this;c&&(d=d.slice(c));N(b)&&(b=!0);c=D(a)?a.source.replace("^",""):Ra(a);return q("^"+c,b?"":"i").test(d)},endsWith:function(a){var b=arguments,c=b[1],b=b[2],d=this;M(c)&&(d=d.slice(0,c));N(b)&&(b=!0);c=D(a)?a.source.replace("$",""):Ra(a);return q(c+"$",b?"":"i").test(d)}});
|
||||
H(s,!0,!0,{escapeRegExp:function(){return Ra(this)},escapeURL:function(a){return a?encodeURIComponent(this):encodeURI(this)},unescapeURL:function(a){return a?decodeURI(this):decodeURIComponent(this)},escapeHTML:function(){return this.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")},unescapeHTML:function(){return this.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(///g,
|
||||
"/").replace(/&/g,"&")},encodeBase64:function(){return Nc(unescape(encodeURIComponent(this)))},decodeBase64:function(){return decodeURIComponent(escape(Oc(this)))},each:function(a,b){var c,d,e;F(a)?(b=a,a=/[\s\S]/g):a?z(a)?a=q(Ra(a),"gi"):D(a)&&(a=q(a.source,Qa(a,"g"))):a=/[\s\S]/g;c=this.match(a)||[];if(b)for(d=0,e=c.length;d<e;d++)c[d]=b.call(this,c[d],d,c)||c[d];return c},shift:function(a){var b="";a=a||0;this.codes(function(c){b+=s.fromCharCode(c+a)});return b},codes:function(a){var b=[],
|
||||
c,d;c=0;for(d=this.length;c<d;c++){var e=this.charCodeAt(c);b.push(e);a&&a.call(this,e,c)}return b},chars:function(a){return this.each(a)},words:function(a){return this.trim().each(/\S+/g,a)},lines:function(a){return this.trim().each(/^.*$/gm,a)},paragraphs:function(a){var b=this.trim().split(/[\r\n]{2,}/);return b=b.map(function(b){if(a)var d=a.call(b);return d?d:b})},isBlank:function(){return 0===this.trim().length},has:function(a){return-1!==this.search(D(a)?a:Ra(a))},add:function(a,b){b=N(b)?
|
||||
this.length:b;return this.slice(0,b)+a+this.slice(b)},remove:function(a){return this.replace(a,"")},reverse:function(){return this.split("").reverse().join("")},compact:function(){return this.trim().replace(/([\r\n\s\u3000])+/g,function(a,b){return"\u3000"===b?b:" "})},at:function(){return Wa(this,arguments,!0)},from:function(a){return this.slice(Mc(this,a,!0))},to:function(a){N(a)&&(a=this.length);return this.slice(0,Mc(this,a))},dasherize:function(){return this.underscore().replace(/_/g,"-")},underscore:function(){return this.replace(/[-\s]+/g,
|
||||
"_").replace(s.Inflector&&s.Inflector.acronymRegExp,function(a,b){return(0<b?"_":"")+a.toLowerCase()}).replace(/([A-Z\d]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").toLowerCase()},camelize:function(a){return this.underscore().replace(/(^|_)([^_]+)/g,function(b,c,d,e){b=(b=s.Inflector)&&b.acronyms[d];b=z(b)?b:void 0;e=!1!==a||0<e;return b?e?b:b.toLowerCase():e?d.capitalize():d})},spacify:function(){return this.underscore().replace(/_/g," ")},stripTags:function(){var a=this;sa(0<arguments.length?
|
||||
arguments:[""],function(b){a=a.replace(q("</?"+Ra(b)+"[^<>]*>","gi"),"")});return a},removeTags:function(){var a=this;sa(0<arguments.length?arguments:["\\S+"],function(b){b=q("<("+b+")[^<>]*(?:\\/>|>.*?<\\/\\1>)","gi");a=a.replace(b,"")});return a},truncate:function(a,b,c){return Kc(this,a,b,c)},truncateOnWord:function(a,b,c){return Kc(this,a,b,c,!0)},pad:function(a,b){var c,d;a=Ic(a);c=S(0,a-this.length)/2;d=Q(c);c=Aa(c);return Jc(d,b)+this+Jc(c,b)},padLeft:function(a,b){a=Ic(a);return Jc(S(0,a-
|
||||
this.length),b)+this},padRight:function(a,b){a=Ic(a);return this+Jc(S(0,a-this.length),b)},first:function(a){N(a)&&(a=1);return this.substr(0,a)},last:function(a){N(a)&&(a=1);return this.substr(0>this.length-a?0:this.length-a)},toNumber:function(a){return Oa(this,a)},capitalize:function(a){var b;return this.toLowerCase().replace(a?/[^']/g:/^\S/,function(a){var d=a.toUpperCase(),e;e=b?a:d;b=d!==a;return e})},assign:function(){var a={};sa(arguments,function(b,c){G(b)?xa(a,b):a[c+1]=b});return this.replace(/\{([^{]+?)\}/g,
|
||||
function(b,c){return J(a,c)?a[c]:b})}});H(s,!0,!0,{insert:s.prototype.add});
|
||||
(function(a){if(ba.btoa)Nc=ba.btoa,Oc=ba.atob;else{var b=/[^A-Za-z0-9\+\/\=]/g;Nc=function(b){var d="",e,g,f,h,l,n,x=0;do e=b.charCodeAt(x++),g=b.charCodeAt(x++),f=b.charCodeAt(x++),h=e>>2,e=(e&3)<<4|g>>4,l=(g&15)<<2|f>>6,n=f&63,isNaN(g)?l=n=64:isNaN(f)&&(n=64),d=d+a.charAt(h)+a.charAt(e)+a.charAt(l)+a.charAt(n);while(x<b.length);return d};Oc=function(c){var d="",e,g,f,h,l,n=0;if(c.match(b))throw Error("String contains invalid base64 characters");c=c.replace(/[^A-Za-z0-9\+\/\=]/g,"");do e=a.indexOf(c.charAt(n++)),
|
||||
g=a.indexOf(c.charAt(n++)),h=a.indexOf(c.charAt(n++)),l=a.indexOf(c.charAt(n++)),e=e<<2|g>>4,g=(g&15)<<4|h>>2,f=(h&3)<<6|l,d+=s.fromCharCode(e),64!=h&&(d+=s.fromCharCode(g)),64!=l&&(d+=s.fromCharCode(f));while(n<c.length);return d}}})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");})();
|
||||
22
tagserverApp/assets/js/router.js
Normal file
22
tagserverApp/assets/js/router.js
Normal file
@@ -0,0 +1,22 @@
|
||||
var tagserver = angular.module('tagserver', ['ngRoute', 'tsCtrlrs']);
|
||||
|
||||
tagserver.config([
|
||||
'$routeProvider', function($routeProvider) {
|
||||
$routeProvider.when('/dashboard', {
|
||||
templateUrl: '/templates/dashboard.html',
|
||||
controller: 'dashboardCtrl'
|
||||
}).when('/tags', {
|
||||
templateUrl: '/templates/tags.html',
|
||||
controller: 'tagsCtrl'
|
||||
}).when('/tag/:tagID', {
|
||||
templateUrl: '/templates/tagVals.html',
|
||||
controller: 'tagValsCtrl'
|
||||
}).when('/config', {
|
||||
templateUrl: '/templates/config.html',
|
||||
controller: 'configCtrl'
|
||||
}).when('/', {
|
||||
templateUrl: '/templates/dashboard.html',
|
||||
controller: 'dashboardCtrl'
|
||||
});
|
||||
}
|
||||
]);
|
||||
15
tagserverApp/assets/styles/app.css
Normal file
15
tagserverApp/assets/styles/app.css
Normal file
@@ -0,0 +1,15 @@
|
||||
.topMargin40 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.row-flex {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.row-flex > [class*='col-'] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
6
tagserverApp/assets/styles/bootstrap-theme.min.css
vendored
Normal file
6
tagserverApp/assets/styles/bootstrap-theme.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
tagserverApp/assets/styles/bootstrap.min.css
vendored
Normal file
6
tagserverApp/assets/styles/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
17
tagserverApp/assets/styles/font-awesome.less
vendored
Normal file
17
tagserverApp/assets/styles/font-awesome.less
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*!
|
||||
* Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/
|
||||
|
||||
@import "variables.less";
|
||||
@import "mixins.less";
|
||||
@import "path.less";
|
||||
@import "core.less";
|
||||
@import "larger.less";
|
||||
@import "fixed-width.less";
|
||||
@import "list.less";
|
||||
@import "bordered-pulled.less";
|
||||
@import "animated.less";
|
||||
@import "rotated-flipped.less";
|
||||
@import "stacked.less";
|
||||
@import "icons.less";
|
||||
80
tagserverApp/assets/templates/config.html
Normal file
80
tagserverApp/assets/templates/config.html
Normal file
@@ -0,0 +1,80 @@
|
||||
<div ng-if="loading" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 well" style="text-align:center;">
|
||||
<h1>Loading Config...</h1>
|
||||
<img class="img-responsive" src="/images/loading.gif" style="margin:0 auto;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!loading">
|
||||
<div ng-if="error" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md=12">
|
||||
<h1>Error Caught!</h1>
|
||||
<pre>{{message}}</pre>
|
||||
<button ng-click="loadDashboard()" class="btn btn-large btn-danger"><i class="fa fa-refresh"></i> Reload Dashboard</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!error" class="container">
|
||||
<div class="row well">
|
||||
<div class="col-md-12">
|
||||
<h1 ng-if="!loggerLoading">Logger Status:
|
||||
<span ng-if="loggerRunning" class="label label-success">Running</span>
|
||||
<span ng-if="!loggerRunning" class="label label-danger">Not Running</span>
|
||||
</h1>
|
||||
<h1 ng-if="loggerLoading">
|
||||
<span class="label label-warning">Checking Logger Status...</span>
|
||||
</h1>
|
||||
<button class="btn btn-primary btn-large" ng-click="checkLogger()">Check Logger</button> <button class="btn btn-warning btn-large" ng-click="restartLogger()">Restart Logger</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h1>Configuration Parameters</h1>
|
||||
<button ng-click="loadConfig()" class="btn btn-large btn-success"><i class="fa fa-refresh"></i> Reload Config</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr ng-repeat="param in config">
|
||||
<td>{{param.parameter}}</td>
|
||||
<td>{{param.val}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="row well">
|
||||
<h2>New Parameter</h2>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="pSelected">Parameter</label>
|
||||
<select class="form-control" id="pSelected" ng-model="newParam.pSelected">
|
||||
<option value="ip_address">PLC IP Address</option>
|
||||
<option value="scan_rate">Scan Rate</option>
|
||||
<option value="other">Other</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="newParam.pSelected=='other'">
|
||||
<label for="pEntry">Parameter Entry</label>
|
||||
<input type="text" class="form-control" id="val" ng-model="newParam.pEntry" placeholder="Parameter Name">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="val">Value</label>
|
||||
<input type="text" class="form-control" id="val" ng-model="newParam.val" placeholder="Parameter Value">
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" ng-click="addParameter()">Set Parameter</button>
|
||||
</form>
|
||||
<!--<pre>{{newParam}}</pre>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
36
tagserverApp/assets/templates/dashboard.html
Normal file
36
tagserverApp/assets/templates/dashboard.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<div ng-if="loading" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 well" style="text-align:center;">
|
||||
<h1>Loading Dashboard...</h1>
|
||||
<img class="img-responsive" src="/images/loading.gif" style="margin:0 auto;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!loading">
|
||||
<div ng-if="error" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md=12">
|
||||
<h1>Error Caught!</h1>
|
||||
<pre>{{message}}</pre>
|
||||
<button ng-click="loadDashboard()" class="btn btn-large btn-danger"><i class="fa fa-refresh"></i> Reload Dashboard</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!error" class="container">
|
||||
<div class="row">
|
||||
<button ng-click="loadDashboard()" class="btn btn-large btn-success"><i class="fa fa-refresh"></i> Reload Dashboard</button>
|
||||
<a href="/json/csv/all" class="btn btn-large btn-primary"><i class="fa fa-download"></i> Download All Data</a>
|
||||
<div ng-repeat="val in vals">
|
||||
<div class="col-md-4" style="height:200px; margin-bottom:40px;">
|
||||
<just-gage id="{{val.name}}" min='val.minExpected' max='val.maxExpected' value='val.val' options="{label:val.units,title:val.name, decimals:2, refreshAnimationType:'bounce', startAnimationType:'bounce'}"></just-gage>
|
||||
<div style="text-align:center">
|
||||
<h5>{{ val.dtime | date: 'medium'}}</h5>
|
||||
<a href="/#/tag/{{val.t_id}}" class="btn btn-large btn-primary"><i class="fa fa-line-chart"></i> View Data</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
79
tagserverApp/assets/templates/tagVals.html
Normal file
79
tagserverApp/assets/templates/tagVals.html
Normal file
@@ -0,0 +1,79 @@
|
||||
<style>
|
||||
.padMe {
|
||||
margin: 10px 20px;
|
||||
}
|
||||
|
||||
.timeLabel {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div ng-if="loading" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 well" style="text-align:center;">
|
||||
<h1>Loading Tag data...</h1>
|
||||
<img class="img-responsive" src="/images/loading.gif" style="margin:0 auto;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!loading">
|
||||
<div ng-if="error" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md=12">
|
||||
<h1>Error Caught!</h1>
|
||||
<pre>{{message}}</pre>
|
||||
<button ng-click="loadTagVals()" class="btn btn-large btn-danger"><i class="fa fa-refresh"></i> Reload Values</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!error" class="container">
|
||||
<div class="row" style="margin-bottom:20px;">
|
||||
<div class="col-md-12">
|
||||
<h1>{{tag.name}}</h1>
|
||||
<div class="row row-flex">
|
||||
<div class="col-md-4">
|
||||
<span class="timeLabel">From: </span><quick-datepicker ng-model='startDatetime'></quick-datepicker>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<span class="timeLabel">To: </span><quick-datepicker ng-model='endDatetime'></quick-datepicker>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<button ng-click="loadTagVals(startDatetime, endDatetime)" class="btn btn-large btn-success padMe"><i class="fa fa-refresh"></i> Reload Values</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="tagChart" style="height:400px;">
|
||||
<linechart data="data" options="options"></linechart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row topMargin40">
|
||||
<div class="col-md-6">
|
||||
<a href="/json/CSV/{{tag.id}}/{{startDatetime | dString}}/{{endDatetime | dString }}" class="btn btn-large btn-primary padMe"><i class="fa fa-download"></i> Download Data</a>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>Value</td>
|
||||
<td>Date Added</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="val in data.vals">
|
||||
<td>{{val.id}}</td>
|
||||
<td>{{val.val}} {{tag.units}}</td>
|
||||
<td>{{val.dtime | date:'short'}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
244
tagserverApp/assets/templates/tags.html
Normal file
244
tagserverApp/assets/templates/tags.html
Normal file
@@ -0,0 +1,244 @@
|
||||
<div class="modal fade" id="addModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Add a New Tag...</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="well" ng-if="message"><h3 class="text-danger">{{message}}</h3></div>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="tag">Tag</label>
|
||||
<input type="text" ng-model="newTag.tag" class="form-control" id="tag" placeholder="Tag Name Here">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" ng-model="newTag.name" class="form-control" id="name" placeholder="Vanity Name Here">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<input type="textarea" ng-model="newTag.description" class="form-control" id="description" placeholder="Tag Description Here">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="data_type">Data Type</label>
|
||||
<select ng-model="newTag.data_type" class="form-control" id="data_type">
|
||||
<option value="REAL">Floating Point</option>
|
||||
<option value="DINT">Integer</option>
|
||||
<option value="BOOL">Boolean</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="form-group">
|
||||
<label for="minExpected">Minimum Value Expected</label>
|
||||
<input type="number" ng-model="newTag.minExpected" class="form-control" id="minExpected" placeholder="0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="form-group">
|
||||
<label for="maxExpected">Maximum Value Expected</label>
|
||||
<input type="number" ng-model="newTag.maxExpected" class="form-control" id="maxExpected" placeholder="100">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label for="units">Units</label>
|
||||
<input type="text" ng-model="newTag.units" class="form-control" id="units" placeholder="lbs, PSI, in, etc.">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="change_threshold">Change Threshold</label>
|
||||
<input type="number" ng-model="newTag.change_threshold" class="form-control" id="change_threshold" placeholder="0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="guarantee_sec">Guarantee Sec.</label>
|
||||
<input type="number" ng-model="newTag.guarantee_sec" class="form-control" id="guarantee_sec" placeholder="3600">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" ng-click="submitAddTag();" data-dismiss="modal">Add Tag</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
|
||||
<div class="modal fade" id="editModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Edit a Tag...</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="well" ng-if="message"><h3 class="text-danger">{{message}}</h3></div>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="tag">Tag Name</label>
|
||||
<input type="text" ng-model="editTag.tag" class="form-control" id="tag" placeholder="Tag Name Here">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Vanity Name</label>
|
||||
<input type="text" ng-model="editTag.name" class="form-control" id="name" placeholder="Vanity Name Here">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<input type="textarea" ng-model="editTag.description" class="form-control" id="description" placeholder="Tag Description Here">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="data_type">Data Type</label>
|
||||
<select ng-model="editTag.data_type" class="form-control" id="data_type">
|
||||
<option value="REAL">Floating Point</option>
|
||||
<option value="DINT">Integer</option>
|
||||
<option value="BOOL">Boolean</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="form-group">
|
||||
<label for="minExpected">Minimum Value Expected</label>
|
||||
<input type="number" ng-model="editTag.minExpected" class="form-control" id="minExpected" placeholder="0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="form-group">
|
||||
<label for="maxExpected">Maximum Value Expected</label>
|
||||
<input type="number" ng-model="editTag.maxExpected" class="form-control" id="maxExpected" placeholder="100">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label for="units">Units</label>
|
||||
<input type="text" ng-model="editTag.units" class="form-control" id="units" placeholder="lbs, PSI, in, etc.">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="change_threshold">Change Threshold</label>
|
||||
<input type="number" ng-model="editTag.change_threshold" class="form-control" id="change_threshold" placeholder="0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="guarantee_sec">Guarantee Sec.</label>
|
||||
<input type="number" ng-model="editTag.guarantee_sec" class="form-control" id="guarantee_sec" placeholder="3600">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<pre>{{editTag}}</pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" ng-click="submitEditTag();" data-dismiss="modal">Submit Tag Edits</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
|
||||
<div class="modal fade" id="deleteModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Are you sure?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="well" ng-if="message"><h3 class="text-danger">{{message}}</h3></div>
|
||||
<h3>Are you sure you want to delete the tag {{dTag.name}} ({{dTag.tag}})?</h3>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">NO!!!!!!</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="deleteTag(dTag.id);" data-dismiss="modal">Heck yes, delete it!</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div class="modal fade" id="clearTagDataModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Are you sure?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="well" ng-if="message"><h3 class="text-danger">{{message}}</h3></div>
|
||||
<h3>Are you sure you want to delete the data for tag {{dTagValues.name}} ({{dTagValues.tag}})?</h3>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">NO!!!!!!</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="deleteTagValues(dTagValues.id);" data-dismiss="modal">Heck yes, delete it!</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
|
||||
|
||||
|
||||
<div ng-if="loading" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 well" style="text-align:center;">
|
||||
<h1>Loading Tags..</h1>
|
||||
<img class="img-responsive" src="/images/loading.gif" style="margin:0 auto;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!loading">
|
||||
<div ng-if="error" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md=12">
|
||||
<h1>Error Caught!</h1>
|
||||
<pre>{{message}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!error" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>Name</td>
|
||||
<td>Min Expected Value</td>
|
||||
<td>Max Expected Value</td>
|
||||
<td>Units</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="tag in tags">
|
||||
<td>{{tag.id}}</td>
|
||||
<td><a href="/#/tag/{{tag.id}}">{{tag.name}}</a> <i class="fa fa-info-circle" data-toggle="popover" title="{{tag.name}}" data-content="Tag Name: {{tag.tag}} </br>Details: {{tag.description}}<br/>Type: {{tag.data_type}}"></i></td>
|
||||
<td>{{tag.minExpected}}</td>
|
||||
<td>{{tag.maxExpected}}</td>
|
||||
<td>{{tag.units}}</td>
|
||||
<td><button data-toggle="modal" data-target="#editModal" ng-click="openEditTag(tag.id)" class="btn btn-primary">Edit</button></td>
|
||||
<td><button data-toggle="modal" data-target="#clearTagDataModal" ng-click="openClearTagData(tag.id)" class="btn btn-primary">Clear Data</button></td>
|
||||
<td><button data-toggle="modal" data-target="#deleteModal" ng-click="openDeleteTag(tag.id)" class="btn btn-danger">Delete</button></td>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('[data-toggle="popover"]').popover({html: true});
|
||||
});
|
||||
</script>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addModal">
|
||||
Add Tag
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
30
tagserverApp/bower.json
Normal file
30
tagserverApp/bower.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "TagServer",
|
||||
"description": "Tag Datalogger for Rockwell PLC & MySQL/SQLite DB",
|
||||
"main": "app.js",
|
||||
"authors": [
|
||||
"Patrick McDonagh"
|
||||
],
|
||||
"license": "ISC",
|
||||
"moduleType": [],
|
||||
"homepage": "",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"angular-justgage": "~1.0.1",
|
||||
"angular": "angularjs#~1.4.9",
|
||||
"bootstrap": "~3.3.6",
|
||||
"angular-route": "~1.4.9",
|
||||
"font-awesome": "~4.5.0",
|
||||
"ngQuickDate": "^1.3.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"angular": "~1.4.9"
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,9 @@ module.exports.connections = {
|
||||
* Installed by default. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
localDiskDb: {
|
||||
adapter: 'sails-disk'
|
||||
},
|
||||
// localDiskDb: {
|
||||
// adapter: 'sails-disk'
|
||||
// },
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports.models = {
|
||||
* connections (see `config/connections.js`) *
|
||||
* *
|
||||
***************************************************************************/
|
||||
// connection: 'localDiskDb',
|
||||
connection: 'mysqlDb',
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
@@ -27,6 +27,6 @@ module.exports.models = {
|
||||
* See http://sailsjs.org/#!/documentation/concepts/ORM/model-settings.html *
|
||||
* *
|
||||
***************************************************************************/
|
||||
// migrate: 'alter'
|
||||
migrate: 'alter'
|
||||
|
||||
};
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
"grunt-contrib-uglify": "0.7.0",
|
||||
"grunt-contrib-watch": "0.5.3",
|
||||
"grunt-sails-linker": "~0.10.1",
|
||||
"grunt-bower": "*",
|
||||
"grunt-sync": "0.2.4",
|
||||
"include-all": "~0.1.6",
|
||||
"rc": "1.0.1",
|
||||
"sails": "~0.12.3",
|
||||
"sails-disk": "~0.10.9"
|
||||
"sails-disk": "~0.10.9",
|
||||
"n3-charts": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"debug": "node debug app.js",
|
||||
@@ -34,4 +36,4 @@
|
||||
},
|
||||
"author": "patrickjmcd",
|
||||
"license": ""
|
||||
}
|
||||
}
|
||||
|
||||
56
tagserverApp/public/fonts/less/bootstrap.less
vendored
Normal file
56
tagserverApp/public/fonts/less/bootstrap.less
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*!
|
||||
* Bootstrap v3.3.6 (http://getbootstrap.com)
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
// Core variables and mixins
|
||||
@import "variables.less";
|
||||
@import "mixins.less";
|
||||
|
||||
// Reset and dependencies
|
||||
@import "normalize.less";
|
||||
@import "print.less";
|
||||
@import "glyphicons.less";
|
||||
|
||||
// Core CSS
|
||||
@import "scaffolding.less";
|
||||
@import "type.less";
|
||||
@import "code.less";
|
||||
@import "grid.less";
|
||||
@import "tables.less";
|
||||
@import "forms.less";
|
||||
@import "buttons.less";
|
||||
|
||||
// Components
|
||||
@import "component-animations.less";
|
||||
@import "dropdowns.less";
|
||||
@import "button-groups.less";
|
||||
@import "input-groups.less";
|
||||
@import "navs.less";
|
||||
@import "navbar.less";
|
||||
@import "breadcrumbs.less";
|
||||
@import "pagination.less";
|
||||
@import "pager.less";
|
||||
@import "labels.less";
|
||||
@import "badges.less";
|
||||
@import "jumbotron.less";
|
||||
@import "thumbnails.less";
|
||||
@import "alerts.less";
|
||||
@import "progress-bars.less";
|
||||
@import "media.less";
|
||||
@import "list-group.less";
|
||||
@import "panels.less";
|
||||
@import "responsive-embed.less";
|
||||
@import "wells.less";
|
||||
@import "close.less";
|
||||
|
||||
// Components w/ JavaScript
|
||||
@import "modals.less";
|
||||
@import "tooltip.less";
|
||||
@import "popovers.less";
|
||||
@import "carousel.less";
|
||||
|
||||
// Utility classes
|
||||
@import "utilities.less";
|
||||
@import "responsive-utilities.less";
|
||||
12
tagserverApp/tasks/config/bower.js
Normal file
12
tagserverApp/tasks/config/bower.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = function(grunt) {
|
||||
grunt.config.set('bower', {
|
||||
dev: {
|
||||
dest: '.tmp/public',
|
||||
js_dest: '.tmp/public/js',
|
||||
css_dest: '.tmp/public/styles',
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-bower');
|
||||
|
||||
};
|
||||
@@ -21,15 +21,33 @@
|
||||
*/
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.config.set('copy', {
|
||||
dev: {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: './assets',
|
||||
src: ['**/*.!(coffee|less)'],
|
||||
dest: '.tmp/public'
|
||||
}]
|
||||
},
|
||||
grunt.config.set('copy', {
|
||||
dev: {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: './assets',
|
||||
src: ['**/*.!(coffee|less)'],
|
||||
dest: '.tmp/public'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
cwd: './node_modules/d3',
|
||||
src: ['d3.min.js'],
|
||||
dest: '.tmp/public/js'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
cwd: './node_modules/n3-charts/build',
|
||||
src: ['LineChart.js'],
|
||||
dest: '.tmp/public/js'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
cwd: './node_modules/n3-charts/build',
|
||||
src: ['LineChart.css'],
|
||||
dest: '.tmp/public/styles'
|
||||
}]
|
||||
},
|
||||
build: {
|
||||
files: [{
|
||||
expand: true,
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
// (if you're using LESS with the built-in default config, you'll want
|
||||
// to change `assets/styles/importer.less` instead.)
|
||||
var cssFilesToInject = [
|
||||
'styles/**/*.css'
|
||||
'styles/**/*.css',
|
||||
'less/**/*.less'
|
||||
];
|
||||
|
||||
|
||||
@@ -33,6 +34,18 @@ var jsFilesToInject = [
|
||||
|
||||
// All of the rest of your client-side js files
|
||||
// will be injected here in no particular order.
|
||||
'js/angular.js',
|
||||
'js/angular-route.js',
|
||||
'js/dist/jquery.js',
|
||||
'js/raphael.js',
|
||||
'js/dist/js/bootstrap.js',
|
||||
'js/dist/ng-quick-date.js',
|
||||
'js/justgage.js',
|
||||
'js/ng-justgage.js',
|
||||
'js/d3.min.js',
|
||||
'js/LineChart.js',
|
||||
'js/router.js',
|
||||
'js/controller.js',
|
||||
'js/**/*.js'
|
||||
];
|
||||
|
||||
@@ -71,5 +84,3 @@ module.exports.jsFilesToInject = jsFilesToInject.map(function(jsPath) {
|
||||
module.exports.templateFilesToInject = templateFilesToInject.map(function(tplPath) {
|
||||
return require('path').join('assets/',tplPath);
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
module.exports = function(grunt) {
|
||||
grunt.registerTask('compileAssets', [
|
||||
'clean:dev',
|
||||
'bower:dev', // ADDED
|
||||
'jst:dev',
|
||||
'less:dev',
|
||||
'copy:dev',
|
||||
|
||||
74
tagserverApp/views/homepage.bak.ejs
Normal file
74
tagserverApp/views/homepage.bak.ejs
Normal file
@@ -0,0 +1,74 @@
|
||||
<!-- Default home page -->
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400italic,600' rel='stylesheet' type='text/css'>
|
||||
<style>
|
||||
/* Styles included inline since you'll probably be deleting this page anyway */
|
||||
html,body{text-align:left;font-size:1em}html,body,img,form,textarea,input,fieldset,div,p,div,ul,li,ol,dl,dt,dd,h1,h2,h3,h4,h5,h6,pre,code{margin:0;padding:0}ul,li{list-style:none}img{display:block}a img{border:0}a{text-decoration:none;font-weight:normal;font-family:inherit}*:active,*:focus{outline:0;-moz-outline-style:none}h1,h2,h3,h4,h5,h6{font-weight:normal}div.clear{clear:both}.clearfix:after{clear:both;content:".";display:block;font-size:0;height:0;line-height:0;visibility:hidden}body{font-family:"Open Sans",Arial,sans-serif;font-weight:300;}.top-bar {width: 100%; background-color: #e4f0f1; padding: 15px 0;}.top-bar .container img {float: left;}.top-bar .container ul {float: right; padding-top: 25px;}.top-bar .container li {float: left; width: 125px; text-align: center; font-size: 15px; color:#000; font-weight: 600;}.top-bar .container a li:hover {color: #118798; -webkit-transition:color 200ms; -moz-transition:color 200ms; -o-transition:color 200ms;transition:color 200ms;}.container{width: 80%; max-width: 1200px; margin: auto;}div.header {-webkit-transition: 6s; -moz-transition: 6s; -o-transition: 6s;transition: 6s; background: rgba(4, 36, 41, 0.89) url(http://sailsjs.org/images/img_sailsShadow.png) no-repeat 42% bottom; padding: 100px 0 65px;}.header h1#main-title{color: #fff; font-weight: 300; font-size: 2.5em;}.header h3{color: #b1eef7; font-style: italic; font-weight: 300;}.header h3 code{font-style: normal!important; background-color: rgba(255,255,255,0.5); font-weight: 300; color:#0e6471; margin: 0px 5px;}div.main.container{padding: 50px 0;}h1 {color: #118798; font-weight: 300;}code {font-size: inherit; font-family: 'Consolas', 'Monaco', monospace; padding:4px 5px 1px; background-color: #f3f5f7}a{color: #118798; font-weight: 300; text-decoration: underline;}a:hover {color: #0e6471; -webkit-transition:color 200ms; -moz-transition:color 200ms; -o-transition:color 200ms;transition:color 200ms;}p{line-height: 1.5em;}blockquote{background-color: #e4f0f1; padding: 25px; line-height: 1.5em; margin: 15px 0;}blockquote span{font-weight: 600; padding-right: 5px;}ul.getting-started{padding: 25px 75px 25px 0; width: 70%; float: left; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;}ul.getting-started li{padding: 25px 0;}ul.getting-started li h3 {padding-bottom: 10px; font-size: 25px; font-weight: 300;}.sprite{background:url(http://sailsjs.org/images/newapp.sprite.png) no-repeat; position: absolute; left: 0; top:0;}.getting-started .sprite{margin-left:10px;padding-left:60px;height:42px;width:0; float: left;}.getting-started .one{background-position:0 0}.getting-started .two{background-position:0 -42px}.getting-started .three{background-position:0 -83px}div.step {position: relative; padding-left: 70px; opacity: 0.9;}div.step:hover{ opacity: 1;}div.links {float: left; width: 30%; max-width: 325px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; background-color: #f3f5f7; border: 1px solid #ebebeb; padding: 25px 45px 35px;}div.links h3 {color: #727272; text-align: center; font-size: 28px; font-weight: 300;}div.links h4 {color: #727272; font-size: 17px; font-weight: 600; padding: 15px 0 10px;}div.links .link-list a {text-decoration: none; font-weight: 400;}div.links .link-list a li {padding: 0px 0px 5px 10px;}div.default-page{min-width: 1200px;}.pocket{display:none;}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
setTimeout(function sunrise () {
|
||||
document.getElementsByClassName('header')[0].style.backgroundColor = '#118798';
|
||||
}, 0);
|
||||
</script>
|
||||
|
||||
<div class="default-page">
|
||||
<div class="header">
|
||||
<h1 id="main-title" class="container"><%= __('A brand new app.') %></h1>
|
||||
<h3 class="container">You're looking at: <code><%= view.pathFromApp + '.' +view.ext %></code></h3>
|
||||
</div>
|
||||
<div class="main container clearfix">
|
||||
<!-- <h1>Getting started</h1>
|
||||
<p>Don't worry, we've got your back.</p> -->
|
||||
<ul class="getting-started">
|
||||
<li class="clearfix">
|
||||
<div class="step">
|
||||
<div class="sprite one"></div>
|
||||
<h3>Generate a REST API.</h3>
|
||||
<p>
|
||||
Run <code>sails generate api user</code>. This will create two files: a <a href="http://sailsjs.org/#!/documentation/concepts/ORM/Models.html">model</a> <code class="pocket">api/models/User.js</code> and a <a href="http://sailsjs.org/#!/documentation/concepts/Controllers">controller</a><code class="pocket">api/controllers/UserController.js</code>.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="clearfix">
|
||||
<div class="step">
|
||||
<div class="sprite two"></div>
|
||||
<h3>
|
||||
Lift your app.
|
||||
</h3>
|
||||
<p>
|
||||
Run <code>sails lift</code> to start up your app server. If you visit <a target="_blank" href="http://localhost:<%= sails.config.port || 1337%>/user"><code>http://localhost:<%= sails.config.port || 1337%>/user</code></a> in your browser, you'll see a <a href="http://sailsjs.org/#!/documentation/reference/blueprint-api">WebSocket-compatible</a> user API.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="clearfix">
|
||||
<div class="step">
|
||||
<div class="sprite three"></div>
|
||||
<h3>
|
||||
Dive in.
|
||||
</h3>
|
||||
<p>Blueprints are just the beginning. You'll probably also want to learn how to customize your app's <a href="http://sailsjs.org/#!/documentation/concepts/Routes">routes</a>, set up <a href="http://sailsjs.org/#!/documentation/concepts/Policies">security policies</a>, configure your <a href="http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.connections.html">data sources</a>, and build custom <a target="_blank" href="http://sailsjs.org/#!/documentation/concepts/Controllers?q=actions">controller actions</a>. For more help getting started, check out the links on this page.</p>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="links">
|
||||
<!-- <h3>Links</h3> -->
|
||||
<ul class="link-list">
|
||||
|
||||
<h4>Docs</h4>
|
||||
<a target="_blank" href="http://sailsjs.org/#!/documentation/anatomy/myApp"><li>App Structure</li></a>
|
||||
<a target="_blank" href="http://sailsjs.org/#!/documentation/reference"><li>Reference</li></a>
|
||||
<a target="_blank" href="http://sailsjs.org/#!/documentation/concepts/extending-sails/Adapters/adapterList.html"><li>Supported Databases</li></a>
|
||||
|
||||
<h4>Tutorials</h4>
|
||||
<a target="_blank" href="https://github.com/sails101"><li>Sails 101</li></a>
|
||||
|
||||
<h4>Community</h4>
|
||||
<a target="_blank" href="http://stackoverflow.com/search?q=sails.js"><li>StackOverFlow</li></a>
|
||||
<a target="_blank" href="https://github.com/balderdashy/sails"><li>GitHub</li></a>
|
||||
<a target="_blank" href="https://groups.google.com/forum/#!forum/sailsjs"><li>Google Group</li></a>
|
||||
<a target="_blank" href="http://webchat.freenode.net/"><li>IRC (#sailsjs on freenode)</li></a>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,74 +1,29 @@
|
||||
<!-- Default home page -->
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400italic,600' rel='stylesheet' type='text/css'>
|
||||
<style>
|
||||
/* Styles included inline since you'll probably be deleting this page anyway */
|
||||
html,body{text-align:left;font-size:1em}html,body,img,form,textarea,input,fieldset,div,p,div,ul,li,ol,dl,dt,dd,h1,h2,h3,h4,h5,h6,pre,code{margin:0;padding:0}ul,li{list-style:none}img{display:block}a img{border:0}a{text-decoration:none;font-weight:normal;font-family:inherit}*:active,*:focus{outline:0;-moz-outline-style:none}h1,h2,h3,h4,h5,h6{font-weight:normal}div.clear{clear:both}.clearfix:after{clear:both;content:".";display:block;font-size:0;height:0;line-height:0;visibility:hidden}body{font-family:"Open Sans",Arial,sans-serif;font-weight:300;}.top-bar {width: 100%; background-color: #e4f0f1; padding: 15px 0;}.top-bar .container img {float: left;}.top-bar .container ul {float: right; padding-top: 25px;}.top-bar .container li {float: left; width: 125px; text-align: center; font-size: 15px; color:#000; font-weight: 600;}.top-bar .container a li:hover {color: #118798; -webkit-transition:color 200ms; -moz-transition:color 200ms; -o-transition:color 200ms;transition:color 200ms;}.container{width: 80%; max-width: 1200px; margin: auto;}div.header {-webkit-transition: 6s; -moz-transition: 6s; -o-transition: 6s;transition: 6s; background: rgba(4, 36, 41, 0.89) url(http://sailsjs.org/images/img_sailsShadow.png) no-repeat 42% bottom; padding: 100px 0 65px;}.header h1#main-title{color: #fff; font-weight: 300; font-size: 2.5em;}.header h3{color: #b1eef7; font-style: italic; font-weight: 300;}.header h3 code{font-style: normal!important; background-color: rgba(255,255,255,0.5); font-weight: 300; color:#0e6471; margin: 0px 5px;}div.main.container{padding: 50px 0;}h1 {color: #118798; font-weight: 300;}code {font-size: inherit; font-family: 'Consolas', 'Monaco', monospace; padding:4px 5px 1px; background-color: #f3f5f7}a{color: #118798; font-weight: 300; text-decoration: underline;}a:hover {color: #0e6471; -webkit-transition:color 200ms; -moz-transition:color 200ms; -o-transition:color 200ms;transition:color 200ms;}p{line-height: 1.5em;}blockquote{background-color: #e4f0f1; padding: 25px; line-height: 1.5em; margin: 15px 0;}blockquote span{font-weight: 600; padding-right: 5px;}ul.getting-started{padding: 25px 75px 25px 0; width: 70%; float: left; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;}ul.getting-started li{padding: 25px 0;}ul.getting-started li h3 {padding-bottom: 10px; font-size: 25px; font-weight: 300;}.sprite{background:url(http://sailsjs.org/images/newapp.sprite.png) no-repeat; position: absolute; left: 0; top:0;}.getting-started .sprite{margin-left:10px;padding-left:60px;height:42px;width:0; float: left;}.getting-started .one{background-position:0 0}.getting-started .two{background-position:0 -42px}.getting-started .three{background-position:0 -83px}div.step {position: relative; padding-left: 70px; opacity: 0.9;}div.step:hover{ opacity: 1;}div.links {float: left; width: 30%; max-width: 325px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; background-color: #f3f5f7; border: 1px solid #ebebeb; padding: 25px 45px 35px;}div.links h3 {color: #727272; text-align: center; font-size: 28px; font-weight: 300;}div.links h4 {color: #727272; font-size: 17px; font-weight: 600; padding: 15px 0 10px;}div.links .link-list a {text-decoration: none; font-weight: 400;}div.links .link-list a li {padding: 0px 0px 5px 10px;}div.default-page{min-width: 1200px;}.pocket{display:none;}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
setTimeout(function sunrise () {
|
||||
document.getElementsByClassName('header')[0].style.backgroundColor = '#118798';
|
||||
}, 0);
|
||||
</script>
|
||||
|
||||
<div class="default-page">
|
||||
<div class="header">
|
||||
<h1 id="main-title" class="container"><%= __('A brand new app.') %></h1>
|
||||
<h3 class="container">You're looking at: <code><%= view.pathFromApp + '.' +view.ext %></code></h3>
|
||||
</div>
|
||||
<div class="main container clearfix">
|
||||
<!-- <h1>Getting started</h1>
|
||||
<p>Don't worry, we've got your back.</p> -->
|
||||
<ul class="getting-started">
|
||||
<li class="clearfix">
|
||||
<div class="step">
|
||||
<div class="sprite one"></div>
|
||||
<h3>Generate a REST API.</h3>
|
||||
<p>
|
||||
Run <code>sails generate api user</code>. This will create two files: a <a href="http://sailsjs.org/#!/documentation/concepts/ORM/Models.html">model</a> <code class="pocket">api/models/User.js</code> and a <a href="http://sailsjs.org/#!/documentation/concepts/Controllers">controller</a><code class="pocket">api/controllers/UserController.js</code>.
|
||||
</p>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" rel="home" href="/#/" title="Henry Pump">
|
||||
<img style="max-width:100px; "src="/images/logo.png">
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="clearfix">
|
||||
<div class="step">
|
||||
<div class="sprite two"></div>
|
||||
<h3>
|
||||
Lift your app.
|
||||
</h3>
|
||||
<p>
|
||||
Run <code>sails lift</code> to start up your app server. If you visit <a target="_blank" href="http://localhost:<%= sails.config.port || 1337%>/user"><code>http://localhost:<%= sails.config.port || 1337%>/user</code></a> in your browser, you'll see a <a href="http://sailsjs.org/#!/documentation/reference/blueprint-api">WebSocket-compatible</a> user API.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="clearfix">
|
||||
<div class="step">
|
||||
<div class="sprite three"></div>
|
||||
<h3>
|
||||
Dive in.
|
||||
</h3>
|
||||
<p>Blueprints are just the beginning. You'll probably also want to learn how to customize your app's <a href="http://sailsjs.org/#!/documentation/concepts/Routes">routes</a>, set up <a href="http://sailsjs.org/#!/documentation/concepts/Policies">security policies</a>, configure your <a href="http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.connections.html">data sources</a>, and build custom <a target="_blank" href="http://sailsjs.org/#!/documentation/concepts/Controllers?q=actions">controller actions</a>. For more help getting started, check out the links on this page.</p>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="links">
|
||||
<!-- <h3>Links</h3> -->
|
||||
<ul class="link-list">
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li ng-class="{active: Page.page() == 'dashboard'}"><a href="/#/"><i class="fa fa-home"></i> Dashboard</a></li>
|
||||
<li ng-class="{active: Page.page() == 'tags'}"><a href="/#/tags"><i class="fa fa-tags"></i> Tags</a></li>
|
||||
|
||||
<h4>Docs</h4>
|
||||
<a target="_blank" href="http://sailsjs.org/#!/documentation/anatomy/myApp"><li>App Structure</li></a>
|
||||
<a target="_blank" href="http://sailsjs.org/#!/documentation/reference"><li>Reference</li></a>
|
||||
<a target="_blank" href="http://sailsjs.org/#!/documentation/concepts/extending-sails/Adapters/adapterList.html"><li>Supported Databases</li></a>
|
||||
|
||||
<h4>Tutorials</h4>
|
||||
<a target="_blank" href="https://github.com/sails101"><li>Sails 101</li></a>
|
||||
|
||||
<h4>Community</h4>
|
||||
<a target="_blank" href="http://stackoverflow.com/search?q=sails.js"><li>StackOverFlow</li></a>
|
||||
<a target="_blank" href="https://github.com/balderdashy/sails"><li>GitHub</li></a>
|
||||
<a target="_blank" href="https://groups.google.com/forum/#!forum/sailsjs"><li>Google Group</li></a>
|
||||
<a target="_blank" href="http://webchat.freenode.net/"><li>IRC (#sailsjs on freenode)</li></a>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li ng-class="{active: Page.page() == 'configuration'}"><a href="/#/config"><i class="fa fa-cog"></i> Configuration</a></li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
<div ng-view style="margin-top:40px;"></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html ng-app="tagserver" ng-controller="mainCtrl">
|
||||
<head>
|
||||
<title><%=typeof title == 'undefined' ? 'New Sails App' : title%></title>
|
||||
|
||||
@@ -29,7 +29,15 @@
|
||||
-->
|
||||
|
||||
<!--STYLES-->
|
||||
<link rel="stylesheet" href="/styles/LineChart.css">
|
||||
<link rel="stylesheet" href="/styles/app.css">
|
||||
<link rel="stylesheet" href="/styles/bootstrap-theme.min.css">
|
||||
<link rel="stylesheet" href="/styles/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/styles/dist/ng-quick-date-default-theme.css">
|
||||
<link rel="stylesheet" href="/styles/dist/ng-quick-date.css">
|
||||
<link rel="stylesheet" href="/styles/importer.css">
|
||||
<link rel="stylesheet" href="/less/bootstrap.less">
|
||||
<link rel="stylesheet" href="/less/font-awesome.less">
|
||||
<!--STYLES END-->
|
||||
</head>
|
||||
|
||||
@@ -60,7 +68,7 @@
|
||||
-->
|
||||
|
||||
<!--TEMPLATES-->
|
||||
|
||||
<script type="text/javascript" src="/jst.js"></script>
|
||||
<!--TEMPLATES END-->
|
||||
|
||||
|
||||
@@ -89,6 +97,19 @@
|
||||
|
||||
<!--SCRIPTS-->
|
||||
<script src="/js/dependencies/sails.io.js"></script>
|
||||
<script src="/js/dependencies/sugar.min.js"></script>
|
||||
<script src="/js/angular.js"></script>
|
||||
<script src="/js/angular-route.js"></script>
|
||||
<script src="/js/dist/jquery.js"></script>
|
||||
<script src="/js/raphael.js"></script>
|
||||
<script src="/js/dist/js/bootstrap.js"></script>
|
||||
<script src="/js/dist/ng-quick-date.js"></script>
|
||||
<script src="/js/justgage.js"></script>
|
||||
<script src="/js/ng-justgage.js"></script>
|
||||
<script src="/js/d3.min.js"></script>
|
||||
<script src="/js/LineChart.js"></script>
|
||||
<script src="/js/router.js"></script>
|
||||
<script src="/js/controller.js"></script>
|
||||
<!--SCRIPTS END-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user