def edit(): if request.method == "GET": appid = request.args.get("appid") if not appid: return "appid not provided", 400 app = appstorage.get_app(appid) if app is None: return "App not found", 500 data = json.loads(app.data) text = data["text"] return render_template("composers/dummy/edit.html", app=app, text=text) elif request.method == "POST": appid = request.form["appid"] text = request.form["text"] # Retrieve the app we're editing by its id. app = appstorage.get_app(appid) # Build our dummy composer JSON. data = {"dummy_version": 1, "text": text} appstorage.update_app_data(app, data) flash(gettext("Saved successfully"), "success") # TODO: Print a success message etc etc. # If the user clicked on saveexit we redirect to appview, otherwise # we stay here. if "saveexit" in request.form: return redirect(url_for("user.apps.index")) return render_template("composers/dummy/edit.html", app=app, text=text)
def test_data_save(self): data = {"MYNAME": "TEST"} api.update_app_data(self.tapp, json.dumps(data)) recdata = api.get_app_by_name("UTApp").data pdata = json.loads(recdata) assert data == pdata
def do_languages_initial_merge(app, bm): """ Carries out an initial merge. Bundles from the language-owners are merged into the app. @param app: Target app. App into which the bundles of each language owner are merged. @param bm: Target BundleManager. Bundle manager into which the bundles of each language owner are merged. @note: The App's data is updated automatically to reflect the new merge. """ # Retrieve every single "owned" App for that xmlspec. ownerships = _db_get_ownerships(bm.get_gadget_spec()) for ownership in ownerships: language = ownership.value ownerapp = ownership.app bm.merge_language(language, ownerapp) update_app_data(app, bm.to_json())
def edit(): if request.method == "GET": appid = request.args.get("appid") if not appid: return "appid not provided", 400 app = appstorage.get_app(appid) if app is None: return "App not found", 500 data = json.loads(app.data) text = data["text"] return render_template("composers/dummy/edit.html", app=app, text=text) elif request.method == "POST": appid = request.form["appid"] text = request.form["text"] # Retrieve the app we're editing by its id. app = appstorage.get_app(appid) # Build our dummy composer JSON. data = { "dummy_version": 1, "text": text} appstorage.update_app_data(app, data) flash(gettext("Saved successfully"), "success") # TODO: Print a success message etc etc. # If the user clicked on saveexit we redirect to appview, otherwise # we stay here. if "saveexit" in request.form: return redirect(url_for("user.apps.index")) return render_template("composers/dummy/edit.html", app=app, text=text)
def translate_edit(): """ Translation editor for the selected language. @note: Returns error 400 if the source language or group don't exist. """ # No matter if we are handling a GET or POST, we require these parameters. appid = request.values.get("appid") srclang = request.values.get("srclang") targetlang = request.values.get("targetlang") srcgroup = request.values.get("srcgroup") targetgroup = request.values.get("targetgroup") # Retrieve the application we want to view or edit. app = get_app(appid) if app is None: return render_template("composers/errors.html", message=gettext("App not found")), 404 bm = BundleManager.create_from_existing_app(app.data) spec = bm.get_gadget_spec() # Retrieve the bundles for our lang. For this, we build the code from the info we have. srcbundle_code = BundleManager.partialcode_to_fullcode(srclang, srcgroup) targetbundle_code = BundleManager.partialcode_to_fullcode(targetlang, targetgroup) srcbundle = bm.get_bundle(srcbundle_code) # Ensure the existence of the source bundle. if srcbundle is None: return render_template("composers/errors.html", message=gettext("The source language and group combination does not exist")), 400 targetbundle = bm.get_bundle(targetbundle_code) # The target bundle doesn't exist yet. We need to create it ourselves. if targetbundle is None: splits = targetlang.split("_") if len(splits) == 2: lang, country = splits targetbundle = Bundle(lang, country, targetgroup) bm.add_bundle(targetbundle_code, targetbundle) # Get the owner for this target language. owner_app = _db_get_lang_owner_app(spec, targetlang) # If the language has no owner, we declare ourselves as owners. if owner_app is None: _db_declare_ownership(app, targetlang) owner_app = app # We override the standard Ownership's system is_owner. # TODO: Verify that this doesn't break anything. is_owner = owner_app == app # Get the language names target_translation_name = targetbundle.get_readable_name() source_translation_name = srcbundle.get_readable_name() # This is a GET request. We are essentially viewing-only. if request.method == "GET": pass # This is a POST request. We need to save the entries. else: # Protect against CSRF attacks. if not verify_csrf(request): return render_template("composers/errors.html", message=gettext("Request does not seem to come from the right source (csrf check)")), 400 # Retrieve a list of all the key-values to save. That is, the parameters which start with _message_. messages = [(k[len("_message_"):], v) for (k, v) in request.values.items() if k.startswith("_message_")] # Save all the messages we retrieved from the POST or GET params into the Bundle. for identifier, msg in messages: if len(msg) > 0: # Avoid adding empty messages. targetbundle.add_msg(identifier, msg) # Now we need to save the changes into the database. json_str = bm.to_json() update_app_data(app, json_str) flash(gettext("Changes have been saved."), "success") propose_to_owner = request.values.get("proposeToOwner") if propose_to_owner is not None and owner_app != app: # Normally we will add the proposal to the queue. However, sometimes the owner wants to auto-accept # all proposals. We check for this. If the autoaccept mode is enabled on the app, we do the merge # right here and now. obm = BundleManager.create_from_existing_app(owner_app.data) if obm.get_autoaccept(): flash(gettext("Changes are being applied instantly because the owner has auto-accept enabled")) # Merge into the owner app. obm.merge_bundle(targetbundle_code, targetbundle) # Now we need to update the owner app's data. Because we aren't the owners, we can't use the appstorage # API directly. owner_app.data = obm.to_json() db.session.add(owner_app) db.session.commit() # [Context: We are not the leading Bundles, but our changes are merged directly into the leading Bundle] # We report the change to a "leading" bundle. on_leading_bundle_updated(spec, targetbundle) else: # We need to propose this Bundle to the owner. # Note: May be confusing: app.owner.login refers to the generic owner of the App, and not the owner # we are talking about in the specific Translate composer. proposal_data = {"from": app.owner.login, "timestamp": time.time(), "bundle_code": targetbundle_code, "bundle_contents": targetbundle.to_jsonable()} proposal_json = json.dumps(proposal_data) # Link the proposal with the Owner app. add_var(owner_app, "proposal", proposal_json) flash(gettext("Changes have been proposed to the owner")) # If we are the owner app. if owner_app == app: # [Context: We are the leading Bundle] # We report the change. on_leading_bundle_updated(spec, targetbundle) # Check whether the user wants to exit or to continue editing. if "save_exit" in request.values: return redirect(url_for("user.apps.index")) return render_template("composers/translate/edit.html", is_owner=is_owner, app=app, srcbundle=srcbundle, targetbundle=targetbundle, spec=spec, target_translation_name=target_translation_name, source_translation_name=source_translation_name)
def save_data(self, app_id, data): """ Wrapper of the appstorage API. It saves the data in JSON format. """ app = appstorage.get_app(app_id) appstorage.update_app_data(app, data)
def translate_proposed_list(): """ Displays the list of proposed translations. """ # No matter if we are handling a GET or POST, we require these parameters. appid = request.values["appid"] app = get_app(appid) appdata = json.loads(app.data) # TODO: !!!!! THIS IS MISSING AND IS IMPORTANT !!!!! # Ensure that only the app owner can carry out these operations. # owner_app = _db_get_owner_app(appdata["spec"]) # if app != owner_app: # return render_template("composers/errors.html", # message="Not Authorized: You don't seem to be the owner of this app") # Get the list of proposed translations. proposal_vars = _db_get_proposals(app) proposed_translations = [] for prop in proposal_vars: propdata = json.loads(prop.value) propdata["id"] = str(prop.var_id) proposed_translations.append(propdata) # If we received a POST with acceptButton set then we will need to merge the # proposal. if request.method == "POST" and request.values.get("acceptButton") is not None: proposal_id = request.values.get("proposals") if proposal_id is None: return render_template("composers/errors.html", message=gettext("Proposal not selected")) merge_data = request.values.get("data") if merge_data is None: return render_template("composers/errors.html", message=gettext("Merge data was not provided")) merge_data = json.loads(merge_data) # TODO: Optimize this. We already have the vars. proposal = AppVar.query.filter_by(app=app, var_id=proposal_id).first() if proposal is None: return render_template("composers/errors.html", message=gettext("Proposals not found")) data = json.loads(proposal.value) bundle_code = data["bundle_code"] proposed_bundle = Bundle.from_messages(merge_data, bundle_code) bm = BundleManager.create_from_existing_app(app.data) bm.merge_bundle(bundle_code, proposed_bundle) update_app_data(app, bm.to_json()) flash(gettext("Merge done."), "success") # Remove the proposal from the DB. remove_var(proposal) # Remove it from our current proposal list as well, so that it isn't displayed anymore. proposed_translations = [prop for prop in proposed_translations if prop["id"] != proposal_id] # The DENY button was pressed. We have to discard the whole proposal. elif request.method == "POST" and request.values.get("denyButton") is not None: proposal_id = request.values.get("proposals") if proposal_id is None: return render_template("composers/errors.html", message=gettext("Proposal not selected")) proposal = AppVar.query.filter_by(app=app, var_id=proposal_id).first() if proposal is None: return render_template("composers/errors.html", message=gettext("Proposal not found")) remove_var(proposal) # Remove it from our current proposal list as well, so that it isn't displayed anymore. proposed_translations = [prop for prop in proposed_translations if prop["id"] != proposal_id] return render_template("composers/translate/proposed_list.html", app=app, proposals=proposed_translations)