From e1977b4ab6eec9eac80a92eb660c91c34c61ba19 Mon Sep 17 00:00:00 2001
From: Nihadness <1992.nihad@gmail.com>
Date: Wed, 2 May 2018 11:59:58 +0200
Subject: [PATCH 01/28] Rename a column in the Souper: 'path' -->
'remote_path'.
---
src/senaite/sync/complementstep.py | 9 ++---
src/senaite/sync/importstep.py | 56 ++++++++++++++++--------------
src/senaite/sync/souphandler.py | 39 +++++++++++++--------
src/senaite/sync/syncstep.py | 3 +-
src/senaite/sync/utils.py | 7 ++--
5 files changed, 64 insertions(+), 50 deletions(-)
diff --git a/src/senaite/sync/complementstep.py b/src/senaite/sync/complementstep.py
index 6527cc4..0d531bf 100644
--- a/src/senaite/sync/complementstep.py
+++ b/src/senaite/sync/complementstep.py
@@ -9,7 +9,8 @@
from senaite.sync.importstep import ImportStep
from senaite.sync import logger, utils
-from senaite.sync.souphandler import SoupHandler, REMOTE_UID, LOCAL_UID
+from senaite.sync.souphandler import SoupHandler, REMOTE_UID, LOCAL_UID, \
+ REMOTE_PATH
class ComplementStep(ImportStep):
@@ -82,8 +83,8 @@ def _fetch_data(self):
# If remote UID is in the souper table already, just check if
# remote path of the object has been updated
if existing_rec:
- rem_path = data_dict.get('path')
- if rem_path != existing_rec.get('path'):
+ rem_path = data_dict.get(REMOTE_PATH)
+ if rem_path != existing_rec.get(REMOTE_PATH):
self.sh.update_by_remote_uid(**data_dict)
rec_id = existing_rec.get("rec_int_id")
else:
@@ -122,7 +123,7 @@ def _update_objects(self):
row = self.sh.get_record_by_id(rec_id, as_dict=True)
if not row:
continue
- logger.debug("Handling: {} ".format(row["path"]))
+ logger.debug("Handling: {} ".format(row[REMOTE_PATH]))
self._handle_obj(row, handle_dependencies=False)
# Log.info every 50 objects imported
diff --git a/src/senaite/sync/importstep.py b/src/senaite/sync/importstep.py
index 2761109..8d31cef 100644
--- a/src/senaite/sync/importstep.py
+++ b/src/senaite/sync/importstep.py
@@ -25,7 +25,8 @@
from senaite.sync import logger
from senaite.sync import _
from senaite.sync.souphandler import SoupHandler
-from senaite.sync.souphandler import REMOTE_UID, LOCAL_UID, PORTAL_TYPE
+from senaite.sync.souphandler import REMOTE_UID, LOCAL_UID, REMOTE_PATH,\
+ PORTAL_TYPE
from senaite.sync import utils
COMMIT_INTERVAL = 1000
@@ -212,7 +213,7 @@ def _import_data(self):
for item_index, r_uid in enumerate(ordered_uids):
row = self.sh.find_unique(REMOTE_UID, r_uid)
- logger.debug("Handling: {} ".format(row["path"]))
+ logger.debug("Handling: {} ".format(row[REMOTE_PATH]))
self._handle_obj(row)
# Handling object means there is a chunk containing several objects
@@ -297,47 +298,48 @@ def _do_obj_creation(self, row):
:param row: A row dictionary from the souper
:type row: dict
"""
- path = row.get("path")
+ remote_path = row.get(REMOTE_PATH)
- remote_parent_path = utils.get_parent_path(path)
+ remote_parent_path = utils.get_parent_path(remote_path)
# If parent creation failed previously, do not try to create the object
if remote_parent_path in self.skipped:
logger.warning("Parent creation failed previously, skipping: {}"
- .format(path))
+ .format(remote_path))
return None
- existing = self.portal.unrestrictedTraverse(self.translate_path(path),
+ existing = self.portal.unrestrictedTraverse(self.translate_path(remote_path),
None)
if existing:
- local_uid = self.sh.find_unique("path", path).get(LOCAL_UID,
+ local_uid = self.sh.find_unique(REMOTE_PATH, remote_path).get(LOCAL_UID,
None)
if not local_uid:
local_uid = api.get_uid(existing)
- self.sh.update_by_path(path, local_uid=local_uid)
+ self.sh.update_by_remote_path(remote_path, local_uid=local_uid)
return existing
- if not self._parents_created(path):
- logger.warning("Parent creation failed, skipping: {}".format(path))
+ if not self._parents_created(remote_path):
+ logger.warning("Parent creation failed, skipping: {}".format(
+ remote_path))
return None
- parent = self.translate_path(utils.get_parent_path(path))
+ parent = self.translate_path(utils.get_parent_path(remote_path))
container = self.portal.unrestrictedTraverse(str(parent), None)
obj_data = {
- "id": utils.get_id_from_path(path),
+ "id": utils.get_id_from_path(remote_path),
"portal_type": row.get(PORTAL_TYPE)}
obj = self._create_object_slug(container, obj_data)
if obj is not None:
local_uid = api.get_uid(obj)
- self.sh.update_by_path(path, local_uid=local_uid)
+ self.sh.update_by_remote_path(remote_path, local_uid=local_uid)
return obj
- def _parents_created(self, path):
+ def _parents_created(self, remote_path):
""" Check if parents have been already created and create all non-existing
parents and updates local UIDs for the existing ones.
:param path: object path in the remote
:return: True if ALL the parents were created successfully
"""
- p_path = utils.get_parent_path(path)
+ p_path = utils.get_parent_path(remote_path)
if p_path == "/":
return True
@@ -346,42 +348,42 @@ def _parents_created(self, path):
return True
# Incoming path was remote path, translate it into local one
- local_path = self.translate_path(p_path)
+ local_p_path = self.translate_path(p_path)
# Check if the parent already exists. If yes, make sure it has
# 'local_uid' value set in the soup table.
- existing = self.portal.unrestrictedTraverse(local_path, None)
+ existing = self.portal.unrestrictedTraverse(local_p_path, None)
if existing:
- p_row = self.sh.find_unique("path", p_path)
+ p_row = self.sh.find_unique(REMOTE_PATH, p_path)
if p_row is None:
+ # This should never happen
return False
- p_local_uid = self.sh.find_unique("path", p_path).get(
- LOCAL_UID, None)
+ p_local_uid = p_row.get(LOCAL_UID, None)
if not p_local_uid:
if hasattr(existing, "UID") and existing.UID():
p_local_uid = existing.UID()
- self.sh.update_by_path(p_path, local_uid=p_local_uid)
+ self.sh.update_by_remote_path(p_path, local_uid=p_local_uid)
return True
# Before creating an object's parent, make sure grand parents are
# already ready.
if not self._parents_created(p_path):
return False
- parent = self.sh.find_unique("path", p_path)
+ parent = self.sh.find_unique(REMOTE_PATH, p_path)
grand_parent = self.translate_path(utils.get_parent_path(p_path))
container = self.portal.unrestrictedTraverse(str(grand_parent), None)
parent_data = {
"id": utils.get_id_from_path(p_path),
- "path": p_path,
+ "remote_path": p_path,
"portal_type": parent.get(PORTAL_TYPE)}
parent_obj = self._create_object_slug(container, parent_data)
if parent_obj is None:
- logger.warning("Couldn't create parent of {}".format(path))
+ logger.warning("Couldn't create parent of {}".format(remote_path))
return False
# Parent is created, update it in the soup table.
p_local_uid = api.get_uid(parent_obj)
- self.sh.update_by_path(p_path, local_uid=p_local_uid)
+ self.sh.update_by_remote_path(p_path, local_uid=p_local_uid)
return True
def _create_dependencies(self, obj, data):
@@ -537,7 +539,7 @@ def _create_object_slug(self, container, data, *args, **kwargs):
"""Create an content object slug for the given data
"""
id = data.get("id")
- remote_path = data.get("path")
+ remote_path = data.get("remote_path")
portal_type = data.get("portal_type")
types_tool = api.get_tool("portal_types")
fti = types_tool.getTypeInfo(portal_type)
@@ -615,7 +617,7 @@ def _recover_failed_objects(self):
if existing is None:
continue
logger.info('Recovering {0}/{1} : {2} '.format(
- idx+1, total, existing["path"]))
+ idx+1, total, existing[REMOTE_PATH]))
# Mark that update failed previously
existing['updated'] = '0'
self._handle_obj(existing, handle_dependencies=False)
diff --git a/src/senaite/sync/souphandler.py b/src/senaite/sync/souphandler.py
index 4adeee2..c3117af 100644
--- a/src/senaite/sync/souphandler.py
+++ b/src/senaite/sync/souphandler.py
@@ -1,5 +1,4 @@
-
from senaite import api
from senaite.sync import logger
@@ -66,9 +65,10 @@ def insert(self, data):
return False
record = Record()
record.attrs[REMOTE_UID] = data[REMOTE_UID]
- record.attrs['path'] = data['path']
- record.attrs[PORTAL_TYPE] = data[PORTAL_TYPE]
record.attrs[LOCAL_UID] = data.get(LOCAL_UID, "")
+ record.attrs[REMOTE_PATH] = data[REMOTE_PATH]
+ record.attrs[LOCAL_PATH] = data[LOCAL_PATH]
+ record.attrs[PORTAL_TYPE] = data[PORTAL_TYPE]
record.attrs[UPDATED] = data.get(UPDATED, "0")
r_id = self.soup.add(record)
logger.info("Record {} inserted: {}".format(r_id, data))
@@ -82,11 +82,13 @@ def _already_exists(self, data):
"""
r_uid = data.get(REMOTE_UID, False) or '-1'
l_uid = data.get(LOCAL_UID, False) or '-1'
- path = data.get("path", False) or '-1'
+ r_path = data.get(REMOTE_PATH, False) or '-1'
+ l_path = data.get(LOCAL_PATH, False) or '-1'
r_uid_q = Eq(REMOTE_UID, r_uid)
l_uid_q = Eq(LOCAL_UID, l_uid)
- p_q = Eq('path', path)
- ret = [r for r in self.soup.query(Or(r_uid_q, l_uid_q, p_q))]
+ r_p_q = Eq(REMOTE_PATH, r_path)
+ l_p_q = Eq(REMOTE_PATH, l_path)
+ ret = [r for r in self.soup.query(Or(r_uid_q, l_uid_q, r_p_q, l_p_q))]
return ret != []
def get_record_by_id(self, rec_id, as_dict=False):
@@ -137,16 +139,16 @@ def update_by_remote_uid(self, remote_uid, **kwargs):
self.soup.reindex([recs[0]])
return True
- def update_by_path(self, path, **kwargs):
+ def update_by_remote_path(self, remote_path, **kwargs):
"""
Update the row by path column.
:param path: path of the record
:param kwargs: columns and their values to be updated.
"""
- recs = [r for r in self.soup.query(Eq('path', path))]
+ recs = [r for r in self.soup.query(Eq(REMOTE_PATH, remote_path))]
if not recs:
logger.error("Could not find any record with path: '{}'"
- .format(path))
+ .format(REMOTE_PATH))
return False
for k, v in kwargs.iteritems():
recs[0].attrs[k] = v
@@ -174,7 +176,7 @@ def reset_updated_flags(self):
for intid in self.soup.data:
rec = self.soup.get(intid)
rec.attrs[UPDATED] = "0"
- self.soup.reindex(rec)
+ self.soup.reindex()
return True
def _create_domain_catalog(self):
@@ -187,11 +189,17 @@ class DomainSoupCatalogFactory(object):
def __call__(self, context=None):
catalog = Catalog()
r_uid_indexer = NodeAttributeIndexer(REMOTE_UID)
- catalog[u'remote_uid'] = CatalogFieldIndex(r_uid_indexer)
- path_indexer = NodeAttributeIndexer('path')
- catalog[u'path'] = CatalogFieldIndex(path_indexer)
+ catalog[unicode(REMOTE_UID)] = CatalogFieldIndex(r_uid_indexer)
+
l_uid_indexer = NodeAttributeIndexer(LOCAL_UID)
- catalog[u'local_uid'] = CatalogFieldIndex(l_uid_indexer)
+ catalog[unicode(LOCAL_UID)] = CatalogFieldIndex(l_uid_indexer)
+
+ r_path_indexer = NodeAttributeIndexer(REMOTE_PATH)
+ catalog[unicode(REMOTE_PATH)] = CatalogFieldIndex(r_path_indexer)
+
+ l_path_indexer = NodeAttributeIndexer(LOCAL_PATH)
+ catalog[unicode(LOCAL_PATH)] = CatalogFieldIndex(l_path_indexer)
+
return catalog
provideUtility(DomainSoupCatalogFactory(), name=self.domain_name)
@@ -226,7 +234,8 @@ def record_to_dict(record):
'rec_int_id': record.intid,
REMOTE_UID: record.attrs.get(REMOTE_UID, ""),
LOCAL_UID: record.attrs.get(LOCAL_UID, ""),
- 'path': record.attrs.get('path', ""),
+ REMOTE_PATH: record.attrs.get(REMOTE_PATH, ""),
+ LOCAL_PATH: record.attrs.get(LOCAL_PATH, ""),
UPDATED: record.attrs.get(UPDATED, "0"),
PORTAL_TYPE: record.attrs.get(PORTAL_TYPE, "")
}
diff --git a/src/senaite/sync/syncstep.py b/src/senaite/sync/syncstep.py
index 6bd24d2..17935fb 100644
--- a/src/senaite/sync/syncstep.py
+++ b/src/senaite/sync/syncstep.py
@@ -15,6 +15,7 @@
from senaite.sync import logger
from senaite.sync import utils
from senaite.sync.syncerror import SyncError
+from senaite.sync.souphandler import REMOTE_PATH
SYNC_STORAGE = "senaite.sync"
API_BASE_URL = "API/senaite/v1"
@@ -227,7 +228,7 @@ def _parents_fetched(self, item):
if self.is_portal_path(parent_path):
return True
# Skip if already exists
- if self.sh.find_unique("path", parent_path):
+ if self.sh.find_unique(REMOTE_PATH, parent_path):
return True
logger.debug("Inserting missing parent: {}".format(parent_path))
parent = self.get_first_item(item.get("parent_url"))
diff --git a/src/senaite/sync/utils.py b/src/senaite/sync/utils.py
index d8ca84d..8b4ab72 100644
--- a/src/senaite/sync/utils.py
+++ b/src/senaite/sync/utils.py
@@ -7,11 +7,12 @@
from senaite.sync import logger
from DateTime import DateTime
from datetime import datetime
+from senaite.sync.souphandler import REMOTE_UID, REMOTE_PATH, PORTAL_TYPE
-SOUPER_REQUIRED_FIELDS = {"uid": "remote_uid",
- "path": "path",
- "portal_type": "portal_type"}
+SOUPER_REQUIRED_FIELDS = {"uid": REMOTE_UID,
+ "path": REMOTE_PATH,
+ "portal_type": PORTAL_TYPE}
SYNC_CREDENTIALS = "senaite.sync.credentials"
From 0822a514f81a788f948fec047c11ffe6e142135d Mon Sep 17 00:00:00 2001
From: Nihadness <1992.nihad@gmail.com>
Date: Wed, 2 May 2018 13:03:42 +0200
Subject: [PATCH 02/28] Do not fail if local path is not set while inserting to
Souper.
---
src/senaite/sync/souphandler.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/senaite/sync/souphandler.py b/src/senaite/sync/souphandler.py
index c3117af..4004eca 100644
--- a/src/senaite/sync/souphandler.py
+++ b/src/senaite/sync/souphandler.py
@@ -67,7 +67,7 @@ def insert(self, data):
record.attrs[REMOTE_UID] = data[REMOTE_UID]
record.attrs[LOCAL_UID] = data.get(LOCAL_UID, "")
record.attrs[REMOTE_PATH] = data[REMOTE_PATH]
- record.attrs[LOCAL_PATH] = data[LOCAL_PATH]
+ record.attrs[LOCAL_PATH] = data.get(LOCAL_PATH, "")
record.attrs[PORTAL_TYPE] = data[PORTAL_TYPE]
record.attrs[UPDATED] = data.get(UPDATED, "0")
r_id = self.soup.add(record)
From 95bd9924b2c5c54bb9268fd8bb652fae42ebfcfc Mon Sep 17 00:00:00 2001
From: Nihadness <1992.nihad@gmail.com>
Date: Wed, 2 May 2018 15:15:18 +0200
Subject: [PATCH 03/28] Path Translator with prefix.
---
src/senaite/sync/syncstep.py | 42 ++++++++++++++++++++++++++++++++++--
1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/src/senaite/sync/syncstep.py b/src/senaite/sync/syncstep.py
index 17935fb..8375e3a 100644
--- a/src/senaite/sync/syncstep.py
+++ b/src/senaite/sync/syncstep.py
@@ -15,7 +15,7 @@
from senaite.sync import logger
from senaite.sync import utils
from senaite.sync.syncerror import SyncError
-from senaite.sync.souphandler import REMOTE_PATH
+from senaite.sync.souphandler import REMOTE_PATH, LOCAL_PATH, PORTAL_TYPE
SYNC_STORAGE = "senaite.sync"
API_BASE_URL = "API/senaite/v1"
@@ -44,6 +44,7 @@ def __init__(self, data):
self.password = data.get("ac_password", None)
# Import configuration
self.content_types = data.get("content_types", None)
+ self.prefix = ""
self.import_settings = data.get("import_settings", False)
self.import_users = data.get("import_users", False)
self.import_registry = data.get("import_registry", False)
@@ -52,12 +53,49 @@ def __init__(self, data):
self.fail("Missing parameter in Sync Step: {}".format(data))
def translate_path(self, path):
- """Translate the physical path to a local path
+ """ Translate the physical path to a local path
"""
portal_id = self.portal.getId()
remote_portal_id = path.split("/")[1]
return str(path.replace(remote_portal_id, portal_id))
+ def translate_path_with_prefix(self, remote_path):
+ """
+ """
+ portal_id = self.portal.getId()
+ remote_portal_id = remote_path.split("/")[1]
+ if not self.prefix:
+ return str(remote_path.replace(remote_portal_id, portal_id))
+
+ rem_id = utils.get_id_from_path(remote_path)
+ rec = self.sh.find_unique(REMOTE_PATH, remote_path)
+ if rec[LOCAL_PATH]:
+ return rec[LOCAL_PATH]
+
+ # Get parent's local path
+ remote_parent_path = utils.get_parent_path(remote_path)
+ parent_path = self.translate_path_with_prefix(remote_parent_path)
+
+ # Will check whether prefix needed by portal type
+ portal_type = rec[PORTAL_TYPE]
+ prefix = self.get_prefix(portal_type)
+
+ res = "{0}/{1}{2}".format(parent_path, prefix, rem_id)
+ res = res.replace(remote_portal_id, portal_id)
+ self.sh.update_by_remote_path(remote_path, LOCAL_PATH = res)
+ return res
+
+ def get_prefix(self, portal_type):
+ """
+
+ :param portal_type:
+ :return:
+ """
+ if self.prefix and portal_type == 'Analysis':
+ return "PR_"
+
+ return ""
+
def is_portal_path(self, path):
""" Check if the given path is the path of any portal object.
:return:
From 522d9d2493e5b1e372e6fde4a37e478c6a89a517 Mon Sep 17 00:00:00 2001
From: Nihadness <1992.nihad@gmail.com>
Date: Wed, 2 May 2018 15:29:57 +0200
Subject: [PATCH 04/28] Use prefixes in object and parent creation.
---
src/senaite/sync/importstep.py | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/senaite/sync/importstep.py b/src/senaite/sync/importstep.py
index 8d31cef..4bdc79f 100644
--- a/src/senaite/sync/importstep.py
+++ b/src/senaite/sync/importstep.py
@@ -307,8 +307,8 @@ def _do_obj_creation(self, row):
.format(remote_path))
return None
- existing = self.portal.unrestrictedTraverse(self.translate_path(remote_path),
- None)
+ local_path = self.translate_path_with_prefix(remote_path)
+ existing = self.portal.unrestrictedTraverse(local_path, None)
if existing:
local_uid = self.sh.find_unique(REMOTE_PATH, remote_path).get(LOCAL_UID,
None)
@@ -322,10 +322,10 @@ def _do_obj_creation(self, row):
remote_path))
return None
- parent = self.translate_path(utils.get_parent_path(remote_path))
- container = self.portal.unrestrictedTraverse(str(parent), None)
+ parent_path = utils.get_parent_path(local_path)
+ container = self.portal.unrestrictedTraverse(str(parent_path), None)
obj_data = {
- "id": utils.get_id_from_path(remote_path),
+ "id": utils.get_id_from_path(local_path),
"portal_type": row.get(PORTAL_TYPE)}
obj = self._create_object_slug(container, obj_data)
if obj is not None:
@@ -348,7 +348,7 @@ def _parents_created(self, remote_path):
return True
# Incoming path was remote path, translate it into local one
- local_p_path = self.translate_path(p_path)
+ local_p_path = self.translate_path_with_prefix(p_path)
# Check if the parent already exists. If yes, make sure it has
# 'local_uid' value set in the soup table.
@@ -369,13 +369,15 @@ def _parents_created(self, remote_path):
# already ready.
if not self._parents_created(p_path):
return False
+
parent = self.sh.find_unique(REMOTE_PATH, p_path)
- grand_parent = self.translate_path(utils.get_parent_path(p_path))
- container = self.portal.unrestrictedTraverse(str(grand_parent), None)
+ grand_parent = utils.get_parent_path(local_p_path)
+ container = self.portal.unrestrictedTraverse(grand_parent, None)
parent_data = {
"id": utils.get_id_from_path(p_path),
"remote_path": p_path,
"portal_type": parent.get(PORTAL_TYPE)}
+
parent_obj = self._create_object_slug(container, parent_data)
if parent_obj is None:
logger.warning("Couldn't create parent of {}".format(remote_path))
From ecb6c18f7f6ac35cd0a677fd998332a446e59cbd Mon Sep 17 00:00:00 2001
From: Nihadness <1992.nihad@gmail.com>
Date: Thu, 3 May 2018 10:26:41 +0200
Subject: [PATCH 05/28] Use new local ID while creating parents.
---
src/senaite/sync/importstep.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/senaite/sync/importstep.py b/src/senaite/sync/importstep.py
index 4bdc79f..6513995 100644
--- a/src/senaite/sync/importstep.py
+++ b/src/senaite/sync/importstep.py
@@ -374,7 +374,7 @@ def _parents_created(self, remote_path):
grand_parent = utils.get_parent_path(local_p_path)
container = self.portal.unrestrictedTraverse(grand_parent, None)
parent_data = {
- "id": utils.get_id_from_path(p_path),
+ "id": utils.get_id_from_path(local_p_path),
"remote_path": p_path,
"portal_type": parent.get(PORTAL_TYPE)}
From e62d580019f024877555c1f3b5a871333b942865 Mon Sep 17 00:00:00 2001
From: Nihadness <1992.nihad@gmail.com>
Date: Thu, 3 May 2018 11:38:06 +0200
Subject: [PATCH 06/28] Separated 'Add' and 'Show' views of Remotes.
---
src/senaite/sync/browser/add.py | 86 +++++++++
src/senaite/sync/browser/configure.zcml | 7 +
src/senaite/sync/browser/templates/add.pt | 201 +++++++++++++++++++++
src/senaite/sync/browser/templates/sync.pt | 178 +-----------------
src/senaite/sync/browser/views.py | 44 -----
src/senaite/sync/fetchstep.py | 2 +-
6 files changed, 301 insertions(+), 217 deletions(-)
create mode 100644 src/senaite/sync/browser/add.py
create mode 100644 src/senaite/sync/browser/templates/add.pt
diff --git a/src/senaite/sync/browser/add.py b/src/senaite/sync/browser/add.py
new file mode 100644
index 0000000..ce2a3c0
--- /dev/null
+++ b/src/senaite/sync/browser/add.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2017-2018 SENAITE SYNC.
+
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from plone import protect
+from senaite import api
+from senaite.sync import _
+from senaite.sync.browser.interfaces import ISync
+from senaite.sync.browser.views import Sync
+from senaite.sync.fetchstep import FetchStep
+from zope.interface import implements
+
+SYNC_STORAGE = "senaite.sync"
+
+
+class Add(Sync):
+ """ Add new sync instance view
+ """
+ implements(ISync)
+
+ template = ViewPageTemplateFile("templates/add.pt")
+
+ def __init__(self, context, request):
+ super(Sync, self).__init__(context, request)
+
+ def __call__(self):
+ protect.CheckAuthenticator(self.request.form)
+
+ self.portal = api.get_portal()
+ self.request.set('disable_plone.rightcolumn', 1)
+ self.request.set('disable_border', 1)
+
+ # Handle form submit
+ form = self.request.form
+ fetchform = form.get("fetchform", False)
+ dataform = form.get("dataform", False)
+ if not any([fetchform, dataform]):
+ return self.template()
+
+ # Handle "Fetch" action
+ if form.get("fetch", False):
+
+ url = form.get("url", "")
+ if not url.startswith("http"):
+ url = "http://{}".format(url)
+ domain_name = form.get("domain_name", None)
+ username = form.get("ac_name", None)
+ password = form.get("ac_password", None)
+ # check if all mandatory fields have values
+ if not all([domain_name, url, username, password]):
+ message = _("Please fill in all required fields")
+ self.add_status_message(message, "error")
+ return self.template()
+
+ import_settings = True if form.get("import_settings") == 'on' else False
+ import_users = True if form.get("import_users") == 'on' else False
+ import_registry = True if form.get("import_registry") == 'on' else False
+ content_types = form.get("content_types", None)
+ if content_types is not None:
+ content_types = [t.strip() for t in content_types.split(",")]
+ portal_types = api.get_tool("portal_types")
+ content_types = filter(lambda ct: ct in portal_types,
+ content_types)
+
+ data = {
+ "url": url,
+ "domain_name": domain_name,
+ "ac_name": username,
+ "ac_password": password,
+ "content_types": content_types,
+ "import_settings": import_settings,
+ "import_users": import_users,
+ "import_registry": import_registry,
+ }
+
+ fs = FetchStep(data)
+ verified, message = fs.verify()
+ if verified:
+ fs.run()
+ self.add_status_message(message, "info")
+ else:
+ self.add_status_message(message, "error")
+
+ # render the template
+ return self.template()
diff --git a/src/senaite/sync/browser/configure.zcml b/src/senaite/sync/browser/configure.zcml
index c0200e3..33c85de 100644
--- a/src/senaite/sync/browser/configure.zcml
+++ b/src/senaite/sync/browser/configure.zcml
@@ -9,6 +9,13 @@
permission="cmf.ManagePortal"
/>
+
+
+
+
+
+
+
+
+
+
+ Add new Remote
+
+
+
+
+
+
+
+
+
+
+