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
|
# Unlock any Task that might have been locked
|
||||||
Task.objects.filter(processing_lock=True).update(processing_lock=False)
|
Task.objects.filter(processing_lock=True).update(processing_lock=False)
|
||||||
|
|
||||||
# Register plugins
|
|
||||||
register_plugins()
|
register_plugins()
|
||||||
|
|
||||||
if not settings.TESTING:
|
if not settings.TESTING:
|
||||||
|
|
|
@ -24,8 +24,19 @@ class PluginBase(ABC):
|
||||||
def get_module_name(self):
|
def get_module_name(self):
|
||||||
return self.__class__.__module__
|
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):
|
def has_public_path(self):
|
||||||
return os.path.isdir(self.get_path("public"))
|
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):
|
def __str__(self):
|
||||||
return "[{}]".format(self.get_module_name())
|
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;
|
parser.href = href;
|
||||||
|
|
||||||
return `${parser.protocol}//${parser.host}/${path}`;
|
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 React from 'react';
|
||||||
import ReactDOMServer from 'react-dom/server';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import '../css/Map.scss';
|
import '../css/Map.scss';
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
import Leaflet from 'leaflet';
|
import Leaflet from 'leaflet';
|
||||||
|
@ -17,6 +15,7 @@ import SwitchModeButton from './SwitchModeButton';
|
||||||
import ShareButton from './ShareButton';
|
import ShareButton from './ShareButton';
|
||||||
import AssetDownloads from '../classes/AssetDownloads';
|
import AssetDownloads from '../classes/AssetDownloads';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import PluginsAPI from '../classes/PluginsAPI';
|
||||||
|
|
||||||
class Map extends React.Component {
|
class Map extends React.Component {
|
||||||
static defaultProps = {
|
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) {
|
componentDidUpdate(prevProps) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import '../css/main.scss';
|
import '../css/main.scss';
|
||||||
import './django/csrf';
|
import './django/csrf';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import PluginsAPI from './classes/PluginsAPI';
|
||||||
|
|
||||||
// Main is always executed first in the page
|
// Main is always executed first in the page
|
||||||
|
|
||||||
// We share the ReactDOM object to avoid having to include it
|
// We share the ReactDOM object to avoid having to include it
|
||||||
// as a dependency in each component (adds too much space overhead)
|
// as a dependency in each component (adds too much space overhead)
|
||||||
window.ReactDOM = ReactDOM;
|
window.ReactDOM = ReactDOM;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
{% load i18n static settings compress %}
|
{% load i18n static settings compress plugins %}
|
||||||
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
@ -22,6 +22,10 @@
|
||||||
{% load render_bundle from webpack_loader %}
|
{% load render_bundle from webpack_loader %}
|
||||||
{% render_bundle 'main' %}
|
{% render_bundle 'main' %}
|
||||||
|
|
||||||
|
{% autoescape off %}
|
||||||
|
{% get_plugins_js_includes %}
|
||||||
|
{% endautoescape %}
|
||||||
|
|
||||||
<title>{{title|default:"Login"}} - {{ SETTINGS.app_name }}</title>
|
<title>{{title|default:"Login"}} - {{ SETTINGS.app_name }}</title>
|
||||||
|
|
||||||
{% compress css %}
|
{% 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": "^3.3.0",
|
||||||
"enzyme-adapter-react-16": "^1.1.1",
|
"enzyme-adapter-react-16": "^1.1.1",
|
||||||
"extract-text-webpack-plugin": "^3.0.0",
|
"extract-text-webpack-plugin": "^3.0.0",
|
||||||
|
"fbemitter": "^2.1.1",
|
||||||
"file-loader": "^0.9.0",
|
"file-loader": "^0.9.0",
|
||||||
"gl-matrix": "^2.3.2",
|
"gl-matrix": "^2.3.2",
|
||||||
"history": "^4.7.2",
|
"history": "^4.7.2",
|
||||||
|
|
|
@ -3,4 +3,7 @@ from app.plugins import PluginBase
|
||||||
class Plugin(PluginBase):
|
class Plugin(PluginBase):
|
||||||
|
|
||||||
def register(self):
|
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