diff --git a/app/assets/javascripts/Metamaps.ServerData.js.erb b/app/assets/javascripts/Metamaps.ServerData.js.erb new file mode 100644 index 00000000..86c8d2b9 --- /dev/null +++ b/app/assets/javascripts/Metamaps.ServerData.js.erb @@ -0,0 +1,18 @@ +/* global Metamaps */ + +/* erb variables from rails */ +Metamaps.ServerData = Metamaps.ServerData || {} +Metamaps.ServerData['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>' +Metamaps.ServerData['user.png'] = '<%= asset_path('user.png') %>' +Metamaps.ServerData['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>' +Metamaps.ServerData['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>' +Metamaps.ServerData['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>' +Metamaps.ServerData['synapse16.png'] = '<%= asset_path('synapse16.png') %>' +Metamaps.ServerData['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>' +Metamaps.ServerData['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>' +Metamaps.ServerData.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %> +Metamaps.ServerData.REALTIME_SERVER = '<%= ENV['REALTIME_SERVER'] %>' +Metamaps.ServerData.RAILS_ENV = '<%= ENV['RAILS_ENV'] %>' +Metamaps.ServerData.VERSION = '<%= METAMAPS_VERSION %>' +Metamaps.ServerData.BUILD = '<%= METAMAPS_BUILD %>' +Metamaps.ServerData.LAST_UPDATED = '<%= METAMAPS_LAST_UPDATED %>' diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 051edc8b..d669012a 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,5 +14,5 @@ //= require jquery-ui //= require jquery_ujs //= require_directory ./lib -//= require ./src/Metamaps.Erb //= require ./webpacked/metamaps.bundle +//= require ./Metamaps.ServerData diff --git a/app/assets/javascripts/src/Metamaps.Erb.js.erb b/app/assets/javascripts/src/Metamaps.Erb.js.erb deleted file mode 100644 index 57f26c98..00000000 --- a/app/assets/javascripts/src/Metamaps.Erb.js.erb +++ /dev/null @@ -1,24 +0,0 @@ -/* global Metamaps */ - -/* - * Metamaps.Erb.js.erb - */ - -/* erb variables from rails */ -window.Metamaps = window.Metamaps || {} -Metamaps.Erb = {} -Metamaps.Erb['REALTIME_SERVER'] = '<%= ENV['REALTIME_SERVER'] %>' -Metamaps.Erb['RAILS_ENV'] = '<%= ENV['RAILS_ENV'] %>' -Metamaps.Erb['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>' -Metamaps.Erb['user.png'] = '<%= asset_path('user.png') %>' -Metamaps.Erb['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>' -Metamaps.Erb['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>' -Metamaps.Erb['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>' -Metamaps.Erb['synapse16.png'] = '<%= asset_path('synapse16.png') %>' -Metamaps.Erb['import-example.png'] = '<%= asset_path('import-example.png') %>' -Metamaps.Erb['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>' -Metamaps.Erb['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>' -Metamaps.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %> -Metamaps.VERSION = '<%= METAMAPS_VERSION %>' -Metamaps.BUILD = '<%= METAMAPS_BUILD %>' -Metamaps.LAST_UPDATED = '<%= METAMAPS_LAST_UPDATED %>' diff --git a/app/views/explore/active.html.erb b/app/views/explore/active.html.erb index 0ca442e5..e6e2a3a6 100644 --- a/app/views/explore/active.html.erb +++ b/app/views/explore/active.html.erb @@ -5,11 +5,11 @@ # %> diff --git a/app/views/explore/featured.html.erb b/app/views/explore/featured.html.erb index 806b2fac..9396ebdc 100644 --- a/app/views/explore/featured.html.erb +++ b/app/views/explore/featured.html.erb @@ -5,11 +5,11 @@ # %> diff --git a/app/views/explore/mapper.html.erb b/app/views/explore/mapper.html.erb index 68792f47..bf3e73c0 100644 --- a/app/views/explore/mapper.html.erb +++ b/app/views/explore/mapper.html.erb @@ -5,14 +5,14 @@ # %> diff --git a/app/views/explore/mine.html.erb b/app/views/explore/mine.html.erb index 8e39c296..21f034c3 100644 --- a/app/views/explore/mine.html.erb +++ b/app/views/explore/mine.html.erb @@ -5,11 +5,11 @@ # %> diff --git a/app/views/explore/shared.html.erb b/app/views/explore/shared.html.erb index 246498a0..0f01fcf0 100644 --- a/app/views/explore/shared.html.erb +++ b/app/views/explore/shared.html.erb @@ -5,11 +5,11 @@ # %> diff --git a/app/views/explore/starred.html.erb b/app/views/explore/starred.html.erb index 825dbf5d..125c3e76 100644 --- a/app/views/explore/starred.html.erb +++ b/app/views/explore/starred.html.erb @@ -5,11 +5,11 @@ # %> diff --git a/app/views/layouts/_foot.html.erb b/app/views/layouts/_foot.html.erb index 1f5ad1c8..e309c65f 100644 --- a/app/views/layouts/_foot.html.erb +++ b/app/views/layouts/_foot.html.erb @@ -2,28 +2,13 @@ <%= render :partial => 'layouts/templates' %> <%= render :partial => 'shared/metacodeBgColors' %> <%= render :partial => 'layouts/googleanalytics' if Rails.env.production? %> diff --git a/app/views/layouts/_templates.html.erb b/app/views/layouts/_templates.html.erb index 921a7d88..9e298b3c 100644 --- a/app/views/layouts/_templates.html.erb +++ b/app/views/layouts/_templates.html.erb @@ -4,50 +4,49 @@ #%>
- - + - + - + - + - + - - - - - - + + + + +
diff --git a/app/views/main/home.html.erb b/app/views/main/home.html.erb index d6e99b48..16870f13 100644 --- a/app/views/main/home.html.erb +++ b/app/views/main/home.html.erb @@ -33,7 +33,8 @@ + diff --git a/app/views/maps/show.html.erb b/app/views/maps/show.html.erb index 8bdbfdee..4ecbd274 100644 --- a/app/views/maps/show.html.erb +++ b/app/views/maps/show.html.erb @@ -9,13 +9,14 @@ diff --git a/app/views/shared/_switchmetacodes.html.erb b/app/views/shared/_switchmetacodes.html.erb index 24739716..4c56dd41 100644 --- a/app/views/shared/_switchmetacodes.html.erb +++ b/app/views/shared/_switchmetacodes.html.erb @@ -117,6 +117,6 @@
diff --git a/app/views/topics/show.html.erb b/app/views/topics/show.html.erb index 02a147c4..119f2f40 100644 --- a/app/views/topics/show.html.erb +++ b/app/views/topics/show.html.erb @@ -1,27 +1,20 @@ <%# +# # @file -# This shows a topic view. It is used. -# The first commented out section used to be a card at the top showing all -# info. Now we're moving towards most screens looking the same. The -# consequence of accessing data from this view is that you can't remove -# the topic that corresponds to the page you're on. Originally, accessing this -# page showed the topic with its neighbours arrayed around. Now it shows the -# same, but there's no cues to say which topic's page you're on. So when the -# map recenters on a new topic, it's like you're on that topic's page. -# Nice, but the URL and being unable to remove the root node still hamper that -# experience. +# This shows a topic and its siblings. # URL: /topics/ # -#%> +%> <% content_for :title, @topic.name + " | Metamaps" %> <% content_for :mobile_title, @topic.name %> diff --git a/frontend/src/Metamaps/Account.js b/frontend/src/Metamaps/Account.js index 1ac87811..b7e1fe79 100644 --- a/frontend/src/Metamaps/Account.js +++ b/frontend/src/Metamaps/Account.js @@ -1,11 +1,11 @@ /* global $, CanvasLoader */ -/* - * Metamaps.Erb - */ - const Account = { + init: function (serverData) { + Account.userIconUrl = serverData['user.png'] + }, listenersInitialized: false, + userIconUrl: null, initListeners: function () { var self = Account @@ -25,24 +25,18 @@ const Account = { if (!self.listenersInitialized) self.initListeners() }, closeChangePicture: function () { - var self = Account - $('.userImageMenu').hide() }, showLoading: function () { - var self = Account - var loader = new CanvasLoader('accountPageLoading') - loader.setColor('#4FC059'); // default is '#000000' + loader.setColor('#4FC059') // default is '#000000' loader.setDiameter(28) // default is 40 loader.setDensity(41) // default is 40 - loader.setRange(0.9); // default is 1.3 + loader.setRange(0.9) // default is 1.3 loader.show() // Hidden by default $('#accountPageLoading').show() }, showImagePreview: function () { - var self = Account - var file = $('#user_image')[0].files[0] var reader = new window.FileReader() @@ -90,7 +84,7 @@ const Account = { var self = Account $('.userImageDiv canvas').remove() - $('.userImageDiv img').attr('src', window.Metamaps.Erb['user.png']).show() + $('.userImageDiv img').attr('src', self.userIconUrl).show() $('.userImageMenu').hide() var input = $('#user_image') diff --git a/frontend/src/Metamaps/Active.js b/frontend/src/Metamaps/Active.js index c61a8bb9..ddd44152 100644 --- a/frontend/src/Metamaps/Active.js +++ b/frontend/src/Metamaps/Active.js @@ -1,7 +1,7 @@ const Active = { Map: null, - Topic: null, - Mapper: null -}; + Mapper: null, + Topic: null +} export default Active diff --git a/frontend/src/Metamaps/Backbone/index.js b/frontend/src/Metamaps/Backbone/index.js deleted file mode 100644 index ff4c48b9..00000000 --- a/frontend/src/Metamaps/Backbone/index.js +++ /dev/null @@ -1,663 +0,0 @@ -/* global Metamaps, Backbone, $ */ - -import _ from 'lodash' -import Backbone from 'backbone' -Backbone.$ = window.$ - -import Active from '../Active' -import Filter from '../Filter' -import JIT from '../JIT' -import Map, { InfoBox } from '../Map' -import Mapper from '../Mapper' -import Realtime from '../Realtime' -import Synapse from '../Synapse' -import SynapseCard from '../SynapseCard' -import Topic from '../Topic' -import TopicCard from '../TopicCard' -import Visualize from '../Visualize' - -/* - * Metamaps.Backbone.js.erb - * - * Dependencies: - * - Metamaps.Collaborators - * - Metamaps.Creators - * - Metamaps.Loading - * - Metamaps.Mappers - * - Metamaps.Mappings - * - Metamaps.Metacodes - * - Metamaps.Synapses - * - Metamaps.Topics - */ - -const _Backbone = {} - -_Backbone.Map = Backbone.Model.extend({ - urlRoot: '/maps', - blacklist: ['created_at', 'updated_at', 'created_at_clean', 'updated_at_clean', 'user_name', 'contributor_count', 'topic_count', 'synapse_count', 'topics', 'synapses', 'mappings', 'mappers'], - toJSON: function (options) { - return _.omit(this.attributes, this.blacklist) - }, - save: function (key, val, options) { - var attrs - - // Handle both `"key", value` and `{key: value}` -style arguments. - if (key == null || typeof key === 'object') { - attrs = key - options = val - } else { - (attrs = {})[key] = val - } - - var newOptions = options || {} - var s = newOptions.success - - newOptions.success = function (model, response, opt) { - if (s) s(model, response, opt) - model.trigger('saved') - } - return Backbone.Model.prototype.save.call(this, attrs, newOptions) - }, - initialize: function () { - this.on('changeByOther', this.updateView) - this.on('saved', this.savedEvent) - }, - savedEvent: function () { - Realtime.updateMap(this) - }, - authorizeToEdit: function (mapper) { - if (mapper && ( - this.get('permission') === 'commons' || - (this.get('collaborator_ids') || []).includes(mapper.get('id')) || - this.get('user_id') === mapper.get('id'))) { - return true - } else { - return false - } - }, - authorizePermissionChange: function (mapper) { - if (mapper && this.get('user_id') === mapper.get('id')) { - return true - } else { - return false - } - }, - getUser: function () { - return Mapper.get(this.get('user_id')) - }, - updateView: function () { - var map = Active.Map - var isActiveMap = this.id === map.id - if (isActiveMap) { - InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission')) - this.updateMapWrapper() - // mobile menu - $('#header_content').html(this.get('name')) - document.title = this.get('name') + ' | Metamaps' - } - }, - updateMapWrapper: function () { - var map = Active.Map - var isActiveMap = this.id === map.id - var authorized = map && map.authorizeToEdit(Active.Mapper) ? 'canEditMap' : '' - var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '' - if (isActiveMap) { - $('.wrapper').removeClass('canEditMap commonsMap').addClass(authorized + ' ' + commonsMap) - } - } -}) -_Backbone.MapsCollection = Backbone.Collection.extend({ - model: _Backbone.Map, - initialize: function (models, options) { - this.id = options.id - this.sortBy = options.sortBy - - if (options.mapperId) { - this.mapperId = options.mapperId - } - - // this.page represents the NEXT page to fetch - this.page = models.length > 0 ? (models.length < 20 ? 'loadedAll' : 2) : 1 - }, - url: function () { - if (!this.mapperId) { - return '/explore/' + this.id + '.json' - } else { - return '/explore/mapper/' + this.mapperId + '.json' - } - }, - comparator: function (a, b) { - a = a.get(this.sortBy) - b = b.get(this.sortBy) - var temp - if (this.sortBy === 'name') { - a = a ? a.toLowerCase() : '' - b = b ? b.toLowerCase() : '' - } else { - // this is for updated_at and created_at - temp = a - a = b - b = temp - a = (new Date(a)).getTime() - b = (new Date(b)).getTime() - } - return a > b ? 1 : a < b ? -1 : 0 - }, - getMaps: function (cb) { - var self = this - - Metamaps.Loading.show() - - if (this.page !== 'loadedAll') { - var numBefore = this.length - this.fetch({ - remove: false, - silent: true, - data: { page: this.page }, - success: function (collection, response, options) { - // you can pass additional options to the event you trigger here as well - if (collection.length - numBefore < 20) { - self.page = 'loadedAll' - } else { - self.page += 1 - } - self.trigger('successOnFetch', cb) - }, - error: function (collection, response, options) { - // you can pass additional options to the event you trigger here as well - self.trigger('errorOnFetch') - } - }) - } else { - self.trigger('successOnFetch', cb) - } - } -}) - -_Backbone.Message = Backbone.Model.extend({ - urlRoot: '/messages', - blacklist: ['created_at', 'updated_at'], - toJSON: function (options) { - return _.omit(this.attributes, this.blacklist) - }, - prepareLiForFilter: function () { - /* var li = '' - * li += '
  • ' - * li += '' - * li += '

    ' + this.get('name') + '

  • ' - * return li - */ - } -}) -_Backbone.MessageCollection = Backbone.Collection.extend({ - model: _Backbone.Message, - url: '/messages' -}) - -_Backbone.Mapper = Backbone.Model.extend({ - urlRoot: '/users', - blacklist: ['created_at', 'updated_at'], - toJSON: function (options) { - return _.omit(this.attributes, this.blacklist) - }, - prepareLiForFilter: function () { - var li = '' - li += '
  • ' - li += '' - li += '

    ' + this.get('name') + '

  • ' - return li - } -}) - -_Backbone.MapperCollection = Backbone.Collection.extend({ - model: _Backbone.Mapper, - url: '/users' -}) - -_Backbone.init = function () { - var self = _Backbone - - self.Metacode = Backbone.Model.extend({ - initialize: function () { - var image = new Image() - image.crossOrigin = 'Anonymous' - image.src = this.get('icon') - this.set('image', image) - }, - prepareLiForFilter: function () { - var li = '' - li += '
  • ' - li += '' - li += '

    ' + this.get('name').toLowerCase() + '

  • ' - return li - } - - }) - self.MetacodeCollection = Backbone.Collection.extend({ - model: this.Metacode, - url: '/metacodes', - comparator: function (a, b) { - a = a.get('name').toLowerCase() - b = b.get('name').toLowerCase() - return a > b ? 1 : a < b ? -1 : 0 - } - }) - - self.Topic = Backbone.Model.extend({ - urlRoot: '/topics', - blacklist: ['node', 'created_at', 'updated_at', 'user_name', 'user_image', 'map_count', 'synapse_count'], - toJSON: function (options) { - return _.omit(this.attributes, this.blacklist) - }, - save: function (key, val, options) { - var attrs - - // Handle both `"key", value` and `{key: value}` -style arguments. - if (key == null || typeof key === 'object') { - attrs = key - options = val - } else { - (attrs = {})[key] = val - } - - var newOptions = options || {} - var s = newOptions.success - - var permBefore = this.get('permission') - - newOptions.success = function (model, response, opt) { - if (s) s(model, response, opt) - model.trigger('saved') - model.set('calculated_permission', model.get('permission')) - - if (permBefore === 'private' && model.get('permission') !== 'private') { - model.trigger('noLongerPrivate') - } - else if (permBefore !== 'private' && model.get('permission') === 'private') { - model.trigger('nowPrivate') - } - } - return Backbone.Model.prototype.save.call(this, attrs, newOptions) - }, - initialize: function () { - if (this.isNew()) { - this.set({ - 'user_id': Active.Mapper.id, - 'desc': this.get('desc') || '', - 'link': this.get('link') || '', - 'permission': Active.Map ? Active.Map.get('permission') : 'commons' - }) - } - - this.on('changeByOther', this.updateCardView) - this.on('change', this.updateNodeView) - this.on('saved', this.savedEvent) - this.on('nowPrivate', function () { - var removeTopicData = { - mappableid: this.id - } - - $(document).trigger(JIT.events.removeTopic, [removeTopicData]) - }) - this.on('noLongerPrivate', function () { - var newTopicData = { - mappingid: this.getMapping().id, - mappableid: this.id - } - - $(document).trigger(JIT.events.newTopic, [newTopicData]) - }) - - this.on('change:metacode_id', Filter.checkMetacodes, this) - }, - authorizeToEdit: function (mapper) { - if (mapper && - (this.get('user_id') === mapper.get('id') || - this.get('calculated_permission') === 'commons' || - this.get('collaborator_ids').includes(mapper.get('id')))) { - return true - } else { - return false - } - }, - authorizePermissionChange: function (mapper) { - if (mapper && this.get('user_id') === mapper.get('id')) return true - else return false - }, - getDate: function () {}, - getMetacode: function () { - return Metamaps.Metacodes.get(this.get('metacode_id')) - }, - getMapping: function () { - if (!Active.Map) return false - - return Metamaps.Mappings.findWhere({ - map_id: Active.Map.id, - mappable_type: 'Topic', - mappable_id: this.isNew() ? this.cid : this.id - }) - }, - createNode: function () { - var mapping - var node = { - adjacencies: [], - id: this.isNew() ? this.cid : this.id, - name: this.get('name') - } - - if (Active.Map) { - mapping = this.getMapping() - node.data = { - $mapping: null, - $mappingID: mapping.id - } - } - - return node - }, - updateNode: function () { - var mapping - var node = this.get('node') - node.setData('topic', this) - - if (Active.Map) { - mapping = this.getMapping() - node.setData('mapping', mapping) - } - - return node - }, - savedEvent: function () { - Realtime.updateTopic(this) - }, - updateViews: function () { - var onPageWithTopicCard = Active.Map || Active.Topic - var node = this.get('node') - // update topic card, if this topic is the one open there - if (onPageWithTopicCard && this == TopicCard.openTopicCard) { - TopicCard.showCard(node) - } - - // update the node on the map - if (onPageWithTopicCard && node) { - node.name = this.get('name') - Visualize.mGraph.plot() - } - }, - updateCardView: function () { - var onPageWithTopicCard = Active.Map || Active.Topic - var node = this.get('node') - // update topic card, if this topic is the one open there - if (onPageWithTopicCard && this == TopicCard.openTopicCard) { - TopicCard.showCard(node) - } - }, - updateNodeView: function () { - var onPageWithTopicCard = Active.Map || Active.Topic - var node = this.get('node') - - // update the node on the map - if (onPageWithTopicCard && node) { - node.name = this.get('name') - Visualize.mGraph.plot() - } - } - }) - - self.TopicCollection = Backbone.Collection.extend({ - model: self.Topic, - url: '/topics' - }) - - self.Synapse = Backbone.Model.extend({ - urlRoot: '/synapses', - blacklist: ['edge', 'created_at', 'updated_at'], - toJSON: function (options) { - return _.omit(this.attributes, this.blacklist) - }, - save: function (key, val, options) { - var attrs - - // Handle both `"key", value` and `{key: value}` -style arguments. - if (key == null || typeof key === 'object') { - attrs = key - options = val - } else { - (attrs = {})[key] = val - } - - var newOptions = options || {} - var s = newOptions.success - - var permBefore = this.get('permission') - - newOptions.success = function (model, response, opt) { - if (s) s(model, response, opt) - model.trigger('saved') - - if (permBefore === 'private' && model.get('permission') !== 'private') { - model.trigger('noLongerPrivate') - } - else if (permBefore !== 'private' && model.get('permission') === 'private') { - model.trigger('nowPrivate') - } - } - return Backbone.Model.prototype.save.call(this, attrs, newOptions) - }, - initialize: function () { - if (this.isNew()) { - this.set({ - 'user_id': Active.Mapper.id, - 'permission': Active.Map ? Active.Map.get('permission') : 'commons', - 'category': 'from-to' - }) - } - - this.on('changeByOther', this.updateCardView) - this.on('change', this.updateEdgeView) - this.on('saved', this.savedEvent) - this.on('noLongerPrivate', function () { - var newSynapseData = { - mappingid: this.getMapping().id, - mappableid: this.id - } - - $(document).trigger(JIT.events.newSynapse, [newSynapseData]) - }) - this.on('nowPrivate', function () { - $(document).trigger(JIT.events.removeSynapse, [{ - mappableid: this.id - }]) - }) - - this.on('change:desc', Filter.checkSynapses, this) - }, - prepareLiForFilter: function () { - var li = '' - li += '
  • ' - li += '
  • ' - return li - }, - authorizeToEdit: function (mapper) { - if (mapper && (this.get('calculated_permission') === 'commons' || this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true - else return false - }, - authorizePermissionChange: function (mapper) { - if (mapper && this.get('user_id') === mapper.get('id')) return true - else return false - }, - getTopic1: function () { - return Metamaps.Topics.get(this.get('topic1_id')) - }, - getTopic2: function () { - return Metamaps.Topics.get(this.get('topic2_id')) - }, - getDirection: function () { - var t1 = this.getTopic1(), - t2 = this.getTopic2() - - return t1 && t2 ? [ - t1.get('node').id, - t2.get('node').id - ] : false - }, - getMapping: function () { - if (!Active.Map) return false - - return Metamaps.Mappings.findWhere({ - map_id: Active.Map.id, - mappable_type: 'Synapse', - mappable_id: this.isNew() ? this.cid : this.id - }) - }, - createEdge: function (providedMapping) { - var mapping, mappingID - var synapseID = this.isNew() ? this.cid : this.id - - var edge = { - nodeFrom: this.get('topic1_id'), - nodeTo: this.get('topic2_id'), - data: { - $synapses: [], - $synapseIDs: [synapseID], - } - } - - if (Active.Map) { - mapping = providedMapping || this.getMapping() - mappingID = mapping.isNew() ? mapping.cid : mapping.id - edge.data.$mappings = [] - edge.data.$mappingIDs = [mappingID] - } - - return edge - }, - updateEdge: function () { - var mapping - var edge = this.get('edge') - edge.getData('synapses').push(this) - - if (Active.Map) { - mapping = this.getMapping() - edge.getData('mappings').push(mapping) - } - - return edge - }, - savedEvent: function () { - Realtime.updateSynapse(this) - }, - updateViews: function () { - this.updateCardView() - this.updateEdgeView() - }, - updateCardView: function () { - var onPageWithSynapseCard = Active.Map || Active.Topic - var edge = this.get('edge') - - // update synapse card, if this synapse is the one open there - if (onPageWithSynapseCard && edge == SynapseCard.openSynapseCard) { - SynapseCard.showCard(edge) - } - }, - updateEdgeView: function () { - var onPageWithSynapseCard = Active.Map || Active.Topic - var edge = this.get('edge') - - // update the edge on the map - if (onPageWithSynapseCard && edge) { - Visualize.mGraph.plot() - } - } - }) - - self.SynapseCollection = Backbone.Collection.extend({ - model: self.Synapse, - url: '/synapses' - }) - - self.Mapping = Backbone.Model.extend({ - urlRoot: '/mappings', - blacklist: ['created_at', 'updated_at'], - toJSON: function (options) { - return _.omit(this.attributes, this.blacklist) - }, - initialize: function () { - if (this.isNew()) { - this.set({ - 'user_id': Active.Mapper.id, - 'map_id': Active.Map ? Active.Map.id : null - }) - } - }, - getMap: function () { - return Map.get(this.get('map_id')) - }, - getTopic: function () { - if (this.get('mappable_type') === 'Topic') return Topic.get(this.get('mappable_id')) - else return false - }, - getSynapse: function () { - if (this.get('mappable_type') === 'Synapse') return Synapse.get(this.get('mappable_id')) - else return false - } - }) - - self.MappingCollection = Backbone.Collection.extend({ - model: self.Mapping, - url: '/mappings' - }) - - Metamaps.Metacodes = Metamaps.Metacodes ? new self.MetacodeCollection(Metamaps.Metacodes) : new self.MetacodeCollection() - - Metamaps.Topics = Metamaps.Topics ? new self.TopicCollection(Metamaps.Topics) : new self.TopicCollection() - - Metamaps.Synapses = Metamaps.Synapses ? new self.SynapseCollection(Metamaps.Synapses) : new self.SynapseCollection() - - Metamaps.Mappers = Metamaps.Mappers ? new self.MapperCollection(Metamaps.Mappers) : new self.MapperCollection() - - Metamaps.Collaborators = Metamaps.Collaborators ? new self.MapperCollection(Metamaps.Collaborators) : new self.MapperCollection() - - // this is for topic view - Metamaps.Creators = Metamaps.Creators ? new self.MapperCollection(Metamaps.Creators) : new self.MapperCollection() - - if (Active.Map) { - Metamaps.Mappings = Metamaps.Mappings ? new self.MappingCollection(Metamaps.Mappings) : new self.MappingCollection() - - Active.Map = new self.Map(Active.Map) - } - - if (Active.Topic) Active.Topic = new self.Topic(Active.Topic) - - // attach collection event listeners - self.attachCollectionEvents = function () { - Metamaps.Topics.on('add remove', function (topic) { - InfoBox.updateNumbers() - Filter.checkMetacodes() - Filter.checkMappers() - }) - - Metamaps.Synapses.on('add remove', function (synapse) { - InfoBox.updateNumbers() - Filter.checkSynapses() - Filter.checkMappers() - }) - - if (Active.Map) { - Metamaps.Mappings.on('add remove', function (mapping) { - InfoBox.updateNumbers() - Filter.checkSynapses() - Filter.checkMetacodes() - Filter.checkMappers() - }) - } - } - self.attachCollectionEvents() -}; // end _Backbone.init - -export default _Backbone diff --git a/frontend/src/Metamaps/Control.js b/frontend/src/Metamaps/Control.js index 7662f47d..8305e097 100644 --- a/frontend/src/Metamaps/Control.js +++ b/frontend/src/Metamaps/Control.js @@ -1,9 +1,10 @@ -/* global Metamaps, $ */ +/* global $ */ import _ from 'lodash' import outdent from 'outdent' import Active from './Active' +import DataModel from './DataModel' import Filter from './Filter' import GlobalUI from './GlobalUI' import JIT from './JIT' @@ -12,16 +13,6 @@ import Selected from './Selected' import Settings from './Settings' import Visualize from './Visualize' -/* - * Metamaps.Control.js - * - * Dependencies: - * - Metamaps.Mappings - * - Metamaps.Metacodes - * - Metamaps.Synapses - * - Metamaps.Topics - */ - const Control = { init: function () {}, selectNode: function (node, e) { @@ -72,7 +63,7 @@ const Control = { Control.deleteSelectedNodes() } - if (Metamaps.Topics.length === 0) { + if (DataModel.Topics.length === 0) { GlobalUI.showDiv('#instructions') } }, @@ -110,7 +101,7 @@ const Control = { var mappableid = topic.id var mapping = node.getData('mapping') topic.destroy() - Metamaps.Mappings.remove(mapping) + DataModel.Mappings.remove(mapping) $(document).trigger(JIT.events.deleteTopic, [{ mappableid: mappableid }]) @@ -127,7 +118,7 @@ const Control = { }) _.each(nodeids, function(nodeid) { if (Active.Topic.id !== nodeid) { - Metamaps.Topics.remove(nodeid) + DataModel.Topics.remove(nodeid) Control.hideNode(nodeid) } }) @@ -165,7 +156,7 @@ const Control = { var mappableid = topic.id var mapping = node.getData('mapping') mapping.destroy() - Metamaps.Topics.remove(topic) + DataModel.Topics.remove(topic) $(document).trigger(JIT.events.removeTopic, [{ mappableid: mappableid }]) @@ -293,7 +284,7 @@ const Control = { synapse.destroy() // the server will destroy the mapping, we just need to remove it here - Metamaps.Mappings.remove(mapping) + DataModel.Mappings.remove(mapping) edge.getData('mappings').splice(index, 1) edge.getData('synapses').splice(index, 1) if (edge.getData('displayIndex')) { @@ -348,7 +339,7 @@ const Control = { var mappableid = synapse.id mapping.destroy() - Metamaps.Synapses.remove(synapse) + DataModel.Synapses.remove(synapse) edge.getData('mappings').splice(index, 1) edge.getData('synapses').splice(index, 1) @@ -432,7 +423,7 @@ const Control = { GlobalUI.notifyUser('Working...') - var metacode = Metamaps.Metacodes.get(metacode_id) + var metacode = DataModel.Metacodes.get(metacode_id) // variables to keep track of how many nodes and synapses you had the ability to change the permission of var nCount = 0 diff --git a/frontend/src/Metamaps/Create.js b/frontend/src/Metamaps/Create.js index 088622e3..d12a5de5 100644 --- a/frontend/src/Metamaps/Create.js +++ b/frontend/src/Metamaps/Create.js @@ -1,5 +1,6 @@ -/* global Metamaps, $, Hogan, Bloodhound */ +/* global $, Hogan, Bloodhound */ +import DataModel from './DataModel' import Mouse from './Mouse' import Selected from './Selected' import Synapse from './Synapse' @@ -7,15 +8,6 @@ import Topic from './Topic' import Visualize from './Visualize' import GlobalUI from './GlobalUI' -/* - * Metamaps.Create.js - * - * Dependencies: - * - Metamaps.Backbone - * - Metamaps.Metacodes - * - Metamaps.Topics - */ - const Create = { isSwitchingSet: false, // indicates whether the metacode set switch lightbox is open selectedMetacodeSet: null, @@ -59,7 +51,7 @@ const Create = { } var codesToSwitchToIds - var metacodeModels = new Metamaps.Backbone.MetacodeCollection() + var metacodeModels = new DataModel.MetacodeCollection() Create.selectedMetacodeSetIndex = index Create.selectedMetacodeSet = 'metacodeset-' + set @@ -80,7 +72,7 @@ const Create = { // sort by name for (var i = 0; i < codesToSwitchToIds.length; i++) { - metacodeModels.add(Metamaps.Metacodes.get(codesToSwitchToIds[i])) + metacodeModels.add(DataModel.Metacodes.get(codesToSwitchToIds[i])) } metacodeModels.sort() @@ -243,7 +235,7 @@ const Create = { $('.pinCarousel').removeClass('isPinned') Create.newTopic.pinned = false } - if (Metamaps.Topics.length === 0) { + if (DataModel.Topics.length === 0) { GlobalUI.showDiv('#instructions') } Create.newTopic.beingCreated = false diff --git a/frontend/src/Metamaps/DataModel/Map.js b/frontend/src/Metamaps/DataModel/Map.js new file mode 100644 index 00000000..2ab98575 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/Map.js @@ -0,0 +1,92 @@ +/* global $ */ + +import _ from 'lodash' +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Active from '../Active' +import InfoBox from '../Map/InfoBox' +import Mapper from '../Mapper' +import Realtime from '../Realtime' + +import MapperCollection from './MapperCollection' +import TopicCollection from './TopicCollection' +import SynapseCollection from './SynapseCollection' +import MappingCollection from './MappingCollection' + +const Map = Backbone.Model.extend({ + urlRoot: '/maps', + blacklist: ['created_at', 'updated_at', 'created_at_clean', 'updated_at_clean', 'user_name', 'contributor_count', 'topic_count', 'synapse_count', 'topics', 'synapses', 'mappings', 'mappers'], + toJSON: function (options) { + return _.omit(this.attributes, this.blacklist) + }, + save: function (key, val, options) { + var attrs + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (key == null || typeof key === 'object') { + attrs = key + options = val + } else { + (attrs = {})[key] = val + } + + var newOptions = options || {} + var s = newOptions.success + + newOptions.success = function (model, response, opt) { + if (s) s(model, response, opt) + model.trigger('saved') + } + return Backbone.Model.prototype.save.call(this, attrs, newOptions) + }, + initialize: function () { + this.on('changeByOther', this.updateView) + this.on('saved', this.savedEvent) + }, + savedEvent: function () { + Realtime.updateMap(this) + }, + authorizeToEdit: function (mapper) { + if (mapper && ( + this.get('permission') === 'commons' || + (this.get('collaborator_ids') || []).includes(mapper.get('id')) || + this.get('user_id') === mapper.get('id'))) { + return true + } else { + return false + } + }, + authorizePermissionChange: function (mapper) { + if (mapper && this.get('user_id') === mapper.get('id')) { + return true + } else { + return false + } + }, + getUser: function () { + return Mapper.get(this.get('user_id')) + }, + updateView: function () { + var map = Active.Map + var isActiveMap = this.id === map.id + if (isActiveMap) { + InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission')) + this.updateMapWrapper() + // mobile menu + $('#header_content').html(this.get('name')) + document.title = this.get('name') + ' | Metamaps' + } + }, + updateMapWrapper: function () { + var map = Active.Map + var isActiveMap = this.id === map.id + var authorized = map && map.authorizeToEdit(Active.Mapper) ? 'canEditMap' : '' + var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '' + if (isActiveMap) { + $('.wrapper').removeClass('canEditMap commonsMap').addClass(authorized + ' ' + commonsMap) + } + } +}) + +export default Map diff --git a/frontend/src/Metamaps/DataModel/MapCollection.js b/frontend/src/Metamaps/DataModel/MapCollection.js new file mode 100644 index 00000000..22bbcf7b --- /dev/null +++ b/frontend/src/Metamaps/DataModel/MapCollection.js @@ -0,0 +1,76 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Loading from '../Loading' + +import Map from './Map' + +const MapCollection = Backbone.Collection.extend({ + model: Map, + initialize: function (models, options) { + this.id = options.id + this.sortBy = options.sortBy + + if (options.mapperId) { + this.mapperId = options.mapperId + } + + // this.page represents the NEXT page to fetch + this.page = models.length > 0 ? (models.length < 20 ? 'loadedAll' : 2) : 1 + }, + url: function () { + if (!this.mapperId) { + return '/explore/' + this.id + '.json' + } else { + return '/explore/mapper/' + this.mapperId + '.json' + } + }, + comparator: function (a, b) { + a = a.get(this.sortBy) + b = b.get(this.sortBy) + var temp + if (this.sortBy === 'name') { + a = a ? a.toLowerCase() : '' + b = b ? b.toLowerCase() : '' + } else { + // this is for updated_at and created_at + temp = a + a = b + b = temp + a = (new Date(a)).getTime() + b = (new Date(b)).getTime() + } + return a > b ? 1 : a < b ? -1 : 0 + }, + getMaps: function (cb) { + var self = this + + Loading.show() + + if (this.page !== 'loadedAll') { + var numBefore = this.length + this.fetch({ + remove: false, + silent: true, + data: { page: this.page }, + success: function (collection, response, options) { + // you can pass additional options to the event you trigger here as well + if (collection.length - numBefore < 20) { + self.page = 'loadedAll' + } else { + self.page += 1 + } + self.trigger('successOnFetch', cb) + }, + error: function (collection, response, options) { + // you can pass additional options to the event you trigger here as well + self.trigger('errorOnFetch') + } + }) + } else { + self.trigger('successOnFetch', cb) + } + } +}) + +export default MapCollection diff --git a/frontend/src/Metamaps/DataModel/Mapper.js b/frontend/src/Metamaps/DataModel/Mapper.js new file mode 100644 index 00000000..39e83503 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/Mapper.js @@ -0,0 +1,21 @@ +import _ from 'lodash' +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} +import outdent from 'outdent' + +const Mapper = Backbone.Model.extend({ + urlRoot: '/users', + blacklist: ['created_at', 'updated_at'], + toJSON: function (options) { + return _.omit(this.attributes, this.blacklist) + }, + prepareLiForFilter: function () { + return outdent` +
  • + ${this.get('name')} +

    ${this.get('name')}

    +
  • ` + } +}) + +export default Mapper diff --git a/frontend/src/Metamaps/DataModel/MapperCollection.js b/frontend/src/Metamaps/DataModel/MapperCollection.js new file mode 100644 index 00000000..836ee48f --- /dev/null +++ b/frontend/src/Metamaps/DataModel/MapperCollection.js @@ -0,0 +1,11 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Mapper from './Mapper' + +const MapperCollection = Backbone.Collection.extend({ + model: Mapper, + url: '/users' +}) + +export default MapperCollection diff --git a/frontend/src/Metamaps/DataModel/Mapping.js b/frontend/src/Metamaps/DataModel/Mapping.js new file mode 100644 index 00000000..282c419f --- /dev/null +++ b/frontend/src/Metamaps/DataModel/Mapping.js @@ -0,0 +1,37 @@ +import _ from 'lodash' +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Active from '../Active' +import Map from '../Map' +import Synapse from '../Synapse' +import Topic from '../Topic' + +const Mapping = Backbone.Model.extend({ + urlRoot: '/mappings', + blacklist: ['created_at', 'updated_at'], + toJSON: function (options) { + return _.omit(this.attributes, this.blacklist) + }, + initialize: function () { + if (this.isNew()) { + this.set({ + 'user_id': Active.Mapper.id, + 'map_id': Active.Map ? Active.Map.id : null + }) + } + }, + getMap: function () { + return Map.get(this.get('map_id')) + }, + getTopic: function () { + if (this.get('mappable_type') !== 'Topic') return false + return Topic.get(this.get('mappable_id')) + }, + getSynapse: function () { + if (this.get('mappable_type') !== 'Synapse') return false + return Synapse.get(this.get('mappable_id')) + } +}) + +export default Mapping diff --git a/frontend/src/Metamaps/DataModel/MappingCollection.js b/frontend/src/Metamaps/DataModel/MappingCollection.js new file mode 100644 index 00000000..9a69f56b --- /dev/null +++ b/frontend/src/Metamaps/DataModel/MappingCollection.js @@ -0,0 +1,11 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Mapping from './Mapping' + +const MappingCollection = Backbone.Collection.extend({ + model: Mapping, + url: '/mappings' +}) + +export default MappingCollection diff --git a/frontend/src/Metamaps/DataModel/Message.js b/frontend/src/Metamaps/DataModel/Message.js new file mode 100644 index 00000000..00f1cf4b --- /dev/null +++ b/frontend/src/Metamaps/DataModel/Message.js @@ -0,0 +1,13 @@ +import _ from 'lodash' +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +const Message = Backbone.Model.extend({ + urlRoot: '/messages', + blacklist: ['created_at', 'updated_at'], + toJSON: function (options) { + return _.omit(this.attributes, this.blacklist) + } +}) + +export default Message diff --git a/frontend/src/Metamaps/DataModel/MessageCollection.js b/frontend/src/Metamaps/DataModel/MessageCollection.js new file mode 100644 index 00000000..3ce440eb --- /dev/null +++ b/frontend/src/Metamaps/DataModel/MessageCollection.js @@ -0,0 +1,11 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Message from './Message' + +const MessageCollection = Backbone.Collection.extend({ + model: Message, + url: '/messages' +}) + +export default MessageCollection diff --git a/frontend/src/Metamaps/DataModel/Metacode.js b/frontend/src/Metamaps/DataModel/Metacode.js new file mode 100644 index 00000000..fbd13755 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/Metacode.js @@ -0,0 +1,21 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} +import outdent from 'outdent' + +const Metacode = Backbone.Model.extend({ + initialize: function () { + var image = new window.Image() + image.crossOrigin = 'Anonymous' + image.src = this.get('icon') + this.set('image', image) + }, + prepareLiForFilter: function () { + return outdent` +
  • + ${this.get('name')} +

    ${this.get('name').toLowerCase()}

    +
  • ` + } +}) + +export default Metacode diff --git a/frontend/src/Metamaps/DataModel/MetacodeCollection.js b/frontend/src/Metamaps/DataModel/MetacodeCollection.js new file mode 100644 index 00000000..03c41613 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/MetacodeCollection.js @@ -0,0 +1,16 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Metacode from './Metacode' + +const MetacodeCollection = Backbone.Collection.extend({ + model: Metacode, + url: '/metacodes', + comparator: function (a, b) { + a = a.get('name').toLowerCase() + b = b.get('name').toLowerCase() + return a > b ? 1 : a < b ? -1 : 0 + } +}) + +export default MetacodeCollection diff --git a/frontend/src/Metamaps/DataModel/Synapse.js b/frontend/src/Metamaps/DataModel/Synapse.js new file mode 100644 index 00000000..a60611a3 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/Synapse.js @@ -0,0 +1,179 @@ +/* global $ */ + +import _ from 'lodash' +import outdent from 'outdent' +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Active from '../Active' +import Filter from '../Filter' +import JIT from '../JIT' +import Realtime from '../Realtime' +import SynapseCard from '../SynapseCard' +import Visualize from '../Visualize' + +import DataModel from './index' + +const Synapse = Backbone.Model.extend({ + urlRoot: '/synapses', + blacklist: ['edge', 'created_at', 'updated_at'], + toJSON: function (options) { + return _.omit(this.attributes, this.blacklist) + }, + save: function (key, val, options) { + var attrs + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (key == null || typeof key === 'object') { + attrs = key + options = val + } else { + (attrs = {})[key] = val + } + + var newOptions = options || {} + var s = newOptions.success + + var permBefore = this.get('permission') + + newOptions.success = function (model, response, opt) { + if (s) s(model, response, opt) + model.trigger('saved') + + if (permBefore === 'private' && model.get('permission') !== 'private') { + model.trigger('noLongerPrivate') + } else if (permBefore !== 'private' && model.get('permission') === 'private') { + model.trigger('nowPrivate') + } + } + return Backbone.Model.prototype.save.call(this, attrs, newOptions) + }, + initialize: function () { + if (this.isNew()) { + this.set({ + 'user_id': Active.Mapper.id, + 'permission': Active.Map ? Active.Map.get('permission') : 'commons', + 'category': 'from-to' + }) + } + + this.on('changeByOther', this.updateCardView) + this.on('change', this.updateEdgeView) + this.on('saved', this.savedEvent) + this.on('noLongerPrivate', function () { + var newSynapseData = { + mappingid: this.getMapping().id, + mappableid: this.id + } + + $(document).trigger(JIT.events.newSynapse, [newSynapseData]) + }) + this.on('nowPrivate', function () { + $(document).trigger(JIT.events.removeSynapse, [{ + mappableid: this.id + }]) + }) + + this.on('change:desc', Filter.checkSynapses, this) + }, + prepareLiForFilter: function () { + return outdent` +
  • + synapse icon +

    ${this.get('desc')}

    +
  • ` + }, + authorizeToEdit: function (mapper) { + if (mapper && (this.get('calculated_permission') === 'commons' || this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true + else return false + }, + authorizePermissionChange: function (mapper) { + if (mapper && this.get('user_id') === mapper.get('id')) return true + else return false + }, + getTopic1: function () { + return DataModel.Topics.get(this.get('topic1_id')) + }, + getTopic2: function () { + return DataModel.Topics.get(this.get('topic2_id')) + }, + getDirection: function () { + var t1 = this.getTopic1() + var t2 = this.getTopic2() + + return t1 && t2 ? [ + t1.get('node').id, + t2.get('node').id + ] : false + }, + getMapping: function () { + if (!Active.Map) return false + + return DataModel.Mappings.findWhere({ + map_id: Active.Map.id, + mappable_type: 'Synapse', + mappable_id: this.isNew() ? this.cid : this.id + }) + }, + createEdge: function (providedMapping) { + var mapping, mappingID + var synapseID = this.isNew() ? this.cid : this.id + + var edge = { + nodeFrom: this.get('topic1_id'), + nodeTo: this.get('topic2_id'), + data: { + $synapses: [], + $synapseIDs: [synapseID] + } + } + + if (Active.Map) { + mapping = providedMapping || this.getMapping() + mappingID = mapping.isNew() ? mapping.cid : mapping.id + edge.data.$mappings = [] + edge.data.$mappingIDs = [mappingID] + } + + return edge + }, + updateEdge: function () { + var mapping + var edge = this.get('edge') + edge.getData('synapses').push(this) + + if (Active.Map) { + mapping = this.getMapping() + edge.getData('mappings').push(mapping) + } + + return edge + }, + savedEvent: function () { + Realtime.updateSynapse(this) + }, + updateViews: function () { + this.updateCardView() + this.updateEdgeView() + }, + updateCardView: function () { + var onPageWithSynapseCard = Active.Map || Active.Topic + var edge = this.get('edge') + + // update synapse card, if this synapse is the one open there + if (onPageWithSynapseCard && edge === SynapseCard.openSynapseCard) { + SynapseCard.showCard(edge) + } + }, + updateEdgeView: function () { + var onPageWithSynapseCard = Active.Map || Active.Topic + var edge = this.get('edge') + + // update the edge on the map + if (onPageWithSynapseCard && edge) { + Visualize.mGraph.plot() + } + } +}) + +export default Synapse diff --git a/frontend/src/Metamaps/DataModel/SynapseCollection.js b/frontend/src/Metamaps/DataModel/SynapseCollection.js new file mode 100644 index 00000000..8d315353 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/SynapseCollection.js @@ -0,0 +1,11 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Synapse from './Synapse' + +const SynapseCollection = Backbone.Collection.extend({ + model: Synapse, + url: '/synapses' +}) + +export default SynapseCollection diff --git a/frontend/src/Metamaps/DataModel/Topic.js b/frontend/src/Metamaps/DataModel/Topic.js new file mode 100644 index 00000000..d8426c92 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/Topic.js @@ -0,0 +1,176 @@ +/* global $ */ + +import _ from 'lodash' +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Active from '../Active' +import Filter from '../Filter' +import JIT from '../JIT' +import Realtime from '../Realtime' +import TopicCard from '../TopicCard' +import Visualize from '../Visualize' + +import DataModel from './index' + +const Topic = Backbone.Model.extend({ + urlRoot: '/topics', + blacklist: ['node', 'created_at', 'updated_at', 'user_name', 'user_image', 'map_count', 'synapse_count'], + toJSON: function (options) { + return _.omit(this.attributes, this.blacklist) + }, + save: function (key, val, options) { + var attrs + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (key == null || typeof key === 'object') { + attrs = key + options = val + } else { + (attrs = {})[key] = val + } + + var newOptions = options || {} + var s = newOptions.success + + var permBefore = this.get('permission') + + newOptions.success = function (model, response, opt) { + if (s) s(model, response, opt) + model.trigger('saved') + model.set('calculated_permission', model.get('permission')) + + if (permBefore === 'private' && model.get('permission') !== 'private') { + model.trigger('noLongerPrivate') + } else if (permBefore !== 'private' && model.get('permission') === 'private') { + model.trigger('nowPrivate') + } + } + return Backbone.Model.prototype.save.call(this, attrs, newOptions) + }, + initialize: function () { + if (this.isNew()) { + this.set({ + 'user_id': Active.Mapper.id, + 'desc': this.get('desc') || '', + 'link': this.get('link') || '', + 'permission': Active.Map ? Active.Map.get('permission') : 'commons' + }) + } + + this.on('changeByOther', this.updateCardView) + this.on('change', this.updateNodeView) + this.on('saved', this.savedEvent) + this.on('nowPrivate', function () { + var removeTopicData = { + mappableid: this.id + } + + $(document).trigger(JIT.events.removeTopic, [removeTopicData]) + }) + this.on('noLongerPrivate', function () { + var newTopicData = { + mappingid: this.getMapping().id, + mappableid: this.id + } + + $(document).trigger(JIT.events.newTopic, [newTopicData]) + }) + + this.on('change:metacode_id', Filter.checkMetacodes, this) + }, + authorizeToEdit: function (mapper) { + if (mapper && + (this.get('user_id') === mapper.get('id') || + this.get('calculated_permission') === 'commons' || + this.get('collaborator_ids').includes(mapper.get('id')))) { + return true + } else { + return false + } + }, + authorizePermissionChange: function (mapper) { + if (mapper && this.get('user_id') === mapper.get('id')) return true + else return false + }, + getDate: function () {}, + getMetacode: function () { + return DataModel.Metacodes.get(this.get('metacode_id')) + }, + getMapping: function () { + if (!Active.Map) return false + + return DataModel.Mappings.findWhere({ + map_id: Active.Map.id, + mappable_type: 'Topic', + mappable_id: this.isNew() ? this.cid : this.id + }) + }, + createNode: function () { + var mapping + var node = { + adjacencies: [], + id: this.isNew() ? this.cid : this.id, + name: this.get('name') + } + + if (Active.Map) { + mapping = this.getMapping() + node.data = { + $mapping: null, + $mappingID: mapping.id + } + } + + return node + }, + updateNode: function () { + var mapping + var node = this.get('node') + node.setData('topic', this) + + if (Active.Map) { + mapping = this.getMapping() + node.setData('mapping', mapping) + } + + return node + }, + savedEvent: function () { + Realtime.updateTopic(this) + }, + updateViews: function () { + var onPageWithTopicCard = Active.Map || Active.Topic + var node = this.get('node') + // update topic card, if this topic is the one open there + if (onPageWithTopicCard && this === TopicCard.openTopicCard) { + TopicCard.showCard(node) + } + + // update the node on the map + if (onPageWithTopicCard && node) { + node.name = this.get('name') + Visualize.mGraph.plot() + } + }, + updateCardView: function () { + var onPageWithTopicCard = Active.Map || Active.Topic + var node = this.get('node') + // update topic card, if this topic is the one open there + if (onPageWithTopicCard && this === TopicCard.openTopicCard) { + TopicCard.showCard(node) + } + }, + updateNodeView: function () { + var onPageWithTopicCard = Active.Map || Active.Topic + var node = this.get('node') + + // update the node on the map + if (onPageWithTopicCard && node) { + node.name = this.get('name') + Visualize.mGraph.plot() + } + } +}) + +export default Topic diff --git a/frontend/src/Metamaps/DataModel/TopicCollection.js b/frontend/src/Metamaps/DataModel/TopicCollection.js new file mode 100644 index 00000000..a1de51d6 --- /dev/null +++ b/frontend/src/Metamaps/DataModel/TopicCollection.js @@ -0,0 +1,11 @@ +import Backbone from 'backbone' +try { Backbone.$ = window.$ } catch (err) {} + +import Topic from './Topic' + +const TopicCollection = Backbone.Collection.extend({ + model: Topic, + url: '/topics' +}) + +export default TopicCollection diff --git a/frontend/src/Metamaps/DataModel/index.js b/frontend/src/Metamaps/DataModel/index.js new file mode 100644 index 00000000..4e62113d --- /dev/null +++ b/frontend/src/Metamaps/DataModel/index.js @@ -0,0 +1,129 @@ +import Active from '../Active' +import Filter from '../Filter' +import { InfoBox } from '../Map' + +import Map from './Map' +import MapCollection from './MapCollection' +import Message from './Message' +import MessageCollection from './MessageCollection' +import Mapper from './Mapper' +import MapperCollection from './MapperCollection' +import Metacode from './Metacode' +import MetacodeCollection from './MetacodeCollection' +import Topic from './Topic' +import TopicCollection from './TopicCollection' +import Synapse from './Synapse' +import SynapseCollection from './SynapseCollection' +import Mapping from './Mapping' +import MappingCollection from './MappingCollection' + +const DataModel = { + Map: Map, + MapCollection: MapCollection, + Message: Message, + MessageCollection: MessageCollection, + Mapper: Mapper, + MapperCollection: MapperCollection, + Metacode: Metacode, + MetacodeCollection: MetacodeCollection, + Topic: Topic, + TopicCollection: TopicCollection, + Synapse: Synapse, + SynapseCollection: SynapseCollection, + Mapping: Mapping, + MappingCollection: MappingCollection, + + Collaborators: new MapperCollection(), + Creators: new MapperCollection(), + Mappers: new MapperCollection(), + Mappings: new MappingCollection(), + Maps: { + Mine: [], + Shared: [], + Starred: [], + Mapper: { + models: [], + mapperId: null + }, + Featured: [], + Active: [] + }, + Messages: [], + Metacodes: new MetacodeCollection(), + Stars: [], + Synapses: new SynapseCollection(), + Topics: new TopicCollection(), + + init: function (serverData) { + var self = DataModel + + // workaround circular import problem + if (!self.MapCollection.model) self.MapCollection.model = Map + + self.synapseIconUrl = serverData['synapse16.png'] + + if (serverData.ActiveMap) Active.Map = new Map(serverData.ActiveMap) + if (serverData.ActiveMapper) Active.Mapper = new Mapper(serverData.ActiveMapper) + if (serverData.ActiveTopic) Active.Topic = new Topic(serverData.ActiveTopic) + + if (serverData.Collaborators) self.Collaborators = new MapperCollection(serverData.Collaborators) + if (serverData.Creators) self.Creators = new MapperCollection(serverData.Creators) + if (serverData.Mappers) self.Mappers = new MapperCollection(serverData.Mappers) + if (serverData.Mappings) self.Mappings = new MappingCollection(serverData.Mappings) + if (serverData.Messages) self.Messages = serverData.Messages + if (serverData.Metacodes) self.Metacodes = new MetacodeCollection(serverData.Metacodes) + if (serverData.Stars) self.Stars = serverData.Stars + if (serverData.Synapses) self.Synapses = new SynapseCollection(serverData.Synapses) + if (serverData.Topics) self.Topics = new TopicCollection(serverData.Topics) + + // initialize global backbone models and collections + if (Active.Mapper) Active.Mapper = new self.Mapper(Active.Mapper) + + var myCollection = serverData.Mine ? serverData.Mine : [] + var sharedCollection = serverData.Shared ? serverData.Shared : [] + var starredCollection = serverData.Starred ? serverData.Starred : [] + var mapperCollection = [] + var mapperOptionsObj = { id: 'mapper', sortBy: 'updated_at' } + if (self.Maps.Mapper.mapperId) { + mapperCollection = serverData.Mapper.models + mapperOptionsObj.mapperId = serverData.Mapper.id + } + var featuredCollection = serverData.Featured ? serverData.Featured : [] + var activeCollection = serverData.Active ? serverData.Active : [] + + self.Maps.Mine = new MapCollection(myCollection, { id: 'mine', sortBy: 'updated_at' }) + self.Maps.Shared = new MapCollection(sharedCollection, { id: 'shared', sortBy: 'updated_at' }) + self.Maps.Starred = new MapCollection(starredCollection, { id: 'starred', sortBy: 'updated_at' }) + // 'Mapper' refers to another mapper + self.Maps.Mapper = new MapCollection(mapperCollection, mapperOptionsObj) + self.Maps.Featured = new MapCollection(featuredCollection, { id: 'featured', sortBy: 'updated_at' }) + self.Maps.Active = new MapCollection(activeCollection, { id: 'active', sortBy: 'updated_at' }) + + self.attachCollectionEvents() + }, + attachCollectionEvents: function () { + DataModel.Topics.on('add remove', function (topic) { + InfoBox.updateNumbers() + Filter.checkMetacodes() + Filter.checkMappers() + }) + DataModel.Synapses.on('add remove', function (synapse) { + InfoBox.updateNumbers() + Filter.checkSynapses() + Filter.checkMappers() + }) + DataModel.Mappings.on('add remove', function (mapping) { + InfoBox.updateNumbers() + Filter.checkSynapses() + Filter.checkMetacodes() + Filter.checkMappers() + }) + } +} + +// Note: Topics, Metacodes, Synapses, Mappers, Mappings, Collaborators, Creators are not exported +// You can access them by importing DataModel + +export { Map, MapCollection, Mapper, MapperCollection, Mapping, MappingCollection, Message, MessageCollection, Metacode, MetacodeCollection, Synapse, SynapseCollection, Topic, TopicCollection } + +export default DataModel diff --git a/frontend/src/Metamaps/Filter.js b/frontend/src/Metamaps/Filter.js index 59aa1bae..271e5758 100644 --- a/frontend/src/Metamaps/Filter.js +++ b/frontend/src/Metamaps/Filter.js @@ -1,23 +1,14 @@ -/* global Metamaps, $ */ +/* global $ */ import _ from 'lodash' import Active from './Active' import Control from './Control' +import DataModel from './DataModel' import GlobalUI from './GlobalUI' import Settings from './Settings' import Visualize from './Visualize' -/* - * Metamaps.Filter.js.erb - * - * Dependencies: - * - Metamaps.Creators - * - Metamaps.Mappers - * - Metamaps.Metacodes - * - Metamaps.Synapses - * - Metamaps.Topics - */ const Filter = { filters: { name: '', @@ -148,7 +139,7 @@ const Filter = { // the first option enables us to accept // ['Topics', 'Synapses'] as 'collection' if (typeof collection === 'object') { - Metamaps[collection[0]].each(function (model) { + DataModel[collection[0]].each(function (model) { var prop = model.get(propertyToCheck) if (prop !== null) { prop = prop.toString() @@ -157,7 +148,7 @@ const Filter = { } } }) - Metamaps[collection[1]].each(function (model) { + DataModel[collection[1]].each(function (model) { var prop = model.get(propertyToCheck) if (prop !== null) { prop = prop.toString() @@ -167,7 +158,7 @@ const Filter = { } }) } else if (typeof collection === 'string') { - Metamaps[collection].each(function (model) { + DataModel[collection].each(function (model) { var prop = model.get(propertyToCheck) if (prop !== null) { prop = prop.toString() @@ -196,8 +187,8 @@ const Filter = { } // for each new filter to be added, create a list item for it and fade it in _.each(added, function (identifier) { - model = Metamaps[correlatedModel].get(identifier) || - Metamaps[correlatedModel].find(function (model) { + model = DataModel[correlatedModel].get(identifier) || + DataModel[correlatedModel].find(function (model) { return model.get(propertyToCheck) === identifier }) li = model.prepareLiForFilter() @@ -359,7 +350,7 @@ const Filter = { var opacityForFilter = onMap ? 0 : 0.4 - Metamaps.Topics.each(function (topic) { + DataModel.Topics.each(function (topic) { var n = topic.get('node') var metacode_id = topic.get('metacode_id').toString() @@ -400,11 +391,11 @@ const Filter = { }) // flag all the edges back to 'untouched' - Metamaps.Synapses.each(function (synapse) { + DataModel.Synapses.each(function (synapse) { var e = synapse.get('edge') e.setData('touched', false) }) - Metamaps.Synapses.each(function (synapse) { + DataModel.Synapses.each(function (synapse) { var e = synapse.get('edge') var desc var user_id = synapse.get('user_id').toString() diff --git a/frontend/src/Metamaps/GlobalUI/CreateMap.js b/frontend/src/Metamaps/GlobalUI/CreateMap.js index a24c73c8..11c8deb9 100644 --- a/frontend/src/Metamaps/GlobalUI/CreateMap.js +++ b/frontend/src/Metamaps/GlobalUI/CreateMap.js @@ -1,13 +1,12 @@ -/* global Metamaps, $ */ +/* global $ */ + +import outdent from 'outdent' import Active from '../Active' +import DataModel from '../DataModel' +import DataModelMap from '../DataModel/Map' import GlobalUI from './index' -/* - * Metamaps.Backbone - * Metamaps.Maps - */ - const CreateMap = { newMap: null, emptyMapForm: '', @@ -17,7 +16,7 @@ const CreateMap = { init: function () { var self = CreateMap - self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }) + self.newMap = new DataModelMap({ permission: 'commons' }) self.bindFormEvents() @@ -44,15 +43,6 @@ const CreateMap = { $(this).remove() }) }, - generateSuccessMessage: function (id) { - var stringStart = "
    SUCCESS!
    Your map has been created. Do you want to: Go to your new map" - stringStart += "ORStay on this " - var page = Active.Map ? 'map' : 'page' - var stringEnd = '
    ' - return stringStart + page + stringEnd - }, switchPermission: function () { var self = CreateMap @@ -109,10 +99,23 @@ const CreateMap = { success: function (model) { var self = CreateMap // push the new map onto the collection of 'my maps' - Metamaps.Maps.Mine.add(model) + DataModel.Maps.Mine.add(model) GlobalUI.clearNotify() - $('#wrapper').append(self.generateSuccessMessage(model.id)) + $('#wrapper').append(outdent` +
    +
    SUCCESS!
    + Your map has been created. Do you want to: + Go to your new map + OR + Stay on this ${Active.Map ? 'map' : 'page'} +
    + `) + $('#mapGo').click(e => GlobalUI.CreateMap.closeSuccess()) + $('#mapStay').click(e => { + GlobalUI.CreateMap.closeSuccess() + return false + }) }, reset: function (id) { var self = CreateMap @@ -128,7 +131,7 @@ const CreateMap = { } self.bindFormEvents() - self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }) + self.newMap = new DataModel.Map({ permission: 'commons' }) return false } diff --git a/frontend/src/Metamaps/GlobalUI/Search.js b/frontend/src/Metamaps/GlobalUI/Search.js index 7ad1fbc1..0859b941 100644 --- a/frontend/src/Metamaps/GlobalUI/Search.js +++ b/frontend/src/Metamaps/GlobalUI/Search.js @@ -1,13 +1,8 @@ -/* global Metamaps, $, Hogan, Bloodhound, CanvasLoader */ +/* global $, Hogan, Bloodhound, CanvasLoader */ import Active from '../Active' import Router from '../Router' -/* - * Metamaps.Erb - * Metamaps.Maps - */ - const Search = { locked: false, isOpen: false, @@ -15,11 +10,13 @@ const Search = { limitMapsToMe: false, changing: false, optionsInitialized: false, - init: function () { + init: function (serverData) { var self = Search - // TODO does this overlap with Metamaps.Loading? - // devin sez: I'd like to remove Metamaps.Loading from the rails code + self.wildcardIconUrl = serverData['icons/wildcard.png'] + self.userIconUrl = serverData['user.png'] + + // this is similar to Metamaps.Loading, but it's for the search element var loader = new CanvasLoader('searchLoading') loader.setColor('#4fb5c0') // default is '#000000' loader.setDiameter(24) // default is 40 @@ -56,7 +53,7 @@ const Search = { return Hogan.compile(topicheader + $('#topicSearchTemplate').html()).render({ value: 'No results', label: 'No results', - typeImageURL: Metamaps.Erb['icons/wildcard.png'], + typeImageURL: self.wildcardIconUrl, rtype: 'noresult' }) }, @@ -124,7 +121,7 @@ const Search = { value: 'No results', label: 'No results', rtype: 'noresult', - profile: Metamaps.Erb['user.png'] + profile: self.userIconUrl }) }, header: mapperheader, diff --git a/frontend/src/Metamaps/GlobalUI/index.js b/frontend/src/Metamaps/GlobalUI/index.js index 4f1feb18..d1a0b6ba 100644 --- a/frontend/src/Metamaps/GlobalUI/index.js +++ b/frontend/src/Metamaps/GlobalUI/index.js @@ -1,8 +1,7 @@ -/* global Metamaps, $ */ +/* global $ */ import clipboard from 'clipboard-js' -import Active from '../Active' import Create from '../Create' import Search from './Search' @@ -10,21 +9,16 @@ import CreateMap from './CreateMap' import Account from './Account' import ImportDialog from './ImportDialog' -/* - * Metamaps.Backbone - * Metamaps.Maps - */ - const GlobalUI = { notifyTimeout: null, lightbox: null, - init: function () { + init: function (serverData) { var self = GlobalUI - self.Search.init() - self.CreateMap.init() - self.Account.init() - self.ImportDialog.init(Metamaps.Erb, self.openLightbox, self.closeLightbox) + self.Search.init(serverData) + self.CreateMap.init(serverData) + self.Account.init(serverData) + self.ImportDialog.init(serverData, self.openLightbox, self.closeLightbox) if ($('#toast').html().trim()) self.notifyUser($('#toast').html()) @@ -36,28 +30,6 @@ const GlobalUI = { }) $('#lightbox_screen, #lightbox_close').click(self.closeLightbox) - - // initialize global backbone models and collections - if (Active.Mapper) Active.Mapper = new Metamaps.Backbone.Mapper(Active.Mapper) - - var myCollection = Metamaps.Maps.Mine ? Metamaps.Maps.Mine : [] - var sharedCollection = Metamaps.Maps.Shared ? Metamaps.Maps.Shared : [] - var starredCollection = Metamaps.Maps.Starred ? Metamaps.Maps.Starred : [] - var mapperCollection = [] - var mapperOptionsObj = { id: 'mapper', sortBy: 'updated_at' } - if (Metamaps.Maps.Mapper) { - mapperCollection = Metamaps.Maps.Mapper.models - mapperOptionsObj.mapperId = Metamaps.Maps.Mapper.id - } - var featuredCollection = Metamaps.Maps.Featured ? Metamaps.Maps.Featured : [] - var activeCollection = Metamaps.Maps.Active ? Metamaps.Maps.Active : [] - Metamaps.Maps.Mine = new Metamaps.Backbone.MapsCollection(myCollection, { id: 'mine', sortBy: 'updated_at' }) - Metamaps.Maps.Shared = new Metamaps.Backbone.MapsCollection(sharedCollection, { id: 'shared', sortBy: 'updated_at' }) - Metamaps.Maps.Starred = new Metamaps.Backbone.MapsCollection(starredCollection, { id: 'starred', sortBy: 'updated_at' }) - // 'Mapper' refers to another mapper - Metamaps.Maps.Mapper = new Metamaps.Backbone.MapsCollection(mapperCollection, mapperOptionsObj) - Metamaps.Maps.Featured = new Metamaps.Backbone.MapsCollection(featuredCollection, { id: 'featured', sortBy: 'updated_at' }) - Metamaps.Maps.Active = new Metamaps.Backbone.MapsCollection(activeCollection, { id: 'active', sortBy: 'updated_at' }) }, showDiv: function (selector) { $(selector).show() diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index 6fd43bfe..8436c148 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -1,26 +1,16 @@ -/* global Metamaps, $ */ +/* global $ */ import parse from 'csv-parse' import _ from 'lodash' import Active from './Active' import AutoLayout from './AutoLayout' +import DataModel from './DataModel' import GlobalUI from './GlobalUI' import Map from './Map' import Synapse from './Synapse' import Topic from './Topic' -/* - * Metamaps.Import.js.erb - * - * Dependencies: - * - Metamaps.Backbone - * - Metamaps.Mappings - * - Metamaps.Metacodes - * - Metamaps.Synapses - * - Metamaps.Topics - */ - const Import = { // note that user is not imported topicWhitelist: [ @@ -228,7 +218,7 @@ const Import = { parsedTopics.forEach(topic => { let coords = { x: topic.x, y: topic.y } if (!coords.x || !coords.y) { - coords = AutoLayout.getNextCoord({ mappings: Metamaps.Mappings }) + coords = AutoLayout.getNextCoord({ mappings: DataModel.Mappings }) } if (!topic.name && topic.link || @@ -255,10 +245,10 @@ const Import = { parsedSynapses.forEach(function (synapse) { // only createSynapseWithParameters once both topics are persisted // if there isn't a cidMapping, check by topic name instead - var topic1 = Metamaps.Topics.get(self.cidMappings[synapse.topic1]) - if (!topic1) topic1 = Metamaps.Topics.findWhere({ name: synapse.topic1 }) - var topic2 = Metamaps.Topics.get(self.cidMappings[synapse.topic2]) - if (!topic2) topic2 = Metamaps.Topics.findWhere({ name: synapse.topic2 }) + var topic1 = DataModel.Topics.get(self.cidMappings[synapse.topic1]) + if (!topic1) topic1 = DataModel.Topics.findWhere({ name: synapse.topic1 }) + var topic2 = DataModel.Topics.get(self.cidMappings[synapse.topic2]) + if (!topic2) topic2 = DataModel.Topics.findWhere({ name: synapse.topic2 }) if (!topic1 || !topic2) { console.error("One of the two topics doesn't exist!") @@ -291,15 +281,15 @@ const Import = { link, xloc, yloc, import_id, opts = {}) { var self = Import $(document).trigger(Map.events.editedByActiveMapper) - var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null + var metacode = DataModel.Metacodes.where({name: metacode_name})[0] || null if (metacode === null) { - metacode = Metamaps.Metacodes.where({ name: 'Wildcard' })[0] + metacode = DataModel.Metacodes.where({ name: 'Wildcard' })[0] console.warn("Couldn't find metacode " + metacode_name + ' so used Wildcard instead.') } var topic_permission = permission || Active.Map.get('permission') var defer_to_map_id = permission === topic_permission ? Active.Map.get('id') : null - var topic = new Metamaps.Backbone.Topic({ + var topic = new DataModel.Topic({ name: name, metacode_id: metacode.id, permission: topic_permission, @@ -308,19 +298,19 @@ const Import = { link: link || '', calculated_permission: Active.Map.get('permission') }) - Metamaps.Topics.add(topic) + DataModel.Topics.add(topic) if (import_id !== null && import_id !== undefined) { self.cidMappings[import_id] = topic.cid } - var mapping = new Metamaps.Backbone.Mapping({ + var mapping = new DataModel.Mapping({ xloc: xloc, yloc: yloc, mappable_id: topic.cid, mappable_type: 'Topic' }) - Metamaps.Mappings.add(mapping) + DataModel.Mappings.add(mapping) // this function also includes the creation of the topic in the database Topic.renderTopic(mapping, topic, true, true, { @@ -340,20 +330,20 @@ const Import = { return } // if - var synapse = new Metamaps.Backbone.Synapse({ + var synapse = new DataModel.Synapse({ desc: desc || '', category: category || 'from-to', permission: permission, topic1_id: topic1.id, topic2_id: topic2.id }) - Metamaps.Synapses.add(synapse) + DataModel.Synapses.add(synapse) - var mapping = new Metamaps.Backbone.Mapping({ + var mapping = new DataModel.Mapping({ mappable_type: 'Synapse', mappable_id: synapse.cid }) - Metamaps.Mappings.add(mapping) + DataModel.Mappings.add(mapping) Synapse.renderSynapse(mapping, synapse, node1, node2, true) }, @@ -361,7 +351,7 @@ const Import = { handleURL: function (url, opts = {}) { let coords = opts.coords if (!coords || coords.x === undefined || coords.y === undefined) { - coords = AutoLayout.getNextCoord({ mappings: Metamaps.Mappings }) + coords = AutoLayout.getNextCoord({ mappings: DataModel.Mappings }) } const name = opts.name || 'Link' diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index f8bc51e8..7cbce927 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -1,4 +1,4 @@ -/* global Metamaps, $, Image, CanvasLoader */ +/* global $, Image, CanvasLoader */ import _ from 'lodash' import outdent from 'outdent' @@ -8,6 +8,7 @@ import $jit from '../patched/JIT' import Active from './Active' import Control from './Control' import Create from './Create' +import DataModel from './DataModel' import Filter from './Filter' import GlobalUI from './GlobalUI' import Map from './Map' @@ -23,14 +24,6 @@ import Util from './Util' import Visualize from './Visualize' import clipboard from 'clipboard-js' -/* - * Metamaps.Erb - * Metamaps.Mappings - * Metamaps.Metacodes - * Metamaps.Synapses - * Metamaps.Topics - */ - let panningInt const JIT = { @@ -58,7 +51,7 @@ const JIT = { /** * This method will bind the event handlers it is interested and initialize the class. */ - init: function () { + init: function (serverData) { const self = JIT $('.zoomIn').click(self.zoomIn) @@ -72,10 +65,10 @@ const JIT = { $('.takeScreenshot').click(Map.exportImage) self.topicDescImage = new Image() - self.topicDescImage.src = Metamaps.Erb['topic_description_signifier.png'] + self.topicDescImage.src = serverData['topic_description_signifier.png'] self.topicLinkImage = new Image() - self.topicLinkImage.src = Metamaps.Erb['topic_link_signifier.png'] + self.topicLinkImage.src = serverData['topic_link_signifier.png'] }, /** * convert our topic JSON into something JIT can use @@ -140,15 +133,15 @@ const JIT = { self.vizData = [] Visualize.loadLater = false - const results = self.convertModelsToJIT(Metamaps.Topics, Metamaps.Synapses) + const results = self.convertModelsToJIT(DataModel.Topics, DataModel.Synapses) self.vizData = results[0] // clean up the synapses array in case of any faulty data _.each(results[1], function (synapse) { mapping = synapse.getMapping() - Metamaps.Synapses.remove(synapse) - if (Metamaps.Mappings) Metamaps.Mappings.remove(mapping) + DataModel.Synapses.remove(synapse) + if (DataModel.Mappings) DataModel.Mappings.remove(mapping) }) // set up addTopic instructions in case they delete all the topics @@ -320,17 +313,6 @@ const JIT = { panning: 'avoid nodes', zooming: 28 // zoom speed. higher is more sensible }, - // background: { - // type: 'Metamaps' - // }, - // NodeStyles: { - // enable: true, - // type: 'Native', - // stylesHover: { - // dim: 30 - // }, - // duration: 300 - // }, // Change node and edge styles such as // color and width. // These properties are also set per node @@ -656,7 +638,6 @@ const JIT = { }, // this will just be used to patch the ForceDirected graphsettings with the few things which actually differ background: { - // type: 'Metamaps', levelDistance: 200, numberOfCircles: 4, CanvasStyles: { @@ -1191,7 +1172,7 @@ const JIT = { eY = -1 * eY const edgesToToggle = [] - Metamaps.Synapses.each(function (synapse) { + DataModel.Synapses.each(function (synapse) { const e = synapse.get('edge') if (edgesToToggle.indexOf(e) === -1) { edgesToToggle.push(e) @@ -1579,15 +1560,15 @@ const JIT = { loader.setRange(0.9) // default is 1.3 loader.show() // Hidden by default - const topics = Metamaps.Topics.map(function (t) { return t.id }) + const topics = DataModel.Topics.map(function (t) { return t.id }) const topicsString = topics.join() const successCallback = function (data) { $('#loadingSiblings').remove() for (var key in data) { - const string = Metamaps.Metacodes.get(key).get('name') + ' (' + data[key] + ')' - $('#fetchSiblingList').append('
  • ' + string + '
  • ') + const string = `${DataModel.Metacodes.get(key).get('name')} (${data[key]})` + $('#fetchSiblingList').append(`
  • ${string}
  • `) } $('.rc-siblings .getSiblings').click(function () { diff --git a/frontend/src/Metamaps/Loading.js b/frontend/src/Metamaps/Loading.js new file mode 100644 index 00000000..b1fc2abb --- /dev/null +++ b/frontend/src/Metamaps/Loading.js @@ -0,0 +1,21 @@ +/* global CanvasLoader, $ */ + +const Loading = { + loader: null, // needs CanvasLoader to be defined + hide: function () { + $('#loading').hide() + }, + show: function () { + $('#loading').show() + }, + setup: function () { + if (!Loading.loader) Loading.loader = new CanvasLoader('loading') + Loading.loader.setColor('#4fb5c0') // default is '#000000' + Loading.loader.setDiameter(28) // default is 40 + Loading.loader.setDensity(41) // default is 40 + Loading.loader.setRange(0.9) // default is 1.3 + Loading.loader.show() // Hidden by default + } +} + +export default Loading diff --git a/frontend/src/Metamaps/Map/InfoBox.js b/frontend/src/Metamaps/Map/InfoBox.js index 79fa6c4d..bf56dc90 100644 --- a/frontend/src/Metamaps/Map/InfoBox.js +++ b/frontend/src/Metamaps/Map/InfoBox.js @@ -1,21 +1,13 @@ -/* global Metamaps, $, Hogan, Bloodhound, Countable */ +/* global $, Hogan, Bloodhound, Countable */ import outdent from 'outdent' import Active from '../Active' +import DataModel from '../DataModel' import GlobalUI from '../GlobalUI' import Router from '../Router' import Util from '../Util' -/* - * Metamaps.Collaborators - * Metamaps.Erb - * Metamaps.Mappers - * Metamaps.Maps - * Metamaps.Synapses - * Metamaps.Topics - */ - const InfoBox = { isOpen: false, changing: false, @@ -42,7 +34,8 @@ const InfoBox = { data-bip-activator="#mapInfoDesc" data-bip-value="{{desc}}" >{{desc}}`, - init: function () { + userImageUrl: '', + init: function (serverData) { var self = InfoBox $('.mapInfoIcon').click(self.toggleBox) @@ -54,7 +47,9 @@ const InfoBox = { self.attachEventListeners() self.generateBoxHTML = Hogan.compile($('#mapInfoBoxTemplate').html()) - + + self.userImageUrl = serverData['user.png'] + var querystring = window.location.search.replace(/^\?/, '') if (querystring == 'new') { self.open() @@ -106,7 +101,7 @@ const InfoBox = { var isCreator = map.authorizePermissionChange(Active.Mapper) var canEdit = map.authorizeToEdit(Active.Mapper) - var relevantPeople = map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators + var relevantPeople = map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators var shareable = map.get('permission') !== 'private' obj['name'] = canEdit ? Hogan.compile(self.nameHTML).render({id: map.id, name: map.get('name')}) : map.get('name') @@ -116,7 +111,7 @@ const InfoBox = { obj['contributor_count'] = relevantPeople.length obj['contributors_class'] = relevantPeople.length > 1 ? 'multiple' : '' obj['contributors_class'] += relevantPeople.length === 2 ? ' mTwo' : '' - obj['contributor_image'] = relevantPeople.length > 0 ? relevantPeople.models[0].get('image') : Metamaps.Erb['user.png'] + obj['contributor_image'] = relevantPeople.length > 0 ? relevantPeople.models[0].get('image') : self.userImageUrl obj['contributor_list'] = self.createContributorList() obj['user_name'] = isCreator ? 'You' : map.get('user_name') @@ -218,7 +213,7 @@ const InfoBox = { value: "No results", label: "No results", rtype: "noresult", - profile: Metamaps.Erb['user.png'], + profile: self.userImageUrl }); }, suggestion: function(s) { @@ -251,24 +246,24 @@ const InfoBox = { }, removeCollaborator: function (collaboratorId) { var self = InfoBox - Metamaps.Collaborators.remove(Metamaps.Collaborators.get(collaboratorId)) - var mapperIds = Metamaps.Collaborators.models.map(function (mapper) { return mapper.id }) + DataModel.Collaborators.remove(DataModel.Collaborators.get(collaboratorId)) + var mapperIds = DataModel.Collaborators.models.map(function (mapper) { return mapper.id }) $.post('/maps/' + Active.Map.id + '/access', { access: mapperIds }) self.updateNumbers() }, addCollaborator: function (newCollaboratorId) { var self = InfoBox - if (Metamaps.Collaborators.get(newCollaboratorId)) { + if (DataModel.Collaborators.get(newCollaboratorId)) { GlobalUI.notifyUser('That user already has access') return } function callback(mapper) { - Metamaps.Collaborators.add(mapper) - var mapperIds = Metamaps.Collaborators.models.map(function (mapper) { return mapper.id }) + DataModel.Collaborators.add(mapper) + var mapperIds = DataModel.Collaborators.models.map(function (mapper) { return mapper.id }) $.post('/maps/' + Active.Map.id + '/access', { access: mapperIds }) - var name = Metamaps.Collaborators.get(newCollaboratorId).get('name') + var name = DataModel.Collaborators.get(newCollaboratorId).get('name') GlobalUI.notifyUser(name + ' will be notified by email') self.updateNumbers() } @@ -289,7 +284,7 @@ const InfoBox = { }, createContributorList: function () { var self = InfoBox - var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators + var relevantPeople = Active.Map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators var activeMapperIsCreator = Active.Mapper && Active.Mapper.id === Active.Map.get('user_id') var string = '' string += '