Commit 0cb750d8 authored by Jérome Perrin's avatar Jérome Perrin

- invalid_category_spreadsheet_handler now returns a boolean, telling if we...

- invalid_category_spreadsheet_handler now returns a boolean, telling if we should continue processing or not.
- Drop "simulation_mode" hack and use an invalid_category_spreadsheet_handler accumulating errors instead.
- Don't fail if some empty sheets are left in the spreadsheet


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@32183 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 939c9828
...@@ -60,9 +60,13 @@ ...@@ -60,9 +60,13 @@
`import_file` must be a spreadsheet in a format supported by openoffice\n `import_file` must be a spreadsheet in a format supported by openoffice\n
\n \n
`invalid_spreadsheet_error_handler` is the callback method that will be called if\n `invalid_spreadsheet_error_handler` is the callback method that will be called if\n
the spreadsheet is invalid. The method must recieve as only parameter a string\n the spreadsheet is invalid. The method must accept one parameter, an\n
explaining the error.\n explanation of the error.\n
If no error_callback is given, the default action is to raise a ValueError.\n The error handler can return a boolean, true meaning that the rest of the\n
spreadsheet have to be processed, false meaning that the processing should\n
stop.\n
If no error_callback is given, the default action is to raise a ValueError on\n
the first error encountered.\n
\n \n
The returned mapping has the following structure:\n The returned mapping has the following structure:\n
\n \n
...@@ -80,7 +84,6 @@ way that parent always precedes their children.\n ...@@ -80,7 +84,6 @@ way that parent always precedes their children.\n
"""\n """\n
from Products.ERP5Type.Message import translateString\n from Products.ERP5Type.Message import translateString\n
from Products.ERP5OOo.OOoUtils import OOoParser\n from Products.ERP5OOo.OOoUtils import OOoParser\n
from Products.ERP5Type.Document import newTempBase\n
parser = OOoParser()\n parser = OOoParser()\n
category_list_spreadsheet_mapping = dict()\n category_list_spreadsheet_mapping = dict()\n
error_list = []\n error_list = []\n
...@@ -91,17 +94,16 @@ def default_invalid_spreadsheet_error_handler(error_message):\n ...@@ -91,17 +94,16 @@ def default_invalid_spreadsheet_error_handler(error_message):\n
if invalid_spreadsheet_error_handler is None:\n if invalid_spreadsheet_error_handler is None:\n
invalid_spreadsheet_error_handler = default_invalid_spreadsheet_error_handler\n invalid_spreadsheet_error_handler = default_invalid_spreadsheet_error_handler\n
\n \n
try:\n # FIXME: we are actually only interested in properties defined on Category\n
property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n # type information.\n
except AttributeError:\n property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n
# Class tool is too old\n
property_id_list = []\n
\n \n
\n \n
def getIDFromString(string=None):\n def getIDFromString(string=None):\n
"""\n """\n
This function transform a string to a safe and beautiful ID.\n This function transform a string to a safe and beautiful ID.\n
It is used here to create a safe category ID from a string.\n It is used here to create a safe category ID from a string.\n
But the code is not really clever...\n
"""\n """\n
if string is None:\n if string is None:\n
return None\n return None\n
...@@ -156,8 +158,11 @@ spreadsheet_list = parser.getSpreadsheetsMapping(no_empty_lines=True)\n ...@@ -156,8 +158,11 @@ spreadsheet_list = parser.getSpreadsheetsMapping(no_empty_lines=True)\n
\n \n
\n \n
for table_name in spreadsheet_list.keys():\n for table_name in spreadsheet_list.keys():\n
sheet = spreadsheet_list[table_name]\n
if not sheet:\n
continue\n
# Get the header of the table\n # Get the header of the table\n
columns_header = spreadsheet_list[table_name][0]\n columns_header = sheet[0]\n
# Get the mapping to help us know the property according a cell index\n # Get the mapping to help us know the property according a cell index\n
property_map = {}\n property_map = {}\n
column_index = 0\n column_index = 0\n
...@@ -204,8 +209,7 @@ for table_name in spreadsheet_list.keys():\n ...@@ -204,8 +209,7 @@ for table_name in spreadsheet_list.keys():\n
# This path_element_list help us to reconstruct the absolute path\n # This path_element_list help us to reconstruct the absolute path\n
path_element_list = []\n path_element_list = []\n
line_index = 2\n line_index = 2\n
for line in spreadsheet_list[table_name][1:]:\n for line in sheet[1:]:\n
\n
# Exclude empty lines\n # Exclude empty lines\n
if line.count(\'\') + line.count(None) == len(line):\n if line.count(\'\') + line.count(None) == len(line):\n
continue\n continue\n
...@@ -218,7 +222,6 @@ for table_name in spreadsheet_list.keys():\n ...@@ -218,7 +222,6 @@ for table_name in spreadsheet_list.keys():\n
property_id = property_map[cell_index]\n property_id = property_map[cell_index]\n
line_data[property_id] = cell\n line_data[property_id] = cell\n
cell_index += 1\n cell_index += 1\n
\n
# Analyse every cell of the line\n # Analyse every cell of the line\n
category_property_list = {}\n category_property_list = {}\n
cell_index = 0\n cell_index = 0\n
...@@ -277,28 +280,23 @@ for table_name in spreadsheet_list.keys():\n ...@@ -277,28 +280,23 @@ for table_name in spreadsheet_list.keys():\n
\n \n
# Detect invalid IDs\n # Detect invalid IDs\n
if path_element_id in property_id_list:\n if path_element_id in property_id_list:\n
if simulation_mode:\n cont = invalid_spreadsheet_error_handler(\n
error = newTempBase(context, \'item\')\n translateString("The ID ${id} in ${table} at line ${line} is invalid, it\'s a reserved property name",\n
error.edit(field_type = \'Invalid ID\', field_category = path_element_id, field_message = translateString("The ID ${id} in ${table} at line ${line} is invalid, it\'s a reserved property name",mapping=dict(id=path_element_id, table=table_name, line=line_index)))\n mapping=dict(id=path_element_id, table=table_name, line=line_index)))\n
error_list.append(error)\n if not cont:\n
else:\n return \n
return invalid_spreadsheet_error_handler(translateString("The ID ${id} in ${table} at line ${line} is invalid, it\'s a reserved property name",mapping=dict(id=path_element_id, table=table_name, line=line_index)))\n
\n
\n
\n \n
# Detect duplicate IDs\n # Detect duplicate IDs\n
for element in path_element_list[::-1]:\n for element in path_element_list[::-1]:\n
if element[\'depth\'] != element_depth:\n if element[\'depth\'] != element_depth:\n
break\n break\n
if element[\'value\'] == path_element_id:\n if element[\'value\'] == path_element_id:\n
if simulation_mode:\n cont = invalid_spreadsheet_error_handler(\n
error = newTempBase(context, \'item\')\n translateString(\n
error.edit(field_type = \'Duplicate ID\', field_category = element[\'value\'], field_message = translateString("Duplicate ID ${id} found in ${table} at line ${line} ", mapping=dict(id=element[\'value\'], table=table_name, line=line_index)))\n "Duplicate ID found in ${table} at line ${line} : ${id}",\n
error_list.append(error)\n
else:\n
return invalid_spreadsheet_error_handler( \n
translateString("Duplicate id found in ${table} at line ${line} : ${id}",\n
mapping=dict(id=element[\'value\'], table=table_name, line=line_index)))\n mapping=dict(id=element[\'value\'], table=table_name, line=line_index)))\n
if not cont:\n
return\n
\n \n
\n \n
# Detect wrong hierarchy\n # Detect wrong hierarchy\n
...@@ -313,17 +311,13 @@ for table_name in spreadsheet_list.keys():\n ...@@ -313,17 +311,13 @@ for table_name in spreadsheet_list.keys():\n
current_depth = element[\'depth\']\n current_depth = element[\'depth\']\n
continue # we are on the direct parent (current level - 1)\n continue # we are on the direct parent (current level - 1)\n
else:\n else:\n
if simulation_mode:\n cont = invalid_spreadsheet_error_handler(\n
error = newTempBase(context, \'item\')\n
error.edit(field_type = \'Wrong hierarchy\', field_category = path_element_id, field_message = translateString("Wrong hierarchy found for ID ${id} and ${depth} in ${table} at line ${line} " ,mapping=dict(id=path_element_id,depth=element_depth, table=table_name, line=line_index)))\n
error_list.append(error) \n
else: \n
return invalid_spreadsheet_error_handler(\n
translateString(\n translateString(\n
"Wrong hierarchy found for ID ${id} and depth ${depth} in ${table} at line ${line} ",\n "Wrong hierarchy found for ID ${id} and depth ${depth} in ${table} at line ${line} ",\n
mapping=dict(id=path_element_id,\n mapping=dict(id=path_element_id,\n
depth=element_depth, table=table_name, line=line_index)))\n depth=element_depth, table=table_name, line=line_index)))\n
\n if not cont:\n
return\n
\n \n
\n \n
# Save the path element\n # Save the path element\n
...@@ -352,7 +346,7 @@ else:\n ...@@ -352,7 +346,7 @@ else:\n
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>import_file, invalid_spreadsheet_error_handler=None, simulation_mode=False</string> </value> <value> <string>import_file, invalid_spreadsheet_error_handler=None</string> </value>
</item> </item>
<item> <item>
<key> <string>errors</string> </key> <key> <string>errors</string> </key>
...@@ -372,7 +366,7 @@ else:\n ...@@ -372,7 +366,7 @@ else:\n
<dictionary> <dictionary>
<item> <item>
<key> <string>co_argcount</string> </key> <key> <string>co_argcount</string> </key>
<value> <int>3</int> </value> <value> <int>2</int> </value>
</item> </item>
<item> <item>
<key> <string>co_varnames</string> </key> <key> <string>co_varnames</string> </key>
...@@ -380,13 +374,10 @@ else:\n ...@@ -380,13 +374,10 @@ else:\n
<tuple> <tuple>
<string>import_file</string> <string>import_file</string>
<string>invalid_spreadsheet_error_handler</string> <string>invalid_spreadsheet_error_handler</string>
<string>simulation_mode</string>
<string>Products.ERP5Type.Message</string> <string>Products.ERP5Type.Message</string>
<string>translateString</string> <string>translateString</string>
<string>Products.ERP5OOo.OOoUtils</string> <string>Products.ERP5OOo.OOoUtils</string>
<string>OOoParser</string> <string>OOoParser</string>
<string>Products.ERP5Type.Document</string>
<string>newTempBase</string>
<string>parser</string> <string>parser</string>
<string>dict</string> <string>dict</string>
<string>category_list_spreadsheet_mapping</string> <string>category_list_spreadsheet_mapping</string>
...@@ -396,10 +387,10 @@ else:\n ...@@ -396,10 +387,10 @@ else:\n
<string>_getattr_</string> <string>_getattr_</string>
<string>context</string> <string>context</string>
<string>property_id_list</string> <string>property_id_list</string>
<string>AttributeError</string>
<string>getIDFromString</string> <string>getIDFromString</string>
<string>content_type</string> <string>content_type</string>
<string>hasattr</string> <string>hasattr</string>
<string>Products.ERP5Type.Document</string>
<string>newTempOOoDocument</string> <string>newTempOOoDocument</string>
<string>tmp_ooo</string> <string>tmp_ooo</string>
<string>_getiter_</string> <string>_getiter_</string>
...@@ -411,6 +402,7 @@ else:\n ...@@ -411,6 +402,7 @@ else:\n
<string>spreadsheet_list</string> <string>spreadsheet_list</string>
<string>table_name</string> <string>table_name</string>
<string>_getitem_</string> <string>_getitem_</string>
<string>sheet</string>
<string>columns_header</string> <string>columns_header</string>
<string>property_map</string> <string>property_map</string>
<string>column_index</string> <string>column_index</string>
...@@ -445,7 +437,7 @@ else:\n ...@@ -445,7 +437,7 @@ else:\n
<string>element</string> <string>element</string>
<string>path</string> <string>path</string>
<string>clean_title</string> <string>clean_title</string>
<string>error</string> <string>cont</string>
<string>current_depth</string> <string>current_depth</string>
</tuple> </tuple>
</value> </value>
...@@ -460,7 +452,6 @@ else:\n ...@@ -460,7 +452,6 @@ else:\n
<value> <value>
<tuple> <tuple>
<none/> <none/>
<int>0</int>
</tuple> </tuple>
</value> </value>
</item> </item>
......
...@@ -62,15 +62,8 @@ detailed_report_append = detailed_report_result.append\n ...@@ -62,15 +62,8 @@ detailed_report_append = detailed_report_result.append\n
base_category_id_list = []\n base_category_id_list = []\n
category_path_dict = {}\n category_path_dict = {}\n
simulation_new_category_id_list = []\n simulation_new_category_id_list = []\n
try:\n \n
property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n property_id_list = context.portal_classes.getPropertySheetPropertyIdList()\n
except AttributeError:\n
# Class tool is too old - use an empty list and warn used in detailed report\n
property_id_list = []\n
if \'warning\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'WARNING\', field_category = \'\', field_message = \'ERP5Type product needs to be upgraded so that portal_classes can supply getPropertySheetPropertyIdList\') \n
detailed_report_append(report_line)\n
\n \n
def Object_hasRelation(obj):\n def Object_hasRelation(obj):\n
# Check if there is some related objets.\n # Check if there is some related objets.\n
...@@ -80,8 +73,6 @@ def Object_hasRelation(obj):\n ...@@ -80,8 +73,6 @@ def Object_hasRelation(obj):\n
related_url = related.getRelativeUrl()\n related_url = related.getRelativeUrl()\n
if related_url.startswith(obj.getRelativeUrl()):\n if related_url.startswith(obj.getRelativeUrl()):\n
continue\n continue\n
elif related_url.startswith(\'portal_simulation\'):\n
continue\n
elif related_url.startswith(\'portal_trash\'):\n elif related_url.startswith(\'portal_trash\'):\n
continue\n continue\n
else:\n else:\n
...@@ -104,7 +95,17 @@ expired_category_counter = 0\n ...@@ -104,7 +95,17 @@ expired_category_counter = 0\n
\n \n
filename = getattr(import_file, \'filename\', \'?\')\n filename = getattr(import_file, \'filename\', \'?\')\n
\n \n
def invalid_category_spreadsheet_handler(message):\n # The list of error from simulation mode\n
error_list = []\n
if simulation_mode:\n
def invalid_category_spreadsheet_handler(message):\n
error = newTempBase(context, \'item\')\n
error.edit(field_type=\'Error\',\n
field_message=message)\n
error_list.append(error)\n
return True # means continue processing the rest of the document\n
else:\n
def invalid_category_spreadsheet_handler(error_type, path, message):\n
# action taken when an invalid spreadsheet is provided.\n # action taken when an invalid spreadsheet is provided.\n
# we *raise* a Redirect, because we don\'t want the transaction to succeed\n # we *raise* a Redirect, because we don\'t want the transaction to succeed\n
# note, we could make a dialog parameter to allow import invalid spreadsheet:\n # note, we could make a dialog parameter to allow import invalid spreadsheet:\n
...@@ -113,10 +114,10 @@ def invalid_category_spreadsheet_handler(message):\n ...@@ -113,10 +114,10 @@ def invalid_category_spreadsheet_handler(message):\n
message)\n message)\n
\n \n
category_list_spreadsheet_mapping = context.Base_getCategoriesSpreadSheetMapping(import_file,\n category_list_spreadsheet_mapping = context.Base_getCategoriesSpreadSheetMapping(import_file,\n
invalid_spreadsheet_error_handler=invalid_category_spreadsheet_handler, simulation_mode=simulation_mode)\n invalid_spreadsheet_error_handler=invalid_category_spreadsheet_handler)\n
\n \n
if category_list_spreadsheet_mapping.has_key(\'error_list\'):\n if simulation_mode and error_list:\n
context.REQUEST.other[\'category_import_report\'] = category_list_spreadsheet_mapping[\'error_list\']\n context.REQUEST.other[\'category_import_report\'] = error_list\n
return context.CategoryTool_viewImportReport()\n return context.CategoryTool_viewImportReport()\n
\n \n
for base_category, category_list in \\\n for base_category, category_list in \\\n
...@@ -147,7 +148,7 @@ for base_category, category_list in \\\n ...@@ -147,7 +148,7 @@ for base_category, category_list in \\\n
simulation_new_category_id_list.append({\'category\':category_id,\'path\':parent_path})\n simulation_new_category_id_list.append({\'category\':category_id,\'path\':parent_path})\n
if \'created\' in displayed_report:\n if \'created\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'Creation\', field_category = category[\'path\'].split(category_id)[0]+category_id, field_message = translateString("Will be created new ${type}", mapping=dict(type=category_type))) \n report_line.edit(field_type = \'Creation\', field_category = category[\'path\'].split(category_id)[0]+category_id, field_message = translateString("Will be created new ${type}", mapping=dict(type=category_type)))\n
detailed_report_append(report_line)\n detailed_report_append(report_line)\n
else:\n else:\n
base_path_obj.newContent( portal_type = category_type\n base_path_obj.newContent( portal_type = category_type\n
...@@ -156,7 +157,7 @@ for base_category, category_list in \\\n ...@@ -156,7 +157,7 @@ for base_category, category_list in \\\n
)\n )\n
if \'created\' in displayed_report:\n if \'created\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'Creation\', field_category = base_path_obj[category_id].getRelativeUrl(), field_message = translateString("Created new ${type}", mapping=dict(type=category_type))) \n report_line.edit(field_type = \'Creation\', field_category = base_path_obj[category_id].getRelativeUrl(), field_message = translateString("Created new ${type}", mapping=dict(type=category_type)))\n
detailed_report_append(report_line)\n detailed_report_append(report_line)\n
else:\n else:\n
# The ID is invalid, we must break the loop\n # The ID is invalid, we must break the loop\n
...@@ -164,7 +165,7 @@ for base_category, category_list in \\\n ...@@ -164,7 +165,7 @@ for base_category, category_list in \\\n
is_valid_category = False\n is_valid_category = False\n
if \'warning\' in displayed_report:\n if \'warning\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'WARNING\', field_category = \'\', field_message = translateString("found invalid ID ${id} ", mapping=dict(id=category_id))) \n report_line.edit(field_type = \'WARNING\', field_category = \'\', field_message = translateString("found invalid ID ${id} ", mapping=dict(id=category_id)))\n
detailed_report_append(report_line)\n detailed_report_append(report_line)\n
break\n break\n
is_new_category = True\n is_new_category = True\n
...@@ -251,23 +252,23 @@ for base_category_id in base_category_id_list:\n ...@@ -251,23 +252,23 @@ for base_category_id in base_category_id_list:\n
# TODO: add a dialog parameter allowing to delete this path\n # TODO: add a dialog parameter allowing to delete this path\n
if \'warning\' in displayed_report:\n if \'warning\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'Warning\', field_category = category.getRelativeUrl(), field_message = translateString("Category is used and can not be deleted or expired ", mapping=dict())) \n report_line.edit(field_type = \'Warning\', field_category = category.getRelativeUrl(), field_message = translateString("Category is used and can not be deleted or expired ", mapping=dict()))\n
detailed_report_append(report_line)\n detailed_report_append(report_line)\n
else:\n else:\n
if existing_category_list == \'keep\' and \'kept\' in displayed_report:\n if existing_category_list == \'keep\' and \'kept\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'Keep\', field_category = category.getRelativeUrl(), field_message = translateString("Kept category", mapping=dict())) \n report_line.edit(field_type = \'Keep\', field_category = category.getRelativeUrl(), field_message = translateString("Kept category", mapping=dict()))\n
detailed_report_append(report_line)\n detailed_report_append(report_line)\n
kept_category_counter += 1\n kept_category_counter += 1\n
else:\n else:\n
if existing_category_list == \'delete\' and \'deleted\' in displayed_report:\n if existing_category_list == \'delete\' and \'deleted\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'Delete\', field_category = category.getRelativeUrl(), field_message = translateString("Deleted category", mapping=dict())) \n report_line.edit(field_type = \'Delete\', field_category = category.getRelativeUrl(), field_message = translateString("Deleted category", mapping=dict()))\n
detailed_report_append(report_line)\n detailed_report_append(report_line)\n
deleted_category_counter += 1\n deleted_category_counter += 1\n
if existing_category_list == \'expire\' and \'expired\' in displayed_report:\n if existing_category_list == \'expire\' and \'expired\' in displayed_report:\n
report_line = newTempBase(context, \'item\')\n report_line = newTempBase(context, \'item\')\n
report_line.edit(field_type = \'Expire\', field_category = category.getRelativeUrl(), field_message = translateString("Expired category", mapping=dict())) \n report_line.edit(field_type = \'Expire\', field_category = category.getRelativeUrl(), field_message = translateString("Expired category", mapping=dict()))\n
detailed_report_append(report_line)\n detailed_report_append(report_line)\n
expired_category_counter += 1\n expired_category_counter += 1\n
category_to_delete_list.append(category.getRelativeUrl())\n category_to_delete_list.append(category.getRelativeUrl())\n
...@@ -378,8 +379,6 @@ return context.REQUEST.RESPONSE.redirect(\n ...@@ -378,8 +379,6 @@ return context.REQUEST.RESPONSE.redirect(\n
<string>simulation_new_category_id_list</string> <string>simulation_new_category_id_list</string>
<string>context</string> <string>context</string>
<string>property_id_list</string> <string>property_id_list</string>
<string>AttributeError</string>
<string>report_line</string>
<string>Object_hasRelation</string> <string>Object_hasRelation</string>
<string>isValidID</string> <string>isValidID</string>
<string>new_category_counter</string> <string>new_category_counter</string>
...@@ -391,9 +390,9 @@ return context.REQUEST.RESPONSE.redirect(\n ...@@ -391,9 +390,9 @@ return context.REQUEST.RESPONSE.redirect(\n
<string>expired_category_counter</string> <string>expired_category_counter</string>
<string>getattr</string> <string>getattr</string>
<string>filename</string> <string>filename</string>
<string>error_list</string>
<string>invalid_category_spreadsheet_handler</string> <string>invalid_category_spreadsheet_handler</string>
<string>category_list_spreadsheet_mapping</string> <string>category_list_spreadsheet_mapping</string>
<string>_getitem_</string>
<string>_write_</string> <string>_write_</string>
<string>_getiter_</string> <string>_getiter_</string>
<string>base_category</string> <string>base_category</string>
...@@ -405,6 +404,7 @@ return context.REQUEST.RESPONSE.redirect(\n ...@@ -405,6 +404,7 @@ return context.REQUEST.RESPONSE.redirect(\n
<string>is_new_category</string> <string>is_new_category</string>
<string>key_list</string> <string>key_list</string>
<string>base_path_obj</string> <string>base_path_obj</string>
<string>_getitem_</string>
<string>category_id_list</string> <string>category_id_list</string>
<string>parent_path</string> <string>parent_path</string>
<string>True</string> <string>True</string>
...@@ -413,6 +413,7 @@ return context.REQUEST.RESPONSE.redirect(\n ...@@ -413,6 +413,7 @@ return context.REQUEST.RESPONSE.redirect(\n
<string>category_id</string> <string>category_id</string>
<string>str</string> <string>str</string>
<string>category_type</string> <string>category_type</string>
<string>report_line</string>
<string>dict</string> <string>dict</string>
<string>None</string> <string>None</string>
<string>new_category</string> <string>new_category</string>
......
1453 1455
\ No newline at end of file \ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment