Files
geutebruck/SOURCES/CODEX/GeViScope/GeViScopeSDK_HTML5/Resources/Scripts/plugins.min.js
Administrator 14893e62a5 feat: Geutebruck GeViScope/GeViSoft Action Mapping System - MVP
This MVP release provides a complete full-stack solution for managing action mappings
in Geutebruck's GeViScope and GeViSoft video surveillance systems.

## Features

### Flutter Web Application (Port 8081)
- Modern, responsive UI for managing action mappings
- Action picker dialog with full parameter configuration
- Support for both GSC (GeViScope) and G-Core server actions
- Consistent UI for input and output actions with edit/delete capabilities
- Real-time action mapping creation, editing, and deletion
- Server categorization (GSC: prefix for GeViScope, G-Core: prefix for G-Core servers)

### FastAPI REST Backend (Port 8000)
- RESTful API for action mapping CRUD operations
- Action template service with comprehensive action catalog (247 actions)
- Server management (G-Core and GeViScope servers)
- Configuration tree reading and writing
- JWT authentication with role-based access control
- PostgreSQL database integration

### C# SDK Bridge (gRPC, Port 50051)
- Native integration with GeViSoft SDK (GeViProcAPINET_4_0.dll)
- Action mapping creation with correct binary format
- Support for GSC and G-Core action types
- Proper Camera parameter inclusion in action strings (fixes CrossSwitch bug)
- Action ID lookup table with server-specific action IDs
- Configuration reading/writing via SetupClient

## Bug Fixes
- **CrossSwitch Bug**: GSC and G-Core actions now correctly display camera/PTZ head parameters in GeViSet
- Action strings now include Camera parameter: `@ PanLeft (Comment: "", Camera: 101028)`
- Proper filter flags and VideoInput=0 for action mappings
- Correct action ID assignment (4198 for GSC, 9294 for G-Core PanLeft)

## Technical Stack
- **Frontend**: Flutter Web, Dart, Dio HTTP client
- **Backend**: Python FastAPI, PostgreSQL, Redis
- **SDK Bridge**: C# .NET 8.0, gRPC, GeViSoft SDK
- **Authentication**: JWT tokens
- **Configuration**: GeViSoft .set files (binary format)

## Credentials
- GeViSoft/GeViScope: username=sysadmin, password=masterkey
- Default admin: username=admin, password=admin123

## Deployment
All services run on localhost:
- Flutter Web: http://localhost:8081
- FastAPI: http://localhost:8000
- SDK Bridge gRPC: localhost:50051
- GeViServer: localhost (default port)

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 18:10:54 +01:00

48 lines
9.3 KiB
JavaScript

/* Array.indexOf polyfill
* https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
*/
if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (e) { "use strict"; if (this == null) { throw new TypeError } var t = Object(this); var n = t.length >>> 0; if (n === 0) { return -1 } var r = 0; if (arguments.length > 1) { r = Number(arguments[1]); if (r != r) { r = 0 } else if (r != 0 && r != Infinity && r != -Infinity) { r = (r > 0 || -1) * Math.floor(Math.abs(r)) } } if (r >= n) { return -1 } var i = r >= 0 ? r : Math.max(n - Math.abs(r), 0); for (; i < n; i++) { if (i in t && t[i] === e) { return i } } return -1 } }
/*
* jQuery hashchange event - v1.3 - 7/21/2010
* http://benalman.com/projects/jquery-hashchange-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function ($, e, b) { var c = "hashchange", h = document, f, g = $.event.special, i = h.documentMode, d = "on" + c in e && (i === b || i > 7); function a(j) { j = j || location.href; return "#" + j.replace(/^[^#]*#?(.*)$/, "$1") } $.fn[c] = function (j) { return j ? this.bind(c, j) : this.trigger(c) }; $.fn[c].delay = 50; g[c] = $.extend(g[c], { setup: function () { if (d) { return false } $(f.start) }, teardown: function () { if (d) { return false } $(f.stop) } }); f = (function () { var j = {}, p, m = a(), k = function (q) { return q }, l = k, o = k; j.start = function () { p || n() }; j.stop = function () { p && clearTimeout(p); p = b }; function n() { var r = a(), q = o(m); if (r !== m) { l(m = r, q); $(e).trigger(c) } else { if (q !== m) { location.href = location.href.replace(/#.*/, "") + q } } p = setTimeout(n, $.fn[c].delay) } $.browser.msie && !d && (function () { var q, r; j.start = function () { if (!q) { r = $.fn[c].src; r = r && r + a(); q = $('<iframe tabindex="-1" title="empty"/>').hide().one("load", function () { r || l(a()); n() }).attr("src", r || "javascript:0").insertAfter("body")[0].contentWindow; h.onpropertychange = function () { try { if (event.propertyName === "title") { q.document.title = h.title } } catch (s) { } } } }; j.stop = k; o = function () { return a(q.location.href) }; l = function (v, s) { var u = q.document, t = $.fn[c].domain; if (v !== s) { u.title = h.title; u.open(); t && u.write('<script>document.domain="' + t + '"<\/script>'); u.close(); q.location.hash = v } } })(); return j })() })(jQuery, this);
/*! http://mths.be/placeholder v1.8.7 by @mathias */
(function (f, h, c) { var a = 'placeholder' in h.createElement('input'), d = 'placeholder' in h.createElement('textarea'), i = c.fn, j; if (a && d) { j = i.placeholder = function () { return this }; j.input = j.textarea = true } else { j = i.placeholder = function () { return this.filter((a ? 'textarea' : ':input') + '[placeholder]').not('.placeholder').bind('focus.placeholder', b).bind('blur.placeholder', e).trigger('blur.placeholder').end() }; j.input = a; j.textarea = d; c(function () { c(h).delegate('form', 'submit.placeholder', function () { var k = c('.placeholder', this).each(b); setTimeout(function () { k.each(e) }, 10) }) }); c(f).bind('unload.placeholder', function () { c('.placeholder').val('') }) } function g(l) { var k = {}, m = /^jQuery\d+$/; c.each(l.attributes, function (o, n) { if (n.specified && !m.test(n.name)) { k[n.name] = n.value } }); return k } function b() { var k = c(this); if (k.val() === k.attr('placeholder') && k.hasClass('placeholder')) { if (k.data('placeholder-password')) { k.hide().next().show().focus().attr('id', k.removeAttr('id').data('placeholder-id')) } else { k.val('').removeClass('placeholder') } } } function e() { var o, n = c(this), k = n, m = this.id; if (n.val() === '') { if (n.is(':password')) { if (!n.data('placeholder-textinput')) { try { o = n.clone().attr({ type: 'text' }) } catch (l) { o = c('<input>').attr(c.extend(g(this), { type: 'text' })) } o.removeAttr('name').data('placeholder-password', true).data('placeholder-id', m).bind('focus.placeholder', b); n.data('placeholder-textinput', o).data('placeholder-id', m).before(o) } n = n.removeAttr('id').hide().prev().attr('id', m).show() } n.addClass('placeholder').val(n.attr('placeholder')) } else { n.removeClass('placeholder') } } } (this, document, jQuery));
/*
* jQuery scrollintoview() plugin and :scrollable selector filter
*
* Version 1.8 (14 Jul 2011)
* Requires jQuery 1.4 or newer
*
* Copyright (c) 2011 Robert Koritnik
* Licensed under the terms of the MIT license
* http://www.opensource.org/licenses/mit-license.php
*/
(function (f) { var c = { vertical: { x: false, y: true }, horizontal: { x: true, y: false }, both: { x: true, y: true }, x: { x: true, y: false }, y: { x: false, y: true} }; var b = { duration: "fast", direction: "both" }; var e = /^(?:html)$/i; var g = function (k, j) { j = j || (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(k, null) : k.currentStyle); var i = document.defaultView && document.defaultView.getComputedStyle ? true : false; var h = { top: (parseFloat(i ? j.borderTopWidth : f.css(k, "borderTopWidth")) || 0), left: (parseFloat(i ? j.borderLeftWidth : f.css(k, "borderLeftWidth")) || 0), bottom: (parseFloat(i ? j.borderBottomWidth : f.css(k, "borderBottomWidth")) || 0), right: (parseFloat(i ? j.borderRightWidth : f.css(k, "borderRightWidth")) || 0) }; return { top: h.top, left: h.left, bottom: h.bottom, right: h.right, vertical: h.top + h.bottom, horizontal: h.left + h.right} }; var d = function (h) { var j = f(window); var i = e.test(h[0].nodeName); return { border: i ? { top: 0, left: 0, bottom: 0, right: 0} : g(h[0]), scroll: { top: (i ? j : h).scrollTop(), left: (i ? j : h).scrollLeft() }, scrollbar: { right: i ? 0 : h.innerWidth() - h[0].clientWidth, bottom: i ? 0 : h.innerHeight() - h[0].clientHeight }, rect: (function () { var k = h[0].getBoundingClientRect(); return { top: i ? 0 : k.top, left: i ? 0 : k.left, bottom: i ? h[0].clientHeight : k.bottom, right: i ? h[0].clientWidth : k.right} })()} }; f.fn.extend({ scrollintoview: function (j) { j = f.extend({}, b, j); j.direction = c[typeof (j.direction) === "string" && j.direction.toLowerCase()] || c.both; var n = ""; if (j.direction.x === true) { n = "horizontal" } if (j.direction.y === true) { n = n ? "both" : "vertical" } var l = this.eq(0); var i = l.closest(":scrollable(" + n + ")"); if (i.length > 0) { i = i.eq(0); var m = { e: d(l), s: d(i) }; var h = { top: m.e.rect.top - (m.s.rect.top + m.s.border.top), bottom: m.s.rect.bottom - m.s.border.bottom - m.s.scrollbar.bottom - m.e.rect.bottom, left: m.e.rect.left - (m.s.rect.left + m.s.border.left), right: m.s.rect.right - m.s.border.right - m.s.scrollbar.right - m.e.rect.right }; var k = {}; if (j.direction.y === true) { if (h.top < 0) { k.scrollTop = m.s.scroll.top + h.top } else { if (h.top > 0 && h.bottom < 0) { k.scrollTop = m.s.scroll.top + Math.min(h.top, -h.bottom) } } } if (j.direction.x === true) { if (h.left < 0) { k.scrollLeft = m.s.scroll.left + h.left } else { if (h.left > 0 && h.right < 0) { k.scrollLeft = m.s.scroll.left + Math.min(h.left, -h.right) } } } if (!f.isEmptyObject(k)) { if (e.test(i[0].nodeName)) { i = f("html,body") } i.animate(k, j.duration).eq(0).queue(function (o) { f.isFunction(j.complete) && j.complete.call(i[0]); o() }) } else { f.isFunction(j.complete) && j.complete.call(i[0]) } } return this } }); var a = { auto: true, scroll: true, visible: false, hidden: false }; f.extend(f.expr[":"], { scrollable: function (k, i, n, h) { var m = c[typeof (n[3]) === "string" && n[3].toLowerCase()] || c.both; var l = (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(k, null) : k.currentStyle); var o = { x: a[l.overflowX.toLowerCase()] || false, y: a[l.overflowY.toLowerCase()] || false, isRoot: e.test(k.nodeName) }; if (!o.x && !o.y && !o.isRoot) { return false } var j = { height: { scroll: k.scrollHeight, client: k.clientHeight }, width: { scroll: k.scrollWidth, client: k.clientWidth }, scrollableX: function () { return (o.x || o.isRoot) && this.width.scroll > this.width.client }, scrollableY: function () { return (o.y || o.isRoot) && this.height.scroll > this.height.client } }; return m.y && j.scrollableY() || m.x && j.scrollableX() } }) })(jQuery);
/*
highlight v4
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>
*/
jQuery.fn.highlight = function (e, t) { function n(e, r) { var i = 0; if (e.nodeType == 3) { var s = e.data.toUpperCase().indexOf(r); if (s >= 0) { var o = document.createElement("span"); o.className = t || "highlight"; var u = e.splitText(s); var a = u.splitText(r.length); var f = u.cloneNode(true); o.appendChild(f); u.parentNode.replaceChild(o, u); i = 1 } } else if (e.nodeType == 1 && e.childNodes && !/(script|style)/i.test(e.tagName)) { for (var l = 0; l < e.childNodes.length; ++l) { l += n(e.childNodes[l], r) } } return i } return this.length && e && e.length ? this.each(function () { n(this, e.toUpperCase()) }) : this }; jQuery.fn.removeHighlight = function (className) { return this.find("span." + className || "highlight").each(function () { this.parentNode.firstChild.nodeName; with (this.parentNode) { replaceChild(this.firstChild, this); normalize() } }).end() }