mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Discovery Panel Skeleton
- renamed calculateIndices files to be calculate_indices - hooked up dataSource.getFields() to the mapper, uses source._wrapcb() to properly trigger digest cycles - fixed an error handling bug in the search source - courier error DocFetchFailure is now just FetchFailure and will be sent from SearchSources as well - courier/index_pattern module is now gone - fixed a bug in the mapper that improperly triggered errors when a pattern matched multiple indices that had similar fields - prototype for discover app is included - directives/kbn_view module is now directives/view, the kbn prefix is implied - added basic table directive
This commit is contained in:
parent
661d89f741
commit
6cb518b035
22 changed files with 338 additions and 87 deletions
|
@ -24,7 +24,11 @@ define(function (require) {
|
|||
// execute a search right now
|
||||
search: function (courier) {
|
||||
if (courier._activeSearchRequest) {
|
||||
return courier._error(new HastyRefresh());
|
||||
// ensure that this happens async, otherwise listeners
|
||||
// might miss error events
|
||||
return nextTick(function () {
|
||||
courier._error(new HastyRefresh());
|
||||
});
|
||||
}
|
||||
|
||||
courier._activeSearchRequest = SearchSource.fetch(
|
||||
|
@ -174,19 +178,24 @@ define(function (require) {
|
|||
}, this);
|
||||
};
|
||||
|
||||
// be default, the courier will throw an error if a fetch
|
||||
// occurs before a previous fetch finishes. To prevent this, you
|
||||
// should call abort before calling .fetch()
|
||||
Courier.prototype.abort = function () {
|
||||
if (this._activeSearchRequest) {
|
||||
this._activeSearchRequest.abort();
|
||||
this._activeSearchRequest = null;
|
||||
}
|
||||
};
|
||||
|
||||
// force a fetch of all datasources right now, optionally filter by type
|
||||
Courier.prototype.fetch = function (onlyType) {
|
||||
var courier = this;
|
||||
// ensure that onFetch functions always run after the tick
|
||||
// so that users can will be able to listen after or before the call to
|
||||
// fetch and always get the same behavior (even if the onFetch runs synchronously)
|
||||
nextTick(function () {
|
||||
_.forOwn(onFetch, function (fn, type) {
|
||||
if (onlyType && onlyType !== type) return;
|
||||
if (courier._refs[type].length) fn(courier);
|
||||
courier._refs[type].forEach(function (ref) {
|
||||
ref.fetchCount ++;
|
||||
});
|
||||
_.forOwn(onFetch, function (fn, type) {
|
||||
if (onlyType && onlyType !== type) return;
|
||||
if (courier._refs[type].length) fn(courier);
|
||||
courier._refs[type].forEach(function (ref) {
|
||||
ref.fetchCount ++;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,7 +3,6 @@ define(function (require) {
|
|||
var _ = require('lodash');
|
||||
var EventEmitter = require('utils/event_emitter');
|
||||
var Mapper = require('courier/mapper');
|
||||
var IndexPattern = require('courier/index_pattern');
|
||||
|
||||
function DataSource(courier, initialState) {
|
||||
var state;
|
||||
|
@ -54,9 +53,6 @@ define(function (require) {
|
|||
this._methods.forEach(function (name) {
|
||||
this[name] = function (val) {
|
||||
state[name] = val;
|
||||
if (name === 'index' && arguments[1]) {
|
||||
state.index = new IndexPattern(val, arguments[1]);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
}, this);
|
||||
|
@ -81,8 +77,8 @@ define(function (require) {
|
|||
* @callback {Error, Array} - calls cb with a possible error or an array of field names
|
||||
* @todo
|
||||
*/
|
||||
DataSource.prototype.getFieldNames = function (cb) {
|
||||
throw new Error('not implemented');
|
||||
DataSource.prototype.getFields = function (cb) {
|
||||
this._courier._mapper.getFields(this, this._wrapcb(cb));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -114,32 +110,33 @@ define(function (require) {
|
|||
* @return {this} - chainable
|
||||
*/
|
||||
DataSource.prototype.$scope = function ($scope) {
|
||||
var emitter = this;
|
||||
var courier = this;
|
||||
|
||||
if (emitter._emitter$scope) {
|
||||
emitter._emitter$scope = $scope;
|
||||
if (courier._$scope) {
|
||||
// simply change the scope that callbacks will point to
|
||||
courier._$scope = $scope;
|
||||
return this;
|
||||
}
|
||||
|
||||
emitter._emitter$scope = $scope;
|
||||
var origOn = emitter.on;
|
||||
courier._$scope = $scope;
|
||||
|
||||
emitter.on = function (event, listener) {
|
||||
var wrapped = function () {
|
||||
var args = arguments;
|
||||
// always use the stored ref so that it can be updated if needed
|
||||
var $scope = emitter._emitter$scope;
|
||||
$scope[$scope.$$phase ? '$eval' : '$apply'](function () {
|
||||
listener.apply(emitter, args);
|
||||
});
|
||||
};
|
||||
// wrap the 'on' method so that all listeners
|
||||
// can be wrapped in calls to $scope.$apply
|
||||
var origOn = courier.on;
|
||||
courier.on = function (event, listener) {
|
||||
var wrapped = courier._wrapcb(listener);
|
||||
// set .listener so that it can be removed by
|
||||
// .removeListener() using the original function
|
||||
wrapped.listener = listener;
|
||||
return origOn.call(emitter, event, wrapped);
|
||||
return origOn.call(courier, event, wrapped);
|
||||
};
|
||||
|
||||
emitter.on.restore = function () {
|
||||
delete emitter._emitter$scope;
|
||||
emitter.on = origOn;
|
||||
// make sure the alias is still set
|
||||
courier.addListener = courier.on;
|
||||
|
||||
courier.on.restore = function () {
|
||||
delete courier._$scope;
|
||||
courier.on = courier.addListener = origOn;
|
||||
};
|
||||
|
||||
return this;
|
||||
|
@ -213,11 +210,22 @@ define(function (require) {
|
|||
return flatState;
|
||||
};
|
||||
|
||||
DataSource.prototype._resolveIndexPattern = function (start, end) {
|
||||
if (this._state.indexInterval) {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
return this._state.index;
|
||||
DataSource.prototype._wrapcb = function (cb) {
|
||||
var courier = this;
|
||||
var wrapped = function () {
|
||||
var args = arguments;
|
||||
// always use the stored ref so that it can be updated if needed
|
||||
var $scope = courier._$scope;
|
||||
|
||||
// don't fall apart if we don't have a scope
|
||||
if (!$scope) return cb.apply(courier, args);
|
||||
|
||||
// use angular's $apply or $eval functions for the given scope
|
||||
$scope[$scope.$$phase ? '$eval' : '$apply'](function () {
|
||||
cb.apply(courier, args);
|
||||
});
|
||||
};
|
||||
return wrapped;
|
||||
};
|
||||
|
||||
return DataSource;
|
||||
|
|
|
@ -2,7 +2,8 @@ define(function (require) {
|
|||
var DataSource = require('courier/data_source/data_source');
|
||||
var inherits = require('utils/inherits');
|
||||
var nextTick = require('utils/next_tick');
|
||||
var errors = require('courier/errors');
|
||||
var VersionConflict = require('courier/errors').VersionConflict;
|
||||
var FetchFailure = require('courier/errors').FetchFailure;
|
||||
var listenerCount = require('utils/event_emitter').listenerCount;
|
||||
var _ = require('lodash');
|
||||
|
||||
|
@ -42,7 +43,7 @@ define(function (require) {
|
|||
var ref = allRefs[i];
|
||||
var source = ref.source;
|
||||
|
||||
if (resp.error) return source._error(new errors.DocFetchFailure(resp));
|
||||
if (resp.error) return source._error(new FetchFailure(resp));
|
||||
if (resp.found) {
|
||||
if (ref.version === resp._version) return; // no change
|
||||
ref.version = resp._version;
|
||||
|
@ -147,7 +148,7 @@ define(function (require) {
|
|||
if (err) return cb(err);
|
||||
|
||||
if (resp && resp.status === 409) {
|
||||
err = new errors.VersionConflict(resp);
|
||||
err = new VersionConflict(resp);
|
||||
if (listenerCount(source, 'conflict')) {
|
||||
return source.emit('conflict', err);
|
||||
} else {
|
||||
|
|
|
@ -2,6 +2,7 @@ define(function (require) {
|
|||
var DataSource = require('courier/data_source/data_source');
|
||||
var inherits = require('utils/inherits');
|
||||
var errors = require('courier/errors');
|
||||
var FetchFailure = require('courier/errors').FetchFailure;
|
||||
var _ = require('lodash');
|
||||
|
||||
function SearchSource(courier, initialState) {
|
||||
|
@ -44,7 +45,7 @@ define(function (require) {
|
|||
|
||||
_.each(resp.responses, function (resp, i) {
|
||||
var source = allRefs[i];
|
||||
if (resp.error) return errors.emit(source, courier, resp);
|
||||
if (resp.error) return source._error(new FetchFailure(resp));
|
||||
source.emit('results', resp);
|
||||
});
|
||||
|
||||
|
|
|
@ -38,17 +38,17 @@ define(function (require) {
|
|||
|
||||
|
||||
/**
|
||||
* DocFetchFailure Error - where there is an error getting a doc
|
||||
* FetchFailure Error - where there is an error getting a doc
|
||||
* @param {String} [msg] - An error message that will probably end up in a log.
|
||||
*/
|
||||
errors.DocFetchFailure = function DocFetchFailure(resp) {
|
||||
errors.FetchFailure = function FetchFailure(resp) {
|
||||
CourierError.call(this,
|
||||
'Failed to get the doc: ' + JSON.stringify(resp),
|
||||
errors.DocFetchFailure);
|
||||
errors.FetchFailure);
|
||||
|
||||
this.resp = resp;
|
||||
};
|
||||
inherits(errors.DocFetchFailure, CourierError);
|
||||
inherits(errors.FetchFailure, CourierError);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
define(function (require) {
|
||||
function IndexPattern(index, interval) {
|
||||
this.text = index;
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
IndexPattern.prototype = {
|
||||
toJSON: function () {
|
||||
return this.text;
|
||||
},
|
||||
toString: function () {
|
||||
return this.text;
|
||||
},
|
||||
forTimeRange: function () {
|
||||
throw new Error('not implemented');
|
||||
},
|
||||
wildcard: function () {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
};
|
||||
|
||||
return IndexPattern;
|
||||
});
|
|
@ -133,17 +133,15 @@ define(function (require) {
|
|||
|
||||
// TODO: Add week/month check
|
||||
client.indices.getFieldMapping(params, function (err, response, status) {
|
||||
|
||||
// TODO: Add error message
|
||||
|
||||
var fields = {};
|
||||
|
||||
_.each(response, function (index) {
|
||||
_.each(response, function (index, indexName) {
|
||||
if (indexName === config.cacheIndex) return;
|
||||
_.each(index.mappings, function (type) {
|
||||
_.each(type, function (field, name) {
|
||||
if (_.isUndefined(field.mapping) || name[0] === '_') return;
|
||||
if (!_.isUndefined(fields[name]) && fields[name] !== field.mapping[_.keys(field.mapping)[0]])
|
||||
return courier._error(new Error.MappingConflict());
|
||||
if (_.size(field.mapping) === 0 || name[0] === '_') return;
|
||||
if (!_.isUndefined(fields[name]) && fields[name].type !== field.mapping[_.keys(field.mapping)[0]].type)
|
||||
return courier._error(new Error.MappingConflict(name));
|
||||
fields[name] = field.mapping[_.keys(field.mapping)[0]];
|
||||
});
|
||||
});
|
||||
|
|
0
src/kibana/apps/dashboard/styles/main.html
Normal file
0
src/kibana/apps/dashboard/styles/main.html
Normal file
|
@ -1 +1,43 @@
|
|||
<h1>Discover</h1>
|
||||
<div ng-controller="discover">
|
||||
<h1>Discover</h1>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">Index</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" ng-model="index">
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="form-group">
|
||||
<label class="control-label col-sm-3">Repeat Interval</label>
|
||||
<div class="col-sm-9">
|
||||
<select
|
||||
class="form-control"
|
||||
ng-model="interval"
|
||||
ng-options="i.display for i in intervalOptions">
|
||||
</select>
|
||||
</div>
|
||||
</div> -->
|
||||
<form class="form-group" ng-submit="reset()">
|
||||
<label class="control-label col-sm-2">Query</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input class="form-control" ng-model="query" >
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn" ng-click="reset()">
|
||||
<i class="glyphicon glyphicon-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label class="control-label col-sm-2">Limit</label>
|
||||
<select
|
||||
class="form-control"
|
||||
ng-model="size"
|
||||
ng-options="size.display for size in sizeOptions">
|
||||
</select>
|
||||
</div>
|
||||
<kbn-table rows="rows" columns="columns"></kbn-table>
|
||||
</div>
|
|
@ -1,6 +1,103 @@
|
|||
define(function (require) {
|
||||
var angular = require('angular');
|
||||
var _ = require('lodash');
|
||||
|
||||
require('directives/table');
|
||||
require('css!./styles/main.css');
|
||||
|
||||
var app = angular.module('app/discover', []);
|
||||
|
||||
var sizeOptions = [
|
||||
{ display: '30', val: 30 },
|
||||
{ display: '50', val: 50 },
|
||||
{ display: '80', val: 80 },
|
||||
{ display: '125', val: 125 },
|
||||
{ display: '250', val: 250 },
|
||||
{ display: 'Unlimited', val: null },
|
||||
];
|
||||
|
||||
var intervalOptions = [
|
||||
{ display: '', val: null },
|
||||
{ display: 'Hourly', val: 'hourly' },
|
||||
{ display: 'Daily', val: 'daily' },
|
||||
{ display: 'Weekly', val: 'weekly' },
|
||||
{ display: 'Monthly', val: 'monthly' },
|
||||
{ display: 'Yearly', val: 'yearly' }
|
||||
];
|
||||
|
||||
app.controller('discover', function ($scope, courier, config) {
|
||||
var source = courier.rootSearchSource.extend()
|
||||
.size(30)
|
||||
.$scope($scope)
|
||||
.on('results', function (res) {
|
||||
if (!$scope.fields) getFields();
|
||||
$scope.rows = res.hits.hits;
|
||||
});
|
||||
|
||||
// stores the complete list of fields
|
||||
$scope.fields = [];
|
||||
|
||||
// stores the fields we want to fetch
|
||||
$scope.columns = [];
|
||||
|
||||
// At what interval are your index patterns
|
||||
$scope.intervalOptions = intervalOptions;
|
||||
$scope.interval = $scope.intervalOptions[0];
|
||||
|
||||
// options to control the size of the queries
|
||||
$scope.sizeOptions = sizeOptions;
|
||||
$scope.size = $scope.sizeOptions[0];
|
||||
|
||||
// watch the discover.defaultIndex config value for changes
|
||||
config.$watch('discover.defaultIndex', function (val) {
|
||||
if (!val) {
|
||||
config.set('discover.defaultIndex', '_all');
|
||||
return;
|
||||
}
|
||||
// only set if datasource doesn't have an index
|
||||
if (!source.get('index')) $scope.index = val;
|
||||
});
|
||||
|
||||
$scope.$watch('index', function (val) {
|
||||
// set the index on the data source
|
||||
source.index(val);
|
||||
// clear the columns and fields, then refetch when we so a search
|
||||
$scope.columns = $scope.fields = null;
|
||||
});
|
||||
|
||||
$scope.$watch('query', function (query) {
|
||||
if (query) {
|
||||
source.query({
|
||||
query_string: {
|
||||
query: query
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// clear the query
|
||||
source.query(null);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('size', function (selectedSize) {
|
||||
source.size(selectedSize.val);
|
||||
});
|
||||
|
||||
$scope.reset = function () {
|
||||
// the check happens only when the results come in; prevents a race condition
|
||||
// if (!$scope.fields) getFields();
|
||||
courier.abort();
|
||||
courier.fetch();
|
||||
};
|
||||
|
||||
function getFields() {
|
||||
source.getFields(function (err, fields) {
|
||||
$scope.fields = fields;
|
||||
$scope.columns = _.keys(fields);
|
||||
source.source({
|
||||
include: $scope.columns
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
});
|
0
src/kibana/apps/discover/styles/main.html
Normal file
0
src/kibana/apps/discover/styles/main.html
Normal file
0
src/kibana/apps/visualize/styles/main.html
Normal file
0
src/kibana/apps/visualize/styles/main.html
Normal file
51
src/kibana/directives/table.js
Normal file
51
src/kibana/directives/table.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
define(function (require) {
|
||||
var html = require('text!partials/table.html');
|
||||
var angular = require('angular');
|
||||
var _ = require('lodash');
|
||||
|
||||
var module = angular.module('kibana/directives');
|
||||
|
||||
/**
|
||||
* kbnTable directive
|
||||
*
|
||||
* displays results in a simple table view. Pass the result object
|
||||
* via the results attribute on the kbnTable element:
|
||||
* ```
|
||||
* <kbn-table results="queryResult"></kbn-table>
|
||||
* ```
|
||||
*/
|
||||
|
||||
var defaults = {
|
||||
columns: [],
|
||||
rows: []
|
||||
};
|
||||
|
||||
module.directive('kbnTable', function () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: html,
|
||||
scope: {
|
||||
columns: '=',
|
||||
rows: '='
|
||||
},
|
||||
controller: function ($scope) {
|
||||
_.defaults($scope, defaults);
|
||||
|
||||
$scope.makeRowHtml = function (row) {
|
||||
var html = '<tr>';
|
||||
_.each($scope.columns, function (col) {
|
||||
html += '<td>';
|
||||
if (row[col] !== void 0) {
|
||||
html += row[col];
|
||||
} else {
|
||||
html += row._source[col];
|
||||
}
|
||||
html += '</td>';
|
||||
});
|
||||
html += '</tr>';
|
||||
return html;
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -77,7 +77,7 @@ define(function (require) {
|
|||
// require global modules
|
||||
require([
|
||||
'controllers/kibana',
|
||||
'directives/kbn_view',
|
||||
'directives/view',
|
||||
'constants/base'
|
||||
], loaded());
|
||||
|
||||
|
|
12
src/kibana/partials/table.html
Normal file
12
src/kibana/partials/table.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<table class="table">
|
||||
<thead>
|
||||
<th ng-repeat="col in columns">{{col}}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="row in rows">
|
||||
<td ng-repeat="col in columns">
|
||||
{{row._source[col] || row[col]}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
|
@ -7,6 +7,7 @@ require.config({
|
|||
'angular-route': '../bower_components/angular-route/angular-route',
|
||||
async: '../bower_components/async/lib/async',
|
||||
css: '../bower_components/require-css/css',
|
||||
text: '../bower_components/requirejs-text/text',
|
||||
d3: '../bower_components/d3/d3',
|
||||
elasticsearch: '../bower_components/elasticsearch/elasticsearch.angular',
|
||||
jquery: '../bower_components/jquery/jquery',
|
||||
|
|
55
src/kibana/styles/_bootstrap.less
Normal file
55
src/kibana/styles/_bootstrap.less
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Core variables and mixins
|
||||
@import "../../bower_components/bootstrap/less/variables.less";
|
||||
|
||||
@icon-font-path: "../../bower_components/bootstrap/fonts/";
|
||||
|
||||
@import "../../bower_components/bootstrap/less/mixins.less";
|
||||
|
||||
// Reset
|
||||
@import "../../bower_components/bootstrap/less/normalize.less";
|
||||
@import "../../bower_components/bootstrap/less/print.less";
|
||||
|
||||
// Core CSS
|
||||
@import "../../bower_components/bootstrap/less/scaffolding.less";
|
||||
@import "../../bower_components/bootstrap/less/type.less";
|
||||
@import "../../bower_components/bootstrap/less/code.less";
|
||||
@import "../../bower_components/bootstrap/less/grid.less";
|
||||
@import "../../bower_components/bootstrap/less/tables.less";
|
||||
@import "../../bower_components/bootstrap/less/forms.less";
|
||||
@import "../../bower_components/bootstrap/less/buttons.less";
|
||||
|
||||
// Components
|
||||
@import "../../bower_components/bootstrap/less/component-animations.less";
|
||||
@import "../../bower_components/bootstrap/less/glyphicons.less";
|
||||
@import "../../bower_components/bootstrap/less/dropdowns.less";
|
||||
@import "../../bower_components/bootstrap/less/button-groups.less";
|
||||
@import "../../bower_components/bootstrap/less/input-groups.less";
|
||||
@import "../../bower_components/bootstrap/less/navs.less";
|
||||
@import "../../bower_components/bootstrap/less/navbar.less";
|
||||
@import "../../bower_components/bootstrap/less/breadcrumbs.less";
|
||||
@import "../../bower_components/bootstrap/less/pagination.less";
|
||||
@import "../../bower_components/bootstrap/less/pager.less";
|
||||
@import "../../bower_components/bootstrap/less/labels.less";
|
||||
@import "../../bower_components/bootstrap/less/badges.less";
|
||||
@import "../../bower_components/bootstrap/less/jumbotron.less";
|
||||
@import "../../bower_components/bootstrap/less/thumbnails.less";
|
||||
@import "../../bower_components/bootstrap/less/alerts.less";
|
||||
@import "../../bower_components/bootstrap/less/progress-bars.less";
|
||||
@import "../../bower_components/bootstrap/less/media.less";
|
||||
@import "../../bower_components/bootstrap/less/list-group.less";
|
||||
@import "../../bower_components/bootstrap/less/panels.less";
|
||||
@import "../../bower_components/bootstrap/less/wells.less";
|
||||
@import "../../bower_components/bootstrap/less/close.less";
|
||||
|
||||
// Components w/ JavaScript
|
||||
@import "../../bower_components/bootstrap/less/modals.less";
|
||||
@import "../../bower_components/bootstrap/less/tooltip.less";
|
||||
@import "../../bower_components/bootstrap/less/popovers.less";
|
||||
@import "../../bower_components/bootstrap/less/carousel.less";
|
||||
|
||||
// Utility classes
|
||||
@import "../../bower_components/bootstrap/less/utilities.less";
|
||||
@import "../../bower_components/bootstrap/less/responsive-utilities.less";
|
||||
|
||||
// automatically include the theme file
|
||||
@import "../../bower_components/bootstrap/less/theme.less";
|
|
@ -2367,8 +2367,8 @@ input[type="button"].btn-block {
|
|||
}
|
||||
@font-face {
|
||||
font-family: 'Glyphicons Halflings';
|
||||
src: url('../fonts/glyphicons-halflings-regular.eot');
|
||||
src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
|
||||
src: url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot');
|
||||
src: url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'), url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
|
||||
}
|
||||
.glyphicon {
|
||||
position: relative;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@import "../../bower_components/bootstrap/less/bootstrap.less";
|
||||
@import "../../bower_components/bootstrap/less/theme.less";
|
||||
@import "./_bootstrap.less";
|
||||
|
||||
body {
|
||||
margin: 60px 10px;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ module.exports = {
|
|||
src: [
|
||||
'<%= app %>/styles/**/*.less',
|
||||
'<%= app %>/apps/**/*.less',
|
||||
'!_*.less'
|
||||
'!<%= src %>/**/_*.less'
|
||||
],
|
||||
expand: true,
|
||||
ext: '.css',
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
require(["/specs/calculateIndices.js","/specs/courier.js","/specs/data_source.js","/specs/mapper.js"], function () {
|
||||
require(["/specs/calculate_indices.js","/specs/courier.js","/specs/data_source.js","/specs/mapper.js"], function () {
|
||||
window.mochaRunner = mocha.run().on('end', function () {
|
||||
window.mochaResults = this.stats;
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue