kopia lustrzana https://github.com/OpenDroneMap/WebODM
Proof of concept JS-side communication between map component and plugin
rodzic
d0b4a058bf
commit
e5a6628f4b
|
@ -88,7 +88,6 @@ def boot():
|
|||
# Unlock any Task that might have been locked
|
||||
Task.objects.filter(processing_lock=True).update(processing_lock=False)
|
||||
|
||||
# Register plugins
|
||||
register_plugins()
|
||||
|
||||
if not settings.TESTING:
|
||||
|
|
|
@ -24,8 +24,19 @@ class PluginBase(ABC):
|
|||
def get_module_name(self):
|
||||
return self.__class__.__module__
|
||||
|
||||
def get_include_js_urls(self):
|
||||
return ["/plugins/{}/{}".format(self.get_name(), js_file) for js_file in self.include_js_files()]
|
||||
|
||||
def has_public_path(self):
|
||||
return os.path.isdir(self.get_path("public"))
|
||||
|
||||
def include_js_files(self):
|
||||
"""
|
||||
Should be overriden by plugins to communicate
|
||||
which JS files should be included in the WebODM interface
|
||||
All paths are relative to a plugin's /public folder.
|
||||
"""
|
||||
return []
|
||||
|
||||
def __str__(self):
|
||||
return "[{}]".format(self.get_module_name())
|
|
@ -0,0 +1,26 @@
|
|||
import { EventEmitter } from 'fbemitter';
|
||||
import Utils from './Utils';
|
||||
|
||||
const { assert } = Utils;
|
||||
|
||||
if (!window.PluginsAPI){
|
||||
const events = new EventEmitter();
|
||||
|
||||
window.PluginsAPI = {
|
||||
Map: {
|
||||
AddPanel: (callback) => {
|
||||
events.addListener('Map::Loaded', callback);
|
||||
},
|
||||
|
||||
Loaded: (params) => {
|
||||
assert(params.map !== undefined);
|
||||
events.emit('Map::Loaded', params);
|
||||
}
|
||||
},
|
||||
|
||||
events
|
||||
};
|
||||
}
|
||||
|
||||
export default window.PluginsAPI;
|
||||
|
|
@ -63,6 +63,16 @@ export default {
|
|||
parser.href = href;
|
||||
|
||||
return `${parser.protocol}//${parser.host}/${path}`;
|
||||
},
|
||||
|
||||
assert: function(condition, message) {
|
||||
if (!condition) {
|
||||
message = message || "Assertion failed";
|
||||
if (typeof Error !== "undefined") {
|
||||
throw new Error(message);
|
||||
}
|
||||
throw message; // Fallback
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import React from 'react';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
import ReactDOM from 'react-dom';
|
||||
import '../css/Map.scss';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import Leaflet from 'leaflet';
|
||||
|
@ -17,6 +15,7 @@ import SwitchModeButton from './SwitchModeButton';
|
|||
import ShareButton from './ShareButton';
|
||||
import AssetDownloads from '../classes/AssetDownloads';
|
||||
import PropTypes from 'prop-types';
|
||||
import PluginsAPI from '../classes/PluginsAPI';
|
||||
|
||||
class Map extends React.Component {
|
||||
static defaultProps = {
|
||||
|
@ -236,6 +235,13 @@ class Map extends React.Component {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
// PluginsAPI.events.addListener('Map::AddPanel', (e) => {
|
||||
// console.log("Received response: " + e);
|
||||
// });
|
||||
PluginsAPI.Map.Loaded({
|
||||
map: this.map
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import '../css/main.scss';
|
||||
import './django/csrf';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PluginsAPI from './classes/PluginsAPI';
|
||||
|
||||
// Main is always executed first in the page
|
||||
|
||||
// We share the ReactDOM object to avoid having to include it
|
||||
// as a dependency in each component (adds too much space overhead)
|
||||
window.ReactDOM = ReactDOM;
|
||||
window.ReactDOM = ReactDOM;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{% load i18n static settings compress %}
|
||||
{% load i18n static settings compress plugins %}
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
@ -22,6 +22,10 @@
|
|||
{% load render_bundle from webpack_loader %}
|
||||
{% render_bundle 'main' %}
|
||||
|
||||
{% autoescape off %}
|
||||
{% get_plugins_js_includes %}
|
||||
{% endautoescape %}
|
||||
|
||||
<title>{{title|default:"Login"}} - {{ SETTINGS.app_name }}</title>
|
||||
|
||||
{% compress css %}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
from django import template
|
||||
from app.plugins import get_active_plugins
|
||||
import itertools
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.simple_tag(takes_context=False)
|
||||
def get_plugins_js_includes():
|
||||
# Flatten all urls for all plugins
|
||||
js_urls = list(itertools.chain(*[plugin.get_include_js_urls() for plugin in get_active_plugins()]))
|
||||
return "\n".join(map(lambda url: "<script src='{}'></script>".format(url), js_urls))
|
|
@ -35,6 +35,7 @@
|
|||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"fbemitter": "^2.1.1",
|
||||
"file-loader": "^0.9.0",
|
||||
"gl-matrix": "^2.3.2",
|
||||
"history": "^4.7.2",
|
||||
|
|
|
@ -3,4 +3,7 @@ from app.plugins import PluginBase
|
|||
class Plugin(PluginBase):
|
||||
|
||||
def register(self):
|
||||
print("I'm registering!!!")
|
||||
print("I'm registering!!!")
|
||||
|
||||
def include_js_files(self):
|
||||
return ['hello.js']
|
|
@ -1 +1,3 @@
|
|||
console.log("HI!!");
|
||||
PluginsAPI.Map.AddPanel(function(params){
|
||||
console.log("GOT: ", params.map);
|
||||
});
|
Ładowanie…
Reference in New Issue