Initial commit
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
const CoreView = require('backbone/core-view');
|
||||
const randomQuote = require('builder/components/loading/random-quote');
|
||||
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
|
||||
const REQUIRED_OPTS = [
|
||||
'collection',
|
||||
'model',
|
||||
'template'
|
||||
];
|
||||
/*
|
||||
* Content result default view
|
||||
*/
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
initialize: function (options) {
|
||||
checkAndBuildOpts(options, REQUIRED_OPTS, this);
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(this._template({
|
||||
defaultUrl: '',
|
||||
page: this._collection.options.get('page'),
|
||||
isSearching: this._model.get('is_searching'),
|
||||
tag: this._collection.options.get('tags'),
|
||||
q: this._collection.options.get('q'),
|
||||
quote: randomQuote(),
|
||||
type: this._collection.options.get('type'),
|
||||
totalItems: this._collection.size(),
|
||||
totalEntries: this._collection.total_entries,
|
||||
msg: ''
|
||||
}));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._collection, 'change remove add reset', this.render);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
<div class="IntermediateInfo">
|
||||
<div class="LayoutIcon LayoutIcon--negative">
|
||||
<i class="CDB-IconFont CDB-IconFont-cockroach"></i>
|
||||
</div>
|
||||
<% if (msg) { %>
|
||||
<p class="CDB-Text CDB-Size-medium u-altTextColor u-tSpace-xl"><%= msg %></p>
|
||||
<% } %>
|
||||
<h4 class="CDB-Text CDB-Size-large u-mainTextColor u-secondaryTextColor u-bSpace--m u-tSpace-xl">Oouch! There has been an error</h4>
|
||||
<p class="CDB-Text CDB-Size-medium u-altTextColor">If the problem persists contact us at <a class="js-mail-link" href="mailto:support@carto.com">support@carto.com</a>.</p>
|
||||
</div>
|
||||
@@ -0,0 +1,80 @@
|
||||
const _ = require('underscore');
|
||||
const moment = require('moment');
|
||||
const CoreView = require('backbone/core-view');
|
||||
const Utils = require('builder/helpers/utils');
|
||||
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
const MapCardPreview = require('dashboard/components/mapcard-preview-view');
|
||||
const template = require('./dataset-item.tpl');
|
||||
|
||||
const GEOM_TYPES = ['point', 'polygon', 'line', 'raster'];
|
||||
|
||||
const REQUIRED_OPTS = [
|
||||
'configModel'
|
||||
];
|
||||
|
||||
/**
|
||||
* View representing an item in the list under datasets route.
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
tagName: 'li',
|
||||
className: 'MapsList-item',
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
const vis = this.model;
|
||||
const date = vis.get('order') === 'updated_at' ? vis.get('updated_at') : vis.get('created_at');
|
||||
|
||||
this.$el.html(template({
|
||||
vis: vis.attributes,
|
||||
datasetSize: this._getDatasetSize(vis.get('table')['size']),
|
||||
geomType: this._getGeometryType(vis.get('table')['geometry_types']),
|
||||
account_host: this._configModel.get('account_host'),
|
||||
dataset_base_url: this._configModel.get('dataset_base_url'),
|
||||
dateFromNow: moment(date).fromNow()
|
||||
}));
|
||||
|
||||
this._renderMapThumbnail();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_renderMapThumbnail: function () {
|
||||
const username = this.model.get('permission')['owner']['username'];
|
||||
const mapCardPreview = new MapCardPreview({
|
||||
el: this.$('.js-header'),
|
||||
username: username,
|
||||
width: 298,
|
||||
height: 220,
|
||||
visId: this.model.get('id'),
|
||||
mapsApiResource: this._configModel.getMapsResourceName(username),
|
||||
config: this._configModel
|
||||
});
|
||||
|
||||
if (this.imageURL) {
|
||||
mapCardPreview.loadURL(this.imageURL);
|
||||
} else {
|
||||
mapCardPreview.load();
|
||||
}
|
||||
|
||||
mapCardPreview.bind('loaded', function (url) {
|
||||
this.imageURL = url;
|
||||
}, this);
|
||||
|
||||
this.addView(mapCardPreview);
|
||||
},
|
||||
|
||||
_getGeometryType: function (geomTypes) {
|
||||
const geomType = (geomTypes && geomTypes[0] || '').toLowerCase();
|
||||
|
||||
return _.find(GEOM_TYPES, type => geomType.indexOf(type) !== -1);
|
||||
},
|
||||
|
||||
_getDatasetSize: function (size) {
|
||||
return size ? Utils.readablizeBytes(size, true).split(' ') : 0;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
<div class="MapCard MapCard--borderless MapCard--squared js-card" data-vis-id="<%- vis.id %>" data-username="<%- vis.permission.owner.username %>">
|
||||
<a href="<%- dataset_base_url %><%- vis.name %>" target="_blank" class="MapCard-header js-header">
|
||||
<div class="MapCard-loader js-loader"></div>
|
||||
</a>
|
||||
|
||||
<div class="MapCard-content">
|
||||
<div class="MapCard-contentFooter MapCard-contentFooter--with-icon">
|
||||
<div class="MapCard-contentFooterIcon">
|
||||
<div class="DatasetsList-itemCategory is--<%= geomType %>Dataset"></div>
|
||||
</div>
|
||||
<div class="MapCard-contentFooterDetails u-ellipsLongText">
|
||||
<div class="MapCard-contentFooterTitle">
|
||||
<h3 class="MapCard-title DefaultTitle CDB-Text is-semibold CDB-Size-large">
|
||||
<a href="<%- dataset_base_url %><%- vis.name %>" target="_blank" class="DefaultTitle-link u-ellipsLongText" title="<%- vis.display_name %>">
|
||||
<% if (vis.display_name) { %>
|
||||
<%- vis.display_name %>
|
||||
<% } else { %>
|
||||
<%- vis.name %>
|
||||
<% } %>
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="MapCard-contentFooterIcons CDB-Size-medium u-altTextColor">
|
||||
<div class="MapCard-contentFooterDetails--left MapCard-contentFooterDetails--noright">
|
||||
<div class="MapCard-contentFooterTimeDiff DefaultTimeDiff">
|
||||
<i class="CDB-IconFont CDB-IconFont-clock DefaultTimeDiff-icon"></i>
|
||||
<%- dateFromNow %>
|
||||
</div>
|
||||
<% if (datasetSize && datasetSize[0] > 0) { %>
|
||||
<div class="MapCard-contentFooterIcon u-hideOnMobile">
|
||||
<i class="CDB-IconFont CDB-IconFont-floppy SizeIndicator-icon"></i>
|
||||
<span class="MapCardIcon-counter"><%- datasetSize[0] %></span> <span class="MapCardIcon-label"><%- datasetSize[1] %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,82 @@
|
||||
const CoreView = require('backbone/core-view');
|
||||
const _ = require('underscore');
|
||||
const DatasetsItemView = require('./dataset-item-view');
|
||||
const PlaceholderItem = require('./placeholder-item-view');
|
||||
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
|
||||
const REQUIRED_OPTS = [
|
||||
'configModel',
|
||||
'collection'
|
||||
];
|
||||
|
||||
const MAP_CARDS_PER_ROW = 3;
|
||||
|
||||
/**
|
||||
* View representing the list of items
|
||||
*/
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
tagName: 'ul',
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
if (this._collection.options.get('page') === 1) {
|
||||
this.clearSubViews();
|
||||
}
|
||||
|
||||
this._collection.each(this._addItem, this);
|
||||
|
||||
let className = 'MapsList';
|
||||
|
||||
if (this._collection._ITEMS_PER_PAGE * this._collection.options.get('page') >= this._collection.total_entries) {
|
||||
className += ' is-bottom';
|
||||
}
|
||||
|
||||
this.$el.attr('class', className);
|
||||
|
||||
if (this._collection.size() > 0) {
|
||||
this._fillEmptySlotsWithPlaceholderItems();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._collection, 'reset loaded', this.render);
|
||||
},
|
||||
|
||||
show: function () {
|
||||
this.$el.removeClass('is-hidden');
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.$el.addClass('is-hidden');
|
||||
},
|
||||
|
||||
_addItem: function (model) {
|
||||
const itemView = new DatasetsItemView({
|
||||
model,
|
||||
configModel: this._configModel
|
||||
});
|
||||
this.addView(itemView);
|
||||
this.$el.append(itemView.render().el);
|
||||
},
|
||||
|
||||
_fillEmptySlotsWithPlaceholderItems: function () {
|
||||
_.times(this._emptySlotsCount(), function () {
|
||||
var view = new PlaceholderItem();
|
||||
this.$el.append(view.render().el);
|
||||
this.addView(view);
|
||||
}, this);
|
||||
},
|
||||
|
||||
_emptySlotsCount: function () {
|
||||
return (this._collection._ITEMS_PER_PAGE - this._collection.size()) % MAP_CARDS_PER_ROW;
|
||||
}
|
||||
});
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<div class="MapCard MapCard--squared MapCard--borderless">
|
||||
<div class="MapCard-header MapCard-header--fake"></div>
|
||||
<div class="MapCard-content"></div>
|
||||
</div>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
const CoreView = require('backbone/core-view');
|
||||
const template = require('./placeholder-item-template.tpl');
|
||||
/**
|
||||
* Represents a map card on data library.
|
||||
*/
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
className: 'MapsList-item MapsList-item--fake',
|
||||
|
||||
tagName: 'li',
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
this.$el.html(template());
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
<div class="IntermediateInfo">
|
||||
<div class="Spinner"></div>
|
||||
<h4 class="CDB-Text CDB-Size-large u-mainTextColor u-secondaryTextColor u-bSpace--m"><%- q || tag ? 'Searching' : 'Loading' %>...</h4>
|
||||
<div class="CDB-Text CDB-Size-medium u-altTextColor"><%= quote %></div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="u-inner u-txt-center">
|
||||
<button class="Button Button--gray Button--centered is-hidden js-more DataLibrary-more">View more</button>
|
||||
</div>
|
||||
@@ -0,0 +1,11 @@
|
||||
<div class="IntermediateInfo">
|
||||
<div class="LayoutIcon">
|
||||
<i class="CDB-IconFont CDB-IconFont-lens" />
|
||||
</div>
|
||||
<h4 class="CDB-Text CDB-Size-large u-mainTextColor u-secondaryTextColor u-bSpace--m">
|
||||
Oh! No results
|
||||
</h4>
|
||||
<p class="CDB-Text CDB-Size-medium u-altTextColor">
|
||||
Your search was correct but returned no results, please try with a different set of parameters before running it again
|
||||
</p>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<div class="IntermediateInfo">
|
||||
<div class="LayoutIcon LayoutIcon--negative">
|
||||
<i class="CDB-IconFont CDB-IconFont-info"></i>
|
||||
</div>
|
||||
<% if (msg) { %>
|
||||
<h4 class="CDB-Text CDB-Size-large u-mainTextColor u-secondaryTextColor u-bSpace--m u-tSpace-xl"><%= msg %></h4>
|
||||
<% } else { %>
|
||||
<h4 class="CDB-Text CDB-Size-large u-mainTextColor u-secondaryTextColor u-bSpace--m u-tSpace-xl">Oouch! There has been an error</h4>
|
||||
<% } %>
|
||||
<p class="CDB-Text CDB-Size-medium u-altTextColor">If the problem persists contact us at <a class="js-mail-link" href="mailto:support@carto.com">support@carto.com</a>.</p>
|
||||
</div>
|
||||
@@ -0,0 +1,271 @@
|
||||
const $ = require('jquery');
|
||||
const _ = require('underscore');
|
||||
const Backbone = require('backbone');
|
||||
const CoreView = require('backbone/core-view');
|
||||
const FiltersView = require('dashboard/views/data-library/filters/filters-view');
|
||||
const ListView = require('dashboard/views/data-library/content/list/list-view');
|
||||
const ContentView = require('dashboard/views/data-library/content/content-view');
|
||||
const DatasetsCollection = require('dashboard/data/datasets-collection');
|
||||
const DataLibraryHeaderView = require('dashboard/views/data-library/header/header-view');
|
||||
const moreTemplate = require('dashboard/views/data-library/content/more-template.tpl');
|
||||
const noResultsTemplate = require('dashboard/views/data-library/content/no-results-template.tpl');
|
||||
const errorTemplate = require('dashboard/views/data-library/content/error-template.tpl');
|
||||
const loaderTemplate = require('dashboard/views/data-library/content/loader-template.tpl');
|
||||
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
|
||||
const REQUIRED_OPTS = [
|
||||
'configModel'
|
||||
];
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
events: {
|
||||
'click .js-more': '_onClickMore'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
|
||||
this._initModels();
|
||||
this._initViews();
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this._fetchCollection();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initModels: function () {
|
||||
this.model = new Backbone.Model({
|
||||
vis_count: 0,
|
||||
show_countries: false,
|
||||
is_searching: false
|
||||
});
|
||||
|
||||
this.collection = new DatasetsCollection(null, { configModel: this._configModel });
|
||||
|
||||
this._resetOptions();
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
this.controlledViews = {}; // All available views
|
||||
this.enabledViews = []; // Visible views
|
||||
|
||||
const dataLibraryHeader = new DataLibraryHeaderView({
|
||||
model: this.model,
|
||||
collection: this.collection,
|
||||
configModel: this._configModel
|
||||
});
|
||||
$('.js-Header--datalibrary').append(dataLibraryHeader.render().el);
|
||||
this.addView(dataLibraryHeader);
|
||||
dataLibraryHeader.load();
|
||||
|
||||
const filtersView = new FiltersView({
|
||||
collection: this.collection,
|
||||
model: this.model
|
||||
});
|
||||
$('.Filters').append(filtersView.render().el);
|
||||
this.addView(filtersView);
|
||||
|
||||
const moreView = new ContentView({
|
||||
model: this.model,
|
||||
collection: this.collection,
|
||||
template: moreTemplate
|
||||
});
|
||||
this.$el.append(moreView.render().el);
|
||||
this.addView(moreView);
|
||||
|
||||
const listView = new ListView({
|
||||
collection: this.collection,
|
||||
configModel: this._configModel
|
||||
});
|
||||
$('.js-DataLibrary-content').append(listView.render().el);
|
||||
this.addView(listView);
|
||||
this.controlledViews['list'] = listView;
|
||||
|
||||
const noResultsView = new ContentView({
|
||||
model: this.model,
|
||||
collection: this.collection,
|
||||
template: noResultsTemplate
|
||||
});
|
||||
this.$el.append(noResultsView.render().el);
|
||||
this.addView(noResultsView);
|
||||
this.controlledViews['no_results'] = noResultsView;
|
||||
|
||||
const errorView = new ContentView({
|
||||
model: this.model,
|
||||
collection: this.collection,
|
||||
template: errorTemplate
|
||||
});
|
||||
this.$el.append(errorView.render().el);
|
||||
this.addView(errorView);
|
||||
this.controlledViews['error'] = errorView;
|
||||
|
||||
const mainLoaderView = new ContentView({
|
||||
model: this.model,
|
||||
collection: this.collection,
|
||||
template: loaderTemplate
|
||||
});
|
||||
this.$el.append(mainLoaderView.render().el);
|
||||
this.addView(mainLoaderView);
|
||||
this.controlledViews['main_loader'] = mainLoaderView;
|
||||
},
|
||||
|
||||
_fetchCollection: function () {
|
||||
this.collection.fetch();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.model.bind('change:show_more', this._onChangeShowMore, this);
|
||||
this.model.bind('change:vis_count', this._onChangeVisCount, this);
|
||||
|
||||
this.listenTo(this.collection.options, 'change:tags', this._resetVisCount);
|
||||
this.listenTo(this.collection.options, 'change:bbox', this._resetVisCount);
|
||||
this.listenTo(this.collection.options, 'change', this._onCollectionOptionsChange);
|
||||
|
||||
this.listenTo(this.collection, 'reset loaded', this._onCollectionReset);
|
||||
this.listenTo(this.collection, 'loading', this._onCollectionLoading);
|
||||
this.listenTo(this.collection, 'error', this._onCollectionError);
|
||||
},
|
||||
|
||||
_resetVisCount: function () {
|
||||
this.model.set({ vis_count: 0 });
|
||||
},
|
||||
|
||||
_onCollectionOptionsChange: function () {
|
||||
this.model.set({ show_more: false });
|
||||
this._fetchCollection();
|
||||
},
|
||||
|
||||
_onCollectionError: function (collection, event, opts) {
|
||||
if (!event || (event && event.statusText !== 'abort')) {
|
||||
this._onDataError(event);
|
||||
}
|
||||
},
|
||||
|
||||
_onCollectionLoading: function () {
|
||||
if (this.collection.options.get('page') === 1) {
|
||||
this._showLoader();
|
||||
} else {
|
||||
this._showLoaderOnly();
|
||||
}
|
||||
},
|
||||
|
||||
_onCollectionReset: function () {
|
||||
this._onDataFetched();
|
||||
},
|
||||
|
||||
_onChangeVisCount: function () {
|
||||
if (this.model.get('vis_count') >= this.collection.total_entries) {
|
||||
this.model.set({ show_more: false });
|
||||
} else {
|
||||
this.model.set({ show_more: true });
|
||||
}
|
||||
},
|
||||
|
||||
_onChangeShowMore: function () {
|
||||
this.$('.js-more').toggleClass('is-hidden', !this.model.get('show_more'));
|
||||
},
|
||||
|
||||
_onDataFetched: function () {
|
||||
const activeViews = [];
|
||||
|
||||
if (this.collection.size() === 0) {
|
||||
activeViews.push('no_results');
|
||||
} else {
|
||||
this.model.set({
|
||||
vis_count: this.model.get('vis_count') + this.collection.length,
|
||||
show_more: true
|
||||
});
|
||||
activeViews.push('list');
|
||||
}
|
||||
|
||||
this._hideBlocks();
|
||||
this._showBlocks(activeViews);
|
||||
},
|
||||
|
||||
_onDataError: function (error) {
|
||||
if (window.trackJs && window.trackJs.track) {
|
||||
window.trackJs.track(error);
|
||||
}
|
||||
|
||||
this._hideBlocks();
|
||||
this._showBlocks(['error']);
|
||||
},
|
||||
|
||||
_showBlocks: function (views) {
|
||||
if (views) {
|
||||
_.each(views, (view) => {
|
||||
this.controlledViews[view].show();
|
||||
this.enabledViews.push(view);
|
||||
});
|
||||
} else {
|
||||
this.enabledViews = [];
|
||||
|
||||
_.each(this.controlledViews, (view) => {
|
||||
view.show();
|
||||
this.enabledViews.push(view);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_hideBlocks: function (views) {
|
||||
if (views) {
|
||||
_.each(views, (view) => {
|
||||
this.controlledViews[view].hide();
|
||||
this.enabledViews = _.without(this.enabledViews, view);
|
||||
});
|
||||
} else {
|
||||
_.each(this.controlledViews, (view) => {
|
||||
view.hide();
|
||||
});
|
||||
|
||||
this.enabledViews = [];
|
||||
}
|
||||
},
|
||||
|
||||
_isBlockEnabled: function (name) {
|
||||
if (name) {
|
||||
return _.contains(this.enabledViews, name);
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_showLoader: function () {
|
||||
this._hideBlocks();
|
||||
this._showBlocks(['main_loader']);
|
||||
},
|
||||
|
||||
_showLoaderOnly: function () {
|
||||
this._showBlocks(['main_loader']);
|
||||
},
|
||||
|
||||
_hideLoader: function () {
|
||||
this._hideBlocks(['main_loader']);
|
||||
},
|
||||
|
||||
_resetOptions: function () {
|
||||
this.collection.options.set({
|
||||
q: '',
|
||||
order: 'updated_at',
|
||||
page: 1,
|
||||
tags: '',
|
||||
bbox: '',
|
||||
source: [],
|
||||
type: 'table'
|
||||
});
|
||||
},
|
||||
|
||||
_onClickMore: function (event) {
|
||||
this.killEvent(event);
|
||||
|
||||
this.model.set({ show_more: false });
|
||||
|
||||
this.collection.options.set({
|
||||
page: this.collection.options.get('page') + 1
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
const $ = require('jquery');
|
||||
const DropdownAdminView = require('dashboard/components/dropdown/dropdown-admin-view');
|
||||
const template = require('./dropdown.tpl');
|
||||
|
||||
/**
|
||||
* The content of the dropdown menu opened by the user in the data-library filters, e.g.:
|
||||
* Category ▼
|
||||
* ______/\____
|
||||
* | |
|
||||
* | this |
|
||||
* |____________|
|
||||
*/
|
||||
module.exports = DropdownAdminView.extend({
|
||||
className: 'CDB-Text Dropdown Dropdown--public',
|
||||
|
||||
events: {
|
||||
'click .js-all': '_onClickAll',
|
||||
'click .js-categoryLink': '_onClickLink'
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(template());
|
||||
|
||||
// TODO: taken from existing code, how should dropdowns really be added to the DOM?
|
||||
$('body').append(this.el);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_onClickAll: function (event) {
|
||||
this.collection.options.set({
|
||||
tags: '',
|
||||
page: 1
|
||||
});
|
||||
|
||||
this.hide();
|
||||
},
|
||||
|
||||
_onClickLink: function (event) {
|
||||
var tag = $(event.target).text();
|
||||
|
||||
this.collection.options.set({
|
||||
tags: tag,
|
||||
page: 1
|
||||
});
|
||||
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
<ul class="SettingsDropdown CDB-Size-medium">
|
||||
<li class="SettingsDropdown-item SettingsDropdown-item--public">
|
||||
<p><button class="SettingsDropdown-itemLink SettingsDropdown-itemLink--public js-all">All categories</button></p>
|
||||
<p><button class="SettingsDropdown-itemLink SettingsDropdown-itemLink--public js-categoryLink">Administrative regions</button></p>
|
||||
<p><button class="SettingsDropdown-itemLink SettingsDropdown-itemLink--public js-categoryLink">Cultural datasets</button></p>
|
||||
<p><button class="SettingsDropdown-itemLink SettingsDropdown-itemLink--public js-categoryLink">Physical datasets</button></p>
|
||||
<p><button class="SettingsDropdown-itemLink SettingsDropdown-itemLink--public js-categoryLink">Historic</button></p>
|
||||
<p><button class="SettingsDropdown-itemLink SettingsDropdown-itemLink--public js-categoryLink">Building footprints</button></p>
|
||||
<p><button class="SettingsDropdown-itemLink SettingsDropdown-itemLink--public js-categoryLink">US Census</button></p>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -0,0 +1,113 @@
|
||||
const $ = require('jquery');
|
||||
const CoreView = require('backbone/core-view');
|
||||
const DropdownView = require('./dropdown/dropdown-view');
|
||||
const Utils = require('builder/helpers/utils');
|
||||
const template = require('./filters.tpl');
|
||||
|
||||
const ESC_KEY = 27;
|
||||
|
||||
/**
|
||||
* Dashboard filters.
|
||||
*
|
||||
* - 'Filter by' collection.
|
||||
* - 'Search' any pattern within collection.
|
||||
*
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
events: {
|
||||
'submit .js-search-form': '_submitSearch',
|
||||
'keydown .js-search-form': '_onSearchKeyDown',
|
||||
'click .js-search-form': 'killEvent',
|
||||
'click .js-search-link': '_onSearchClick',
|
||||
'click .js-clean-search': '_onCleanSearchClick',
|
||||
'click .js-categoriesDropdown': '_createDropdown'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this._preRender();
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
_preRender: function () {
|
||||
const $uInner = $('<div>').addClass('u-inner');
|
||||
const $filtersInner = $('<div>').addClass('Filters-inner');
|
||||
|
||||
this.$el.append($uInner.append($filtersInner));
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$('.Filters-inner').html(
|
||||
template({
|
||||
tag: this.collection.options.get('tags'),
|
||||
q: this.collection.options.get('q')
|
||||
})
|
||||
);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this.collection, 'add remove change reset', this.render);
|
||||
this.listenTo(this.collection.options, 'change:tags', this.render);
|
||||
},
|
||||
|
||||
_createDropdown: function (event) {
|
||||
this._setupDropdown(new DropdownView({
|
||||
target: $(event.target).closest('.js-categoriesDropdown'),
|
||||
tick: 'right',
|
||||
collection: this.collection
|
||||
}));
|
||||
},
|
||||
|
||||
_setupDropdown: function (dropdownView) {
|
||||
this.addView(dropdownView);
|
||||
|
||||
dropdownView.render();
|
||||
dropdownView.open();
|
||||
},
|
||||
|
||||
_onSearchClick: function (event) {
|
||||
this.killEvent(event);
|
||||
|
||||
this.$('.js-search-input').val('');
|
||||
this.$('.js-search-input').focus();
|
||||
},
|
||||
|
||||
_onSearchKeyDown: function (event) {
|
||||
if (event.code === ESC_KEY) {
|
||||
this._onSearchClick(event);
|
||||
}
|
||||
},
|
||||
|
||||
// Filter actions
|
||||
|
||||
_onCleanSearchClick: function (event) {
|
||||
this.killEvent(event);
|
||||
this._cleanSearch();
|
||||
},
|
||||
|
||||
_submitSearch: function (event) {
|
||||
this.killEvent(event);
|
||||
|
||||
this.model.set('is_searching', true);
|
||||
|
||||
this.collection.options.set({
|
||||
q: Utils.stripHTML(this.$('.js-search-input').val().trim(), ''),
|
||||
page: 1
|
||||
});
|
||||
|
||||
this.render();
|
||||
},
|
||||
|
||||
_cleanSearch: function () {
|
||||
this.model.set('is_searching', false);
|
||||
|
||||
this.collection.options.set({
|
||||
q: '',
|
||||
page: 1
|
||||
});
|
||||
|
||||
this.render();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
<span class="Filters-separator"></span>
|
||||
|
||||
<div class="Filters-row">
|
||||
<div class="Filters-group <% if (q) { %>is-searching<% } %>">
|
||||
<div class="Filters-typeItem Filters-typeItem--searchEnabler js-search-enabler">
|
||||
<a href="#/search" class="Filters-searchLink CDB-Text CDB-Size-medium u-actionTextColor u-flex u-upperCase is-semibold js-search-link">
|
||||
<div class="CDB-Shape u-rSpace">
|
||||
<div class="CDB-Shape-magnify is-small is-blue"></div>
|
||||
</div>
|
||||
Search
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="Filters-typeItem Filters-typeItem--searchField js-search-field">
|
||||
<form class="Filters-searchForm js-search-form" action="#">
|
||||
<input class="Filters-searchInput CDB-Text CDB-Size-medium js-search-input" type="text" value="<%- q %>" placeholder="by name" />
|
||||
<% if (q) { %>
|
||||
<div class="CDB-Shape js-clean-search">
|
||||
<div class="CDB-Shape-close is-blue is-large"></div>
|
||||
</div>
|
||||
<% } %>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="Filters-group">
|
||||
<li class="Filters-typeItem <% if (q) { %>is-searching<% } %>">
|
||||
<a class="Filters-typeLink CDB-Text CDB-Size-medium is-semibold u-upperCase js-categoriesDropdown" href="#/category">
|
||||
<%- tag == '' ? 'Category' : tag %>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -0,0 +1,53 @@
|
||||
const CoreView = require('backbone/core-view');
|
||||
const $ = require('jquery');
|
||||
const _ = require('underscore');
|
||||
const L = require('leaflet');
|
||||
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
const template = require('./header.tpl');
|
||||
|
||||
const REQUIRED_OPTS = [
|
||||
'configModel'
|
||||
];
|
||||
|
||||
/**
|
||||
* The header map in the data-library page, where the user can filter by country, e.g.:
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
className: 'DataLibrary-header',
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
_.bindAll(this, '_addGeojsonData');
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(template());
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
load: function () {
|
||||
this.map = L.map(this.$('#DataLibraryMap')[0], {
|
||||
zoomControl: false,
|
||||
attributionControl: false
|
||||
}).setView([44, -31], 3);
|
||||
|
||||
var sqlDomain = this._configModel.get('sql_api_template').replace('{user}', this._configModel.get('common_data_user'));
|
||||
var geojsonURL = sqlDomain + '/api/v2/sql?q=' + encodeURIComponent('select * from world_borders') + '&format=geojson&filename=world_borders';
|
||||
|
||||
$.getJSON(geojsonURL).done(this._addGeojsonData);
|
||||
},
|
||||
|
||||
_addGeojsonData: function (geojsonData) {
|
||||
var style = {
|
||||
color: '#2E3C43',
|
||||
weight: 1,
|
||||
opacity: 1,
|
||||
fillColor: '#242D32',
|
||||
fillOpacity: 1
|
||||
};
|
||||
|
||||
this.layer = L.geoJson(geojsonData, { style: style }).addTo(this.map);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
<div class="DataLibrary-gradient"></div>
|
||||
|
||||
<div class="Header-inner Header-title js-Header-title u-inner">
|
||||
<div class="Header-innerTitle">
|
||||
<h1 class="Title-small">Data library</h1>
|
||||
<p class="Title Title--l Title--white u-vspace-l">Open resources to help you populate your maps</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="Header-inner Header-footer is-hidden">
|
||||
<div class="CountrySelector js-CountrySelector u-inner">
|
||||
<p class="CountrySelector-text">Filter datasets by country selecting it in this map</p>
|
||||
<button class="CountrySelector-button js-country"></button>
|
||||
</div>
|
||||
|
||||
<div class="CountrySelector CountrySelector-back js-CountrySelector-back is-hidden">
|
||||
<div class="CountrySelector-inner u-inner">
|
||||
<p class="CountrySelector-text">Back</p>
|
||||
<button class="NavButton Dialog-countryBack js-back">
|
||||
<i class="CDB-IconFont CDB-IconFont-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="DataLibraryMap" class="DataLibraryMap"></div>
|
||||
Reference in New Issue
Block a user