diff --git a/bos_mint/forms.py b/bos_mint/forms.py
index 3400d70..36f01df 100644
--- a/bos_mint/forms.py
+++ b/bos_mint/forms.py
@@ -266,6 +266,10 @@ def fill(self, selectedObject):
self.name.fill(selectedObject['name'])
+class DeleteForm(FlaskForm):
+ cancel = SubmitField("Cancel")
+ submit = SubmitField("Delete")
+
class NewEventGroupForm(FlaskForm):
sport = SelectField("Sport", validators=[DataRequired()],
choices=None)
diff --git a/bos_mint/node.py b/bos_mint/node.py
index 31be7e3..2af881c 100644
--- a/bos_mint/node.py
+++ b/bos_mint/node.py
@@ -1,18 +1,18 @@
-from . import wrapper
-
from functools import wraps
+
+from bookied_sync.lookup import Lookup
from peerplays.account import Account
-from peerplays.sport import Sport, Sports
-from peerplays.eventgroup import EventGroups, EventGroup
-from peerplays.event import Events, Event
-from peerplays.bettingmarketgroup import BettingMarketGroup, BettingMarketGroups
+from peerplays.asset import Asset
from peerplays.bettingmarket import BettingMarkets, BettingMarket
-from peerplays.rule import Rules, Rule
+from peerplays.bettingmarketgroup import BettingMarketGroup, BettingMarketGroups
+from peerplays.event import Events, Event
+from peerplays.eventgroup import EventGroups, EventGroup
+from peerplays.instance import shared_peerplays_instance
from peerplays.proposal import Proposals
+from peerplays.rule import Rules, Rule
+from peerplays.sport import Sport, Sports
-from peerplays.instance import shared_peerplays_instance
-from peerplays.asset import Asset
-from bookied_sync.lookup import Lookup
+from . import wrapper
class NodeException(Exception):
@@ -368,6 +368,29 @@ def createSport(self, istrings):
except Exception as ex:
raise NodeException(ex.__class__.__name__ + ": " + str(ex))
+ @proposedOperation
+ def deleteSport(self, sportId):
+ try:
+ return self.get_node().sport_delete(
+ sport_id=sportId,
+ account=self.getSelectedAccountName(),
+ append_to=self.getPendingProposal()
+ )
+ except Exception as ex:
+ raise NodeException(ex.__class__.__name__ + ": " + str(ex))
+
+ @proposedOperation
+ def deleteEventgroup(self, event_group_id):
+
+ try:
+ return self.get_node().eventgroup_delete(
+ event_group_id=event_group_id,
+ account=self.getSelectedAccountName(),
+ append_to=self.getPendingProposal()
+ )
+ except Exception as ex:
+ raise NodeException(ex.__class__.__name__ + ": " + str(ex))
+
@proposedOperation
def createEventGroup(self, istrings, sportId):
try:
@@ -522,6 +545,17 @@ def rejectProposal(self, proposalId):
except Exception as ex:
raise NodeException(ex.__class__.__name__ + ": " + str(ex))
+ @proposedOperation
+ def deleteProposal(self, proposalId):
+ try:
+ return self.get_node().deleteproposal(
+ proposalId,
+ "witness-account",
+ append_to=self.getPendingProposal()
+ )
+ except Exception as ex:
+ raise NodeException(ex.__class__.__name__ + ": " + str(ex))
+
@proposedOperation
def resolveBettingMarketGroup(self, bettingMarketGroupId, resultList):
try:
diff --git a/bos_mint/templates/widgets/operationContainer.html b/bos_mint/templates/widgets/operationContainer.html
index 765a638..254efb8 100644
--- a/bos_mint/templates/widgets/operationContainer.html
+++ b/bos_mint/templates/widgets/operationContainer.html
@@ -11,7 +11,7 @@
{% else %}
{% endif %}
-
+
{% for item in listItems %}
@@ -40,7 +40,7 @@
- {% for operation in operations %}
+ {% for operation in operations %}
{{ operation|safe }}
{% endfor %} |
@@ -48,6 +48,16 @@
|
- |
+
{% endif %}
+
-
\ No newline at end of file
+
diff --git a/bos_mint/templates/widgets/operation_event_group_delete.html b/bos_mint/templates/widgets/operation_event_group_delete.html
new file mode 100644
index 0000000..2aa65a3
--- /dev/null
+++ b/bos_mint/templates/widgets/operation_event_group_delete.html
@@ -0,0 +1,12 @@
+{% from "_macros.html" import render_int_string %}
+
+
+
+
+
+ Event group ID: {{ data['event_group_id']}}
+
+
+
+
+
\ No newline at end of file
diff --git a/bos_mint/templates/widgets/operation_sport_delete.html b/bos_mint/templates/widgets/operation_sport_delete.html
new file mode 100644
index 0000000..d81918c
--- /dev/null
+++ b/bos_mint/templates/widgets/operation_sport_delete.html
@@ -0,0 +1,10 @@
+{% from "_macros.html" import render_int_string %}
+
+
+
+
+
+ Sport ID: {{ data['sport_id'] }}
+
+
+
\ No newline at end of file
diff --git a/bos_mint/utils.py b/bos_mint/utils.py
index cd989e8..8ba5c49 100644
--- a/bos_mint/utils.py
+++ b/bos_mint/utils.py
@@ -95,36 +95,24 @@
'bet': 'bettingmarket'
}
-TYPENAME_TO_NEWOP_MAP = {
- 'sport': 'sport_create',
- 'eventgroup': 'event_group_create',
- 'event': 'event_create',
- 'event_status': None,
- 'bettingmarketgroup': 'betting_market_group_create',
- 'bettingmarketgrouprule': 'betting_market_rules_create',
- 'bettingmarket': 'betting_market_create',
- 'bet': 'bet_create',
-}
-
-TYPENAME_TO_UPDATEOP_MAP = {
- 'sport': 'sport_update',
- 'eventgroup': 'event_group_update',
- 'event': 'event_update',
- 'event_status': 'event_update_status',
- 'bettingmarketgroup': 'betting_market_group_update',
- 'bettingmarketgrouprule': 'betting_market_rules_update',
- 'bettingmarket': 'betting_market_update'
-}
-
-UPDATEOP_TO_TYPENAME_MAP = {
+OP_TO_TYPENAME_MAP = {
+ 'sport_create': 'sport',
+ 'sport_delete': 'sport',
'sport_update': 'sport',
+ 'event_group_create': 'eventgroup',
+ 'event_group_delete': 'eventgroup',
'event_group_update': 'eventgroup',
+ 'event_create': 'event',
'event_update': 'event',
'event_update_status': 'event_status',
+ 'betting_market_group_create': 'bettingmarketgroup',
'betting_market_group_update': 'bettingmarketgroup',
+ 'betting_market_rules_create': 'bettingmarketgrouprule',
'betting_market_rules_update': 'bettingmarketgrouprule',
+ 'betting_market_create': 'bettingmarket',
'betting_market_update': 'bettingmarket',
- 'betting_market_group_resolve': 'bettingmarketgroup'
+ 'betting_market_group_resolve': 'bettingmarketgroup',
+ 'bet_create': 'bet',
}
@@ -340,12 +328,7 @@ def getProposalOperations(tx):
operation = operation['op']
operationName = getOperationNameForId(operation[0])
typeName = 'unknown'
- for tmpTypeName, newOpName in TYPENAME_TO_NEWOP_MAP.items():
- if newOpName == operationName:
- typeName = tmpTypeName
-
- typeName = UPDATEOP_TO_TYPENAME_MAP.get(operationName, typeName)
-
+ typeName = OP_TO_TYPENAME_MAP.get(operationName, typeName)
if typeName == 'unknown':
raise Exception
# this is a hack. proper id construction __must__ be
diff --git a/bos_mint/views.py b/bos_mint/views.py
index e8d86c9..3f5cb62 100644
--- a/bos_mint/views.py
+++ b/bos_mint/views.py
@@ -1,3 +1,4 @@
+
from flask import (
redirect,
request,
@@ -22,7 +23,8 @@
ReplayForm,
ApprovalForm,
BettingMarketGroupResolveForm,
- SynchronizationForm
+ SynchronizationForm,
+ DeleteForm
)
from .models import (
LocalProposal,
@@ -54,6 +56,8 @@
from threading import Thread
from datetime import datetime
from peerplays.event import Events
+from peerplays.eventgroup import EventGroup
+from peerplays.sport import Sport
from bos_mint.datestring import string_to_date
from pprint import pformat, pprint
import json
@@ -610,7 +614,19 @@ def overview(typeName=None, identifier=None):
def buildListElements(tmpList):
tmpList = sorted(tmpList, key=lambda k: k['toString'])
for entry in tmpList:
- if entry['typeName'] == 'event':
+ if entry['typeName'] == 'sport':
+ entry['extraLink'] = [{
+ 'title': 'Delete',
+ 'link': 'sport_delete',
+ 'icon': 'trash alternate outline'
+ }]
+ elif entry['typeName'] == 'eventgroup':
+ entry['extraLink'] = [{
+ 'title': 'Delete',
+ 'link': 'eventgroup_delete',
+ 'icon': 'trash alternate outline'
+ }]
+ elif entry['typeName'] == 'event':
entry['extraLink'] = [{
'title': 'Show incidents',
'link': 'event_incidents',
@@ -836,7 +852,8 @@ def votable_proposals():
if proposals:
accountId = Node().getSelectedAccount()['id']
- containerList = widgets.prepareProposalsDataForRendering(proposals)
+ advanced_user = Config.get("advanced_features", default=False)
+ containerList = widgets.prepareProposalsDataForRendering(proposals, accountId=accountId, advanced_user=advanced_user)
containerReview = {}
reviewedProposals = LocalProposal.getAllAsList()
@@ -876,6 +893,18 @@ def votable_proposals_reject(proposalId):
return redirect(url_for('votable_proposals'))
+@app.route("/proposals/delete/", methods=['post', 'get'])
+@unlocked_wallet_required
+def proposal_delete(proposalId):
+ try:
+ Node().deleteProposal(proposalId)
+ flash('Added Proposal delete proposal to Pending operations')
+ except Exception as e:
+ flash(e.__repr__(), category="error")
+
+ return redirect(url_for('votable_proposals'))
+
+
def findAndProcessTranslatons(form):
for field in form._fields.values():
if isinstance(field, FormField) and isinstance(field.form, TranslatedFieldForm) and field.addLanguage.data:
@@ -926,6 +955,7 @@ def sport_new():
return genericNewForm(forms.NewSportForm)
+
@app.route("/eventgroup/new", methods=['post', 'get'])
@app.route("/eventgroup/new/", methods=['post', 'get'])
@unlocked_wallet_required
@@ -964,7 +994,51 @@ def bet_new():
return render_template_menuinfo('index.html', **locals())
+@app.route("/sport/delete/", methods=['post', 'get'])
+@app.route("/sport/delete/", methods=['post', 'get'])
+@unlocked_wallet_required
+def sport_delete(selectId=None):
+ """If this button is pressed a form will be opened to delete the Sport with a given selectId"""
+ form = DeleteForm(sport_id=selectId)
+ sport = Sport(selectId)
+ formTitle = "Are you sure that you want do delete {0} ({1})?".format(sport['name'][0][1], sport['id'])
+ flash('All related Eventgroups will be cancelled and deleted as well', category='warning')
+
+ if form.validate_on_submit():
+ if form.cancel.data: # cancel button has been pressed
+ return redirect(url_for('overview'))
+
+ try:
+ Node().deleteSport(selectId)
+ return redirect(url_for('overview'))
+ except Exception as e:
+ flash(e.__repr__(), category='error')
+
+ return render_template_menuinfo("generic.html", **locals())
+
+
+@app.route("/eventgroup/delete/", methods=['post', 'get'])
+@app.route("/eventgroup/delete/", methods=['post', 'get'])
+@unlocked_wallet_required
+def eventgroup_delete(selectId=None):
+ form = DeleteForm()
+ eventgroup = EventGroup(selectId)
+ print(eventgroup)
+ formTitle = "Are you sure that you want to delete {0} ({1})?".format(eventgroup['name'][0][1], eventgroup['id'])
+ flash("All related Events will be cancelled and deleted as well", category='warning')
+ if form.validate_on_submit():
+ if form.cancel.data:
+ return redirect(url_for('overview'))
+ try:
+ Node().deleteEventgroup(event_group_id=selectId)
+ return redirect(url_for('overview'))
+ except Exception as e:
+ flash(e.__repr__(), category="error")
+
+ return render_template_menuinfo("generic.html", **locals())
+
def genericUpdate(formClass, selectId, removeSubmits=False, details=False):
+
typeName = formClass.getTypeName()
selectFunction = utils.getTypeGetter(typeName)
diff --git a/bos_mint/widgets.py b/bos_mint/widgets.py
index c148802..7f0231d 100644
--- a/bos_mint/widgets.py
+++ b/bos_mint/widgets.py
@@ -110,7 +110,7 @@ def addOperation(self, operationId, data):
self.template_args['operations'].append(ow)
-def prepareProposalsDataForRendering(proposals, accountId=None):
+def prepareProposalsDataForRendering(proposals, accountId=None, advanced_user=False):
tmpList = []
for proposal in proposals:
# ensure the parent expiration time is the shortest time
@@ -151,7 +151,10 @@ def prepareProposalsDataForRendering(proposals, accountId=None):
buttonNegativeURL=url_for('votable_proposals_reject',
proposalId=proposal['id']),
buttonPositiveURL=url_for('votable_proposals_accept',
- proposalId=proposal['id'])
+ proposalId=proposal['id']),
+ buttonDelete="Delete",
+ buttonDeleteURL=url_for("proposal_delete", proposalId=proposal['id']),
+ advanced_user=advanced_user
)
for operation in proposal['proposed_transaction']['operations']:
diff --git a/bos_mint/wrapper.py b/bos_mint/wrapper.py
index 3ab494e..0a67c41 100644
--- a/bos_mint/wrapper.py
+++ b/bos_mint/wrapper.py
@@ -30,7 +30,11 @@ def kwGet(self, kwargs, name, default=None):
if default:
return kwargs.get(name, default)
else:
- return kwargs[name]
+ try:
+ tmpname = kwargs[name]
+ except KeyError:
+ tmpname = "to be deleted"
+ return tmpname
class Sport(BlockchainIdentifiable):
@@ -44,6 +48,11 @@ def translateOperation(cls, operationData):
return {'pendingOperationId': operationData['operationId'],
'id': operationData['sport_id'],
'name': operationData['new_name']}
+ elif operationData.get('operationName', None) == 'sport_delete':
+ return {'pendingOperationId': operationData['operationId'],
+ 'id': operationData['sport_id'],
+ 'name': 'To be deleted',
+ }
else:
from .node import NodeException
raise NodeException(
@@ -69,6 +78,12 @@ def translateOperation(cls, operationData):
'id': operationData['event_group_id'],
'name': operationData['new_name'],
'sport_id': operationData['new_sport_id']}
+ elif operationData.get('operationName', None) == 'event_group_delete':
+ return {
+ 'pendingOperationId': operationData['operationId'],
+ 'id': operationData['operationId'],
+ 'name': 'To be deleted',
+ }
else:
from .node import NodeException
raise NodeException(
diff --git a/requirements.txt b/requirements.txt
index 7c5aceb..cdf9f2f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,7 +14,7 @@ Jinja2
Markdown
PyYAML
requests
-webassets>=0-12.1
+webassets>=0.12.1
flask-script
flask-sqlalchemy
mysqlclient