From 321efa1b363a1cd5f9fd714cd4945778fa55c0e9 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 1 May 2021 10:06:29 +0200 Subject: [PATCH] Add People and Map to the default layers. --- core/org.argeo.suite.ui/OSGI-INF/leadPane.xml | 2 + environment/org.argeo.geo.ui/.project | 5 + .../org.argeo.geo.ui/OSGI-INF/mapLayer.xml | 9 + .../org.argeo.geo.ui/OSGI-INF/overviewMap.xml | 8 + environment/org.argeo.geo.ui/bnd.bnd | 4 + .../config/mapLayer.properties | 4 + .../config/overviewMap.properties | 1 + .../argeo/support/openlayers/OverviewMap.java | 72 +++++++ .../org/argeo/support/openlayers/map-osm.html | 41 ++++ people/org.argeo.people.ui/.project | 5 + .../OSGI-INF/peopleEntryArea.xml | 9 + .../OSGI-INF/peopleLayer.xml | 9 + .../OSGI-INF/personUiProvider.xml | 16 ++ people/org.argeo.people.ui/bnd.bnd | 6 + .../config/peopleEntryArea.properties | 1 + .../config/peopleLayer.properties | 7 + .../config/personUiProvider.properties | 3 + .../org/argeo/people/ui/PeopleEntryArea.java | 184 ++++++++++++++++++ .../org/argeo/people/ui/PersonUiProvider.java | 88 +++++++++ sdk/argeo-suite-rap.properties | 5 +- 20 files changed, 478 insertions(+), 1 deletion(-) create mode 100644 environment/org.argeo.geo.ui/OSGI-INF/mapLayer.xml create mode 100644 environment/org.argeo.geo.ui/OSGI-INF/overviewMap.xml create mode 100644 environment/org.argeo.geo.ui/config/mapLayer.properties create mode 100644 environment/org.argeo.geo.ui/config/overviewMap.properties create mode 100644 environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OverviewMap.java create mode 100644 environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/map-osm.html create mode 100644 people/org.argeo.people.ui/OSGI-INF/peopleEntryArea.xml create mode 100644 people/org.argeo.people.ui/OSGI-INF/peopleLayer.xml create mode 100644 people/org.argeo.people.ui/OSGI-INF/personUiProvider.xml create mode 100644 people/org.argeo.people.ui/config/peopleEntryArea.properties create mode 100644 people/org.argeo.people.ui/config/peopleLayer.properties create mode 100644 people/org.argeo.people.ui/config/personUiProvider.properties create mode 100644 people/org.argeo.people.ui/src/org/argeo/people/ui/PeopleEntryArea.java create mode 100644 people/org.argeo.people.ui/src/org/argeo/people/ui/PersonUiProvider.java diff --git a/core/org.argeo.suite.ui/OSGI-INF/leadPane.xml b/core/org.argeo.suite.ui/OSGI-INF/leadPane.xml index 0775c57..1aeec0a 100644 --- a/core/org.argeo.suite.ui/OSGI-INF/leadPane.xml +++ b/core/org.argeo.suite.ui/OSGI-INF/leadPane.xml @@ -7,6 +7,8 @@ argeo.suite.ui.dashboardLayer argeo.documents.ui.documentsLayer +argeo.people.ui.peopleLayer +argeo.geo.ui.mapLayer diff --git a/environment/org.argeo.geo.ui/.project b/environment/org.argeo.geo.ui/.project index 7956c34..a25e06f 100644 --- a/environment/org.argeo.geo.ui/.project +++ b/environment/org.argeo.geo.ui/.project @@ -20,6 +20,11 @@ + + org.eclipse.pde.ds.core.builder + + + org.eclipse.pde.PluginNature diff --git a/environment/org.argeo.geo.ui/OSGI-INF/mapLayer.xml b/environment/org.argeo.geo.ui/OSGI-INF/mapLayer.xml new file mode 100644 index 0000000..7cf8487 --- /dev/null +++ b/environment/org.argeo.geo.ui/OSGI-INF/mapLayer.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/environment/org.argeo.geo.ui/OSGI-INF/overviewMap.xml b/environment/org.argeo.geo.ui/OSGI-INF/overviewMap.xml new file mode 100644 index 0000000..c75200a --- /dev/null +++ b/environment/org.argeo.geo.ui/OSGI-INF/overviewMap.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/environment/org.argeo.geo.ui/bnd.bnd b/environment/org.argeo.geo.ui/bnd.bnd index 9a3ff7b..a50ed43 100644 --- a/environment/org.argeo.geo.ui/bnd.bnd +++ b/environment/org.argeo.geo.ui/bnd.bnd @@ -8,3 +8,7 @@ org.eclipse.swt,\ org.eclipse.jface.viewers,\ org.osgi.framework,\ * + +Service-Component:\ +OSGI-INF/mapLayer.xml,\ +OSGI-INF/overviewMap.xml diff --git a/environment/org.argeo.geo.ui/config/mapLayer.properties b/environment/org.argeo.geo.ui/config/mapLayer.properties new file mode 100644 index 0000000..2931c2d --- /dev/null +++ b/environment/org.argeo.geo.ui/config/mapLayer.properties @@ -0,0 +1,4 @@ +service.pid=argeo.geo.ui.mapLayer + +title=%map +icon=map \ No newline at end of file diff --git a/environment/org.argeo.geo.ui/config/overviewMap.properties b/environment/org.argeo.geo.ui/config/overviewMap.properties new file mode 100644 index 0000000..d842c98 --- /dev/null +++ b/environment/org.argeo.geo.ui/config/overviewMap.properties @@ -0,0 +1 @@ +service.pid=argeo.geo.ui.overviewMap diff --git a/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OverviewMap.java b/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OverviewMap.java new file mode 100644 index 0000000..33e888f --- /dev/null +++ b/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OverviewMap.java @@ -0,0 +1,72 @@ +package org.argeo.support.openlayers; + +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; +import javax.jcr.query.Query; + +import org.argeo.api.NodeConstants; +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.entity.EntityType; +import org.argeo.jcr.JcrException; +import org.argeo.jcr.JcrUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** Displays an overview map. */ +public class OverviewMap implements CmsUiProvider { + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + parent.setLayout(new GridLayout()); + refreshUi(parent, context); + + try { + String[] nodeTypes = { EntityType.geopoint.get() }; + context.getSession().getWorkspace().getObservationManager().addEventListener(new EventListener() { + + @Override + public void onEvent(EventIterator events) { + if (!parent.isDisposed()) + parent.getDisplay().asyncExec(() -> { + try { + refreshUi(parent, context); + } catch (RepositoryException e) { + throw new JcrException(e); + } + }); + } + }, Event.PROPERTY_CHANGED | Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED, + "/", true, null, nodeTypes, false); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot add JCR observer", e); + } + + return parent; + } + + protected void refreshUi(Composite parent, Node context) throws RepositoryException { + CmsUiUtils.clear(parent); + boolean coworker = CmsView.getCmsView(parent).doAs(() -> CurrentUser.isInRole(NodeConstants.ROLE_USER_ADMIN)); + Query query = context.getSession().getWorkspace().getQueryManager() + .createQuery("SELECT * FROM [" + EntityType.local.get() + "] WHERE [entity:type]='" + + EntityType.geopoint.get() + "'", + Query.JCR_SQL2); + List geoPoints = JcrUtils.nodeIteratorToList(query.execute().getNodes()); + OpenLayersMap apafMap = new OpenLayersMap(parent, SWT.NONE, getClass().getResource("map-osm.html")); + apafMap.setLayoutData(CmsUiUtils.fillAll()); + + // apafMap.setZoom(7); + // apafMap.setCenter(-2.472, 8.010); + apafMap.addPoints(geoPoints); + } +} diff --git a/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/map-osm.html b/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/map-osm.html new file mode 100644 index 0000000..157d708 --- /dev/null +++ b/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/map-osm.html @@ -0,0 +1,41 @@ + + + + + + + +
+ + + \ No newline at end of file diff --git a/people/org.argeo.people.ui/.project b/people/org.argeo.people.ui/.project index 1df2bce..b3d17df 100644 --- a/people/org.argeo.people.ui/.project +++ b/people/org.argeo.people.ui/.project @@ -20,6 +20,11 @@ + + org.eclipse.pde.ds.core.builder + + + org.eclipse.pde.PluginNature diff --git a/people/org.argeo.people.ui/OSGI-INF/peopleEntryArea.xml b/people/org.argeo.people.ui/OSGI-INF/peopleEntryArea.xml new file mode 100644 index 0000000..9601294 --- /dev/null +++ b/people/org.argeo.people.ui/OSGI-INF/peopleEntryArea.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/people/org.argeo.people.ui/OSGI-INF/peopleLayer.xml b/people/org.argeo.people.ui/OSGI-INF/peopleLayer.xml new file mode 100644 index 0000000..09392aa --- /dev/null +++ b/people/org.argeo.people.ui/OSGI-INF/peopleLayer.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/people/org.argeo.people.ui/OSGI-INF/personUiProvider.xml b/people/org.argeo.people.ui/OSGI-INF/personUiProvider.xml new file mode 100644 index 0000000..f727bf8 --- /dev/null +++ b/people/org.argeo.people.ui/OSGI-INF/personUiProvider.xml @@ -0,0 +1,16 @@ + + + + + + + + +cn=APAF Internationale,ou=Groups,dc=apaf,dc=on,dc=djapps,dc=org +cn=APAF Côte d'Ivoire Admin,ou=Groups,dc=apaf,dc=on,dc=djapps,dc=org +cn=APAF Côte d'Ivoire,ou=Groups,dc=apaf,dc=on,dc=djapps,dc=org +cn=APAF Togo Admin,ou=Groups,dc=apaf,dc=on,dc=djapps,dc=org +cn=APAF Togo,ou=Groups,dc=apaf,dc=on,dc=djapps,dc=org + + + diff --git a/people/org.argeo.people.ui/bnd.bnd b/people/org.argeo.people.ui/bnd.bnd index 50f4364..1b92ebb 100644 --- a/people/org.argeo.people.ui/bnd.bnd +++ b/people/org.argeo.people.ui/bnd.bnd @@ -8,3 +8,9 @@ org.eclipse.jface.viewers,\ org.eclipse.jface.window,\ org.osgi.framework,\ * + +Service-Component:\ +OSGI-INF/peopleLayer.xml,\ +OSGI-INF/personUiProvider.xml,\ +OSGI-INF/peopleEntryArea.xml + diff --git a/people/org.argeo.people.ui/config/peopleEntryArea.properties b/people/org.argeo.people.ui/config/peopleEntryArea.properties new file mode 100644 index 0000000..37b28f9 --- /dev/null +++ b/people/org.argeo.people.ui/config/peopleEntryArea.properties @@ -0,0 +1 @@ +service.pid=argeo.people.ui.peopleEntryArea diff --git a/people/org.argeo.people.ui/config/peopleLayer.properties b/people/org.argeo.people.ui/config/peopleLayer.properties new file mode 100644 index 0000000..adadb7b --- /dev/null +++ b/people/org.argeo.people.ui/config/peopleLayer.properties @@ -0,0 +1,7 @@ +service.pid=argeo.people.ui.peopleLayer + +icon=people +weights=5000,5000 +title=%people + +entity.type=entity:person \ No newline at end of file diff --git a/people/org.argeo.people.ui/config/personUiProvider.properties b/people/org.argeo.people.ui/config/personUiProvider.properties new file mode 100644 index 0000000..8c40c7d --- /dev/null +++ b/people/org.argeo.people.ui/config/personUiProvider.properties @@ -0,0 +1,3 @@ +service.pid=argeo.people.ui.personUiProvider + +entity.type=entity:person \ No newline at end of file diff --git a/people/org.argeo.people.ui/src/org/argeo/people/ui/PeopleEntryArea.java b/people/org.argeo.people.ui/src/org/argeo/people/ui/PeopleEntryArea.java new file mode 100644 index 0000000..2fd38da --- /dev/null +++ b/people/org.argeo.people.ui/src/org/argeo/people/ui/PeopleEntryArea.java @@ -0,0 +1,184 @@ +package org.argeo.people.ui; + +import java.util.Set; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.dialogs.CmsWizardDialog; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.eclipse.ui.Selected; +import org.argeo.naming.LdapAttrs; +import org.argeo.suite.SuiteRole; +import org.argeo.suite.ui.SuiteEvent; +import org.argeo.suite.ui.SuiteIcon; +import org.argeo.suite.ui.dialogs.NewUserWizard; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; +import org.osgi.service.useradmin.User; + +/** Entry to the admin area. */ +public class PeopleEntryArea implements CmsUiProvider { + + private CmsUserManager cmsUserManager; + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + CmsTheme theme = CmsTheme.getCmsTheme(parent); + parent.setLayout(new GridLayout()); + TableViewer usersViewer = new TableViewer(parent); + usersViewer.setContentProvider(new UsersContentProvider()); + + TableViewerColumn idCol = new TableViewerColumn(usersViewer, SWT.NONE); + idCol.getColumn().setWidth(70); + idCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.uid.name()); + } + }); + + TableViewerColumn givenNameCol = new TableViewerColumn(usersViewer, SWT.NONE); + givenNameCol.getColumn().setWidth(150); + givenNameCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.givenName.name()); + } + }); + + TableViewerColumn snCol = new TableViewerColumn(usersViewer, SWT.NONE); + snCol.getColumn().setWidth(150); + snCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.sn.name()); + } + }); + + TableViewerColumn mailCol = new TableViewerColumn(usersViewer, SWT.NONE); + mailCol.getColumn().setWidth(400); + mailCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.mail.name()); + } + }); + + Composite bottom = new Composite(parent, SWT.NONE); + bottom.setLayoutData(CmsUiUtils.fillWidth()); + bottom.setLayout(CmsUiUtils.noSpaceGridLayout()); + ToolBar bottomToolBar = new ToolBar(bottom, SWT.NONE); + bottomToolBar.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); + ToolItem deleteItem = new ToolItem(bottomToolBar, SWT.FLAT); + deleteItem.setEnabled(false); +// CmsUiUtils.style(deleteItem, SuiteStyle.recentItems); + deleteItem.setImage(SuiteIcon.delete.getSmallIcon(theme)); + ToolItem addItem = new ToolItem(bottomToolBar, SWT.FLAT); + addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); + usersViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + User user = (User) usersViewer.getStructuredSelection().getFirstElement(); + if (user != null) { +// Node userNode = getOrCreateUserNode(user, context); + CmsView.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), + SuiteEvent.eventProperties(user)); + } + + } + }); + usersViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + User user = (User) usersViewer.getStructuredSelection().getFirstElement(); + if (user != null) { +// Node userNode = getOrCreateUserNode(user, context); + CmsView.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), + SuiteEvent.eventProperties(user)); + deleteItem.setEnabled(true); + } else { + deleteItem.setEnabled(false); + } + } + }); + + addItem.addSelectionListener((Selected) (e) -> { + // SuiteUtils.getOrCreateUserNode(adminSession, userDn); + Wizard wizard = new NewUserWizard(null); + CmsWizardDialog dialog = new CmsWizardDialog(parent.getShell(), wizard); + // WizardDialog dialog = new WizardDialog(shell, wizard); + if (dialog.open() == Window.OK) { + // TODO create + } + }); + + usersViewer.getTable().setLayoutData(CmsUiUtils.fillAll()); + usersViewer.setInput(cmsUserManager); + + return usersViewer.getTable(); + } + +// private Node getOrCreateUserNode(User user, Node context) { +// return JcrUtils.mkdirs(Jcr.getSession(context), +// "/" + EntityType.user.name() + "/" + getUserProperty(user, LdapAttrs.uid.name()), +// EntityType.user.get()); +// } + + private String getUserProperty(Object element, String key) { + Object value = ((User) element).getProperties().get(key); + return value != null ? value.toString() : null; + } + + class UsersContentProvider implements IStructuredContentProvider { + + @Override + public Object[] getElements(Object inputElement) { + CmsUserManager cum = (CmsUserManager) inputElement; + Set users = cum.listUsersInGroup(SuiteRole.coworker.dn(), null); + return users.toArray(); + } + + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + +} diff --git a/people/org.argeo.people.ui/src/org/argeo/people/ui/PersonUiProvider.java b/people/org.argeo.people.ui/src/org/argeo/people/ui/PersonUiProvider.java new file mode 100644 index 0000000..d2ea2fe --- /dev/null +++ b/people/org.argeo.people.ui/src/org/argeo/people/ui/PersonUiProvider.java @@ -0,0 +1,88 @@ +package org.argeo.people.ui; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.cms.ui.viewers.Section; +import org.argeo.naming.LdapAttrs; +import org.argeo.suite.ui.SuiteMsg; +import org.argeo.suite.ui.SuiteUiUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Text; +import org.osgi.service.useradmin.User; + +/** Edit a suite user. */ +public class PersonUiProvider implements CmsUiProvider { + private String[] availableRoles; + private CmsUserManager cmsUserManager; + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + Section main = new Section(parent, SWT.NONE, context); + main.setLayoutData(CmsUiUtils.fillAll()); + + String uid = context.getName(); + User user = cmsUserManager.getUserFromLocalId(uid); + +// Text givenName = new Text(main, SWT.SINGLE); +// givenName.setText(getUserProperty(user, LdapAttrs.givenName.name())); + Text givenName = SuiteUiUtils.addFormInput(main, SuiteMsg.firstName.lead(), + getUserProperty(user, LdapAttrs.givenName.name())); + + Text sn = SuiteUiUtils.addFormInput(main, SuiteMsg.lastName.lead(), getUserProperty(user, LdapAttrs.sn.name())); + // sn.setText(getUserProperty(user, LdapAttrs.sn.name())); + + Text email = SuiteUiUtils.addFormInput(main, SuiteMsg.email.lead(), + getUserProperty(user, LdapAttrs.mail.name())); + // email.setText(getUserProperty(user, LdapAttrs.mail.name())); + + Text uidT = SuiteUiUtils.addFormLine(main, "uid", getUserProperty(user, LdapAttrs.uid.name())); + uidT.setText(uid); + +// Label dnL = new Label(main, SWT.NONE); +// dnL.setText(user.getName()); + + // roles + // Section rolesSection = new Section(main, SWT.NONE, context); + Group rolesSection = new Group(main, SWT.NONE); + rolesSection.setText("Roles"); + rolesSection.setLayoutData(CmsUiUtils.fillWidth()); + rolesSection.setLayout(new GridLayout()); + // new Label(rolesSection, SWT.NONE).setText("Roles:"); + List roles = Arrays.asList(cmsUserManager.getUserRoles(user.getName())); + for (String role : availableRoles) { + // new Label(rolesSection, SWT.NONE).setText(role); + Button radio = new Button(rolesSection, SWT.CHECK); + radio.setText(role); + if (roles.contains(role)) + radio.setSelection(true); + } + + return main; + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + + private String getUserProperty(Object element, String key) { + Object value = ((User) element).getProperties().get(key); + return value != null ? value.toString() : null; + } + + public void init(Map properties) { + availableRoles = (String[]) properties.get("availableRoles"); + } +} diff --git a/sdk/argeo-suite-rap.properties b/sdk/argeo-suite-rap.properties index b9981f9..60f0b9b 100644 --- a/sdk/argeo-suite-rap.properties +++ b/sdk/argeo-suite-rap.properties @@ -17,7 +17,10 @@ org.argeo.suite.theme.default,\ org.argeo.suite.ui.rap argeo.osgi.start.6.suite=\ -org.argeo.documents.ui +org.argeo.documents.ui,\ +org.argeo.people.ui,\ +org.argeo.geo.ui + # Local argeo.node.repo.type=h2 -- 2.30.2