fgeorges / expath-ml-console Goto Github PK
View Code? Open in Web Editor NEWEXPath Console for MarkLogic
EXPath Console for MarkLogic
Preliminary work on supporting groups.
At the end of the day, find a mechanism to install the same package on all app servers in a group (as convenience, because it is not possible to install a package at the group level itself: http://markmail.org/message/zyym6s5b4ya5svru).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ git status
# On branch feature/bootstrap
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: src/appserver.xq
# modified: src/plumbing/rewriter.xml
# modified: src/repo.xq
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# src/appserver/repo-page.xql
# src/group.xq
no changes added to commit (use "git add" and/or "git commit -a")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ cat src/group.xq
xquery version "3.0";
import module namespace p = "http://expath.org/ns/ml/console/repo-page" at "appserver/repo-page.xql";
import module namespace a = "http://expath.org/ns/ml/console/admin" at "lib/admin.xql";
import module namespace t = "http://expath.org/ns/ml/console/tools" at "lib/tools.xql";
import module namespace v = "http://expath.org/ns/ml/console/view" at "lib/view.xql";
declare default element namespace "http://www.w3.org/1999/xhtml";
declare namespace pp = "http://expath.org/ns/repo/packages";
(: path relative to the AS. TODO: To be moved to a lib... :)
declare variable $packages-path := 'expath-repo/.expath-pkg/packages.xml';
(:~
: The overall page function.
:)
declare function local:page()
as element()+
{
let $id-str := t:mandatory-field('id')
let $id := xs:unsignedLong($id-str)
let $group := a:get-group($id)
(: let $pkgs := a:appserver-get-packages($group) :)
return
(: if ( fn:empty($pkgs) ) then :)
p:when-no-repo('group', $group/a:name, $group/@id)
(: else
p:page-with-repo('group', $group/a:name, $group/@id, $pkgs) :)
};
v:console-page('../', 'pkg', 'Group', local:page#0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ cat src/appserver/repo-page.xql
xquery version "3.0";
module namespace p = "http://expath.org/ns/ml/console/repo-page";
import module namespace a = "http://expath.org/ns/ml/console/admin" at "../lib/admin.xql";
import module namespace t = "http://expath.org/ns/ml/console/tools" at "../lib/tools.xql";
import module namespace v = "http://expath.org/ns/ml/console/view" at "../lib/view.xql";
declare default element namespace "http://www.w3.org/1999/xhtml";
declare namespace pp = "http://expath.org/ns/repo/packages";
(: path relative to the AS :)
declare variable $packages-path := 'expath-repo/.expath-pkg/packages.xml';
(:~
: Implement the page when there is no repo setup fot the app server or group.
:)
declare function p:when-no-repo($kind as xs:string, $name as xs:string, $id as xs:string)
as element()+
{
<wrapper>
<p>The { $kind } "<code>{ $name }</code>" has no repo setup. In order to be
able to install packages for this { $kind }, you must first setup a repo.</p>
<p>Do you want to set one up?</p>
<form method="post" action="{ $id }/init-repo" enctype="multipart/form-data">
<button class="btn btn-default" type="submit">Initialize</button>
</form>
</wrapper>/*
};
(:~
: Implement the page when there is a repo setup fot the app server or group.
:)
declare function p:page-with-repo(
$kind as xs:string,
$name as xs:string,
$id as xs:string,
$pkgs as element(pp:packages)
) as element()+
{
<wrapper>
<p>Packages on the { $kind } "<code>{ $name }</code>".</p>
<h3>Installed packages</h3>
{
if ( fn:empty($pkgs/pp:package) ) then
<p>There is no package installed on this app server.</p>
else
p:package-table($pkgs, $id)
}
<h3>Install from file</h3>
<p>Install packages and applications from your filesystem, using a package
file (usually a *.xar file).</p>
{
v:form($id || '/install-pkg', (
v:input-file('xar', 'Package file'),
v:submit('Install')
(: v:input-checkbox('override', 'true', 'Override the package if it already exists') :) ))
}
<h3>Install from CXAN</h3>
<p>Install packages and applications directly from CXAN, using a package
name or a CXAN ID (one or the other), and optionally a version number
(retrieve the latest version by default).</p>
<p>The default CXAN website is <a href="http://cxan.org/">http://cxan.org/</a>.
If you are not sure, keep that one. If you want to use the development
CXAN website, you can use <a href="http://dev.cxan.org/">http://devcxan.org/</a>
instead.</p>
{
(: TODO: Next step: use an XSLT stylesheet, and generate XML instead of
calling functions to generate HTML... :)
v:form($id || '/install-cxan', (
v:input-text('pkg', 'ID', 'CXAN package ID...'),
v:input-text('name', 'Name', '...or package name'),
v:input-text('version', 'Version', 'Package version (latest by default)'),
v:submit('Install'),
v:input-select('std-website', 'Source website', (
v:input-option('prod', 'http://cxan.org/'),
v:input-option('dev', 'http://dev.cxan.org/'))),
v:input-text('other=website', 'Other source',
'Other specific CXAN website to use')))
}
<h3>Nuke the repo</h3>
<p>Delete the package repository that has been setup on this app server.</p>
{
v:form($id || '/delete-repo', v:submit('Delete'))
}
</wrapper>/*
};
(:~
: Build the package table for one app server or group.
:
: @param $pkg The packages element.
: @param $id The ID of the app server or group.
:)
declare %private function p:package-table($pkgs as element(pp:packages), $id as xs:string)
as element(table)
{
<table class="table table-striped">
<thead>
<th>Name</th>
<th>Dir</th>
<th>Version</th>
<th>Action</th>
</thead>
<tbody> {
for $p in $pkgs/pp:package
order by $p/fn:string(@dir)
return
p:package-row($p, $id)
}
</tbody>
</table>
};
(:~
: Build one row in the package table.
:
: @param $pkg One package element.
: @param $id The ID of the app server or group.
:)
declare %private function p:package-row($pkg as element(pp:package), $id as xs:string)
as element(tr)
{
<tr>
<td>{ $pkg/fn:string(@name) }</td>
<td>{ $pkg/fn:string(@dir) }</td>
<td>{ $pkg/fn:string(@version) }</td>
<td> {
v:inline-form($id || '/pkg/' || $pkg/fn:escape-html-uri(@dir) || '/delete',
v:submit('Delete'))
}
</td>
</tr>
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ git diff
diff --git a/src/appserver.xq b/src/appserver.xq
index 71c190f..c0671a2 100644
--- a/src/appserver.xq
+++ b/src/appserver.xq
@@ -1,8 +1,9 @@
xquery version "3.0";
-import module namespace a = "http://expath.org/ns/ml/console/admin" at "lib/admin.xql";
-import module namespace t = "http://expath.org/ns/ml/console/tools" at "lib/tools.xql";
-import module namespace v = "http://expath.org/ns/ml/console/view" at "lib/view.xql";
+import module namespace p = "http://expath.org/ns/ml/console/repo-page" at "appserver/repo-page.xql";
+import module namespace a = "http://expath.org/ns/ml/console/admin" at "lib/admin.xql";
+import module namespace t = "http://expath.org/ns/ml/console/tools" at "lib/tools.xql";
+import module namespace v = "http://expath.org/ns/ml/console/view" at "lib/view.xql";
declare default element namespace "http://www.w3.org/1999/xhtml";
@@ -12,92 +13,6 @@ declare namespace pp = "http://expath.org/ns/repo/packages";
declare variable $packages-path := 'expath-repo/.expath-pkg/packages.xml';
(:~
- : Implement the page when there is no repo setup fot the app server.
- :)
-declare function local:page-no-repo($as as element(a:appserver))
- as element()+
-{
- <wrapper>
- <p>The app server "<code>{ $as/a:name }</code>" has no repo setup. In
- order to be able to install packages for this app server, you must
- first setup a repo. Do you want to set one up?</p>
- <form method="post" action="{ $as/@id }/init-repo" enctype="multipart/form-data">
- <input type="submit" value="Initialize"/>
- <span> repo for this app server.</span>
- </form>
- </wrapper>/*
-};
-
-(:~
- : Implement the page when there is a repo setup fot the app server.
- :)
-declare function local:page-with-repo($as as element(a:appserver), $pkgs as element(pp:packages))
- as element()+
-{
- <wrapper>
- <p>Packages on the app server "<code>{ $as/a:name }</code>".</p>
- <h3>Installed packages</h3>
- {
- if ( fn:empty($pkgs/pp:package) ) then
- <p>There is no package installed on this app server.</p>
- else (
- <table class="table table-striped">
- <thead>
- <th>Name</th>
- <th>Dir</th>
- <th>Version</th>
- <th>Action</th>
- </thead>
- <tbody> {
- for $p in $pkgs/pp:package
- order by $p/fn:string(@dir)
- return
- local:package-row($p, $as)
- }
- </tbody>
- </table>
- )
- }
- <h3>Install from file</h3>
- <p>Install packages and applications from your filesystem, using a package
- file (usually a *.xar file).</p>
- {
- v:form($as/@id || '/install-pkg', (
- v:input-file('xar', 'Package file'),
- v:submit('Install')
- (: v:input-checkbox('override', 'true', 'Override the package if it already exists') :) ))
- }
- <h3>Install from CXAN</h3>
- <p>Install packages and applications directly from CXAN, using a package
- name or a CXAN ID (one or the other), and optionally a version number
- (retrieve the latest version by default).</p>
- <p>The default CXAN website is <a href="http://cxan.org/">http://cxan.org/</a>.
- If you are not sure, keep that one. If you want to use the development
- CXAN website, you can use <a href="http://dev.cxan.org/">http://devcxan.org/</a>
- instead.</p>
- {
- (: TODO: Next step: use an XSLT stylesheet, and generate XML instead of
- calling functions to generate HTML... :)
- v:form($as/@id || '/install-cxan', (
- v:input-text('pkg', 'ID', 'CXAN package ID...'),
- v:input-text('name', 'Name', '...or package name'),
- v:input-text('version', 'Version', 'Package version (latest by default)'),
- v:submit('Install'),
- v:input-select('std-website', 'Source website', (
- v:input-option('prod', 'http://cxan.org/'),
- v:input-option('dev', 'http://dev.cxan.org/'))),
- v:input-text('other=website', 'Other source',
- 'Other specific CXAN website to use')))
- }
- <h3>Nuke the repo</h3>
- <p>Delete the package repository that has been setup on this app server.</p>
- {
- v:form($as/@id || '/delete-repo', v:submit('Delete'))
- }
- </wrapper>/*
-};
-
-(:~
: The overall page function.
:)
declare function local:page()
@@ -109,24 +24,9 @@ declare function local:page()
let $pkgs := a:appserver-get-packages($as)
return
if ( fn:empty($pkgs) ) then
- local:page-no-repo($as)
+ p:when-no-repo('app server', $as/a:name, $as/@id)
else
- local:page-with-repo($as, $pkgs)
-};
-
-declare function local:package-row($pkg as element(pp:package), $as as element(a:appserver))
- as element(tr)
-{
- <tr>
- <td>{ $pkg/fn:string(@name) }</td>
- <td>{ $pkg/fn:string(@dir) }</td>
- <td>{ $pkg/fn:string(@version) }</td>
- <td> {
- v:inline-form($as/@id || '/pkg/' || $pkg/fn:escape-html-uri(@dir) || '/delete',
- v:submit('Delete'))
- }
- </td>
- </tr>
+ p:page-with-repo('app server', $as/a:name, $as/@id, $pkgs)
};
v:console-page('../', 'pkg', 'App server', local:page#0)
diff --git a/src/plumbing/rewriter.xml b/src/plumbing/rewriter.xml
index 159d813..51655cf 100644
--- a/src/plumbing/rewriter.xml
+++ b/src/plumbing/rewriter.xml
@@ -27,6 +27,14 @@
<add-query-param name="pkg">$2</add-query-param>
<dispatch>/appserver/delete-pkg.xq</dispatch>
</match-path>
+ <match-path matches="^/group/([0-9]+)$">
+ <add-query-param name="id">$1</add-query-param>
+ <dispatch>/group.xq</dispatch>
+ </match-path>
+ <match-path matches="^/group/([0-9]+)/init-repo$">
+ <add-query-param name="id">$1</add-query-param>
+ <dispatch>/group/init-repo.xq</dispatch>
+ </match-path>
<match-path matches="^/db/([0-9]+)/browse$">
<add-query-param name="id">$1</add-query-param>
<dispatch>/database/browse.xq</dispatch>
diff --git a/src/repo.xq b/src/repo.xq
index 44df246..016fe69 100644
--- a/src/repo.xq
+++ b/src/repo.xq
@@ -9,28 +9,32 @@ declare function local:page()
as element()+
{
let $groups := a:get-groups()/a:group
- let $count := fn:count($groups)
+ let $count := fn:count($groups)
return
- <wrapper>
- {
- if ( $count eq 0 ) then
- <p>There is no group in this MarkLogic instance. A bug, surely...</p>
- else if ( $count eq 1 ) then (
- <p>There is one single group in this MarkLogic instance:
- <code>{ $groups[1]/xs:string(a:name) }</code>.</p>,
+ <wrapper> {
+ if ( $count eq 0 ) then (
+ <p>There is no group in this MarkLogic instance. A bug, surely...</p>
+ )
+ else if ( $count eq 1 ) then (
+ <p>There is one single group in this MarkLogic instance:
+ <code>{ $groups/xs:string(a:name) }</code>.</p>,
+ <p>Go to the <a href="group/{ $groups/xs:string(@id) }">group page</a>
+ to install packages at the group level itself.</p>,
+ <p>The app servers in the group are:</p>,
+ local:appservers-table($groups)
+ )
+ else (
+ <p>There are { $count } groups in this MarkLogic instance.</p>,
+ for $g in $groups
+ return (
+ <h4>Group <code>{ $g/a:name }</code></h4>,
+ <p>Go to the <a href="group/{ $g/xs:string(@id) }">group page</a>
+ to install packages at the group level itself.</p>,
<p>The app servers in the group are:</p>,
- local:appservers-table($groups)
+ local:appservers-table($g)
)
- else (
- <p>There are { $count } groups in this MarkLogic instance.</p>,
- for $g in $groups
- return (
- <h4>Group <code>{ $g/a:name }</code></h4>,
- <p>The app servers in the group are:</p>,
- local:appservers-table($g)
- )
- )
- }
+ )
+ }
</wrapper>/*
};
I tried to install the console on my new Developer licensed ML server:
After pressing the button at http://localhost:8010/init there is a:
500 Internal Server Error
JS-JAVASCRIPT: xdmp.dir(resp); -- Error running JavaScript request: TypeError: xdmp.dir is not a function
in /init/do-init.sjs, at 19:13, in get() [javascript]
in /init/do-init.sjs, at 128:16 [javascript]
in /init/do-init.sjs [javascript]
I am on a 18GB memory running Windows Server 2012 R2 Datacenter
with MarkLogic Server 9.0-8.2 amd64 (normally I would use Linux)
When displaying a document in the Browser, the collections it is part of are displayed, in a bullet-list kind of way.
It would be handy to be able to add the document to existing collections, as well as to new collections. And to remove it from collections it is part of.
Suggested by Mijneer Peter Kester.
We receive a 404 when calling the first URL:
http://localhost:8010/db/Name.Test
http://localhost:8010/db/Name-Test
Since our naming convention is project.subproject most of our databases cannot be viewed with the EXPath Console Database view. Thanks a lot for your help and keep up the good work.
Steps to reproduce:
I would expect the permissions to be unchanged, but it looks like they're getting clobbered by the admin's default permissions (which are none).
Tested on current master branch, safari, ml 9.0-1.1. Observed earlier on ml8 as well.
Add some tools in order to gather some security-related information about a module. Of course, this is a sharp tool one would have to use carefully, but it would be a convenient way to investigate some issue (or at least to provide someone with some context about it).
Here is some pseudo-code (pseudo because there are some calls which should be done against different databases and they are not resolved properly, but the idea is there), some pseudo-code to retrieve the names (and the IDs) of the roles associated to a module. Add the relevant databases IDs and names as well to the "report" (the user should be able to chose between XML and HTML):
import module namespace sec="http://marklogic.com/xdmp/security"
at "/MarkLogic/security.xqy";
declare variable $modules-db-name := 'SCS-modules';
declare variable $module-uri := '/app/controllers/appbuilder.xqy';
declare function local:get-permissions($uri as xs:string, $db-name as xs:string) as element(sec:permission)*
{
(: TODO: To be executed against database $db-name :)
xdmp:document-get-permissions($uri)
};
(: TODO: Instead of returning a bunch of strings, return structured info in an element. :)
(: TODO: Also, pass all role IDs at once, and get all the relevant info from one call
against the security database. :)
declare function local:get-roles-names($perms as element(sec:permission)*)
{
for $p in $perms
return
(: TODO: To be executed against the security database of database $db-name :)
$p/sec:get-role-names(sec:role-id)
};
(: TODO: Return pairs of ID/name instead. :)
declare function local:get-module-roles($uri as xs:string, $db-name as xs:string)
{
local:get-roles-names(
local:get-permissions($uri, $db-name))
};
local:get-module-roles($module-uri, $modules-db-name)
Just acquired the domain name http://mlconsole.org/ for it. Create it and put it online.
Hi,
I think it would make a nice addition to this great tool to be able to add/edit or delete things like collections, quality and properties in the browser tool.
Would be nice to be able to deploy and get it to run easily.
Do you have any plans or guidance for passing the database password to the get(url)
function in do-init.sjs
? We would like to upgrade our console installations, but we will not be able to hard code the username and password in that function because they vary between systems.
I have many documents that do not begin with a leading slash as part of other URI naming conventions. It would be very convenient to be able to use the Browser tool to view and edit these documents as well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.