Commit e3375121 authored by jan.koester's avatar jan.koester
Browse files

test

parent e509c797
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -173,10 +173,16 @@ var EditorApi = (function() {
            return request('POST', '/api/document/save', { name: name, group: group || '' });
        },

        bulkGenerateTemplates: function(templateIds, rows) {
        listTemplates: function() {
            return request('GET', '/api/templates');
        },

        bulkGenerateTemplates: function(templateIds, rows, overwriteExisting, checkOnly) {
            return request('POST', '/api/template/bulk-generate', {
                template_ids: templateIds || [],
                rows: rows || []
                rows: rows || [],
                overwrite_existing: !!overwriteExisting,
                check_only: !!checkOnly
            });
        },

+36 −10
Original line number Diff line number Diff line
@@ -460,8 +460,8 @@
        wizardCsvRows = [];
        wizardCsvColumns = [];

        EditorApi.listDocuments().then(function(resp) {
            wizardTemplates = resp.documents || [];
        EditorApi.listTemplates().then(function(resp) {
            wizardTemplates = resp.templates || [];
            renderTemplateWizardTemplateList();
            document.getElementById('template-wizard-dialog').showModal();
        }).catch(function(err) {
@@ -516,20 +516,46 @@
                return;
            }

            status.textContent = 'Erzeuge Dokumente...';
            status.textContent = 'Prufe bestehende Vorlagen...';
            status.className = 'set-status';

            EditorApi.bulkGenerateTemplates(selectedIds, wizardCsvRows, false, true).then(function(previewResp) {
                var conflicts = previewResp.conflicts_count || 0;

                if (conflicts > 0) {
                    var q = conflicts + ' Vorlage(n) mit gleichem Name in derselben Gruppe existieren bereits. Uberschreiben?';
                    if (!confirm(q)) {
                        status.textContent = 'Abgebrochen: vorhandene Vorlagen wurden nicht uberschrieben.';
                        status.className = 'set-status';
                        return;
                    }
                    executeTemplateBulk(selectedIds, true);
                    return;
                }

                executeTemplateBulk(selectedIds, false);
            }).catch(function(err) {
                status.textContent = 'Fehler bei Konfliktprufung: ' + ((err && err.error) || 'Unbekannt');
                status.className = 'set-status error';
            });
        });
    }

    function executeTemplateBulk(selectedIds, overwriteExisting) {
        var status = document.getElementById('template-wizard-status');
        status.textContent = overwriteExisting ? 'Uberschreibe bestehende Vorlagen...' : 'Erzeuge Dokumente...';
        status.className = 'set-status';

            EditorApi.bulkGenerateTemplates(selectedIds, wizardCsvRows).then(function(resp) {
        EditorApi.bulkGenerateTemplates(selectedIds, wizardCsvRows, overwriteExisting, false).then(function(resp) {
            var created = resp.created_count || 0;
            var rows = resp.row_count || wizardCsvRows.length;
            var templates = resp.template_count || selectedIds.length;
                status.textContent = 'Fertig: ' + created + ' Dokumente aus ' + templates + ' Vorlagen und ' + rows + ' CSV-Zeilen erzeugt.';
            status.textContent = 'Fertig: ' + created + ' Dokumente aus ' + templates + ' Vorlagen und ' + rows + ' CSV-Zeilen verarbeitet.';
            status.className = 'set-status success';
        }).catch(function(err) {
            status.textContent = 'Fehler: ' + ((err && err.error) || 'Erzeugen fehlgeschlagen');
            status.className = 'set-status error';
        });
        });
    }

    function renderTemplateWizardTemplateList() {
+88 −8
Original line number Diff line number Diff line
@@ -489,6 +489,12 @@ bool webedit::Api::handleRequest(libhttppp::HttpRequest &curreq, const int tid,
        return true;
    }

    // Route: /api/templates
    if (path == "/api/templates") {
        handleListTemplates(curreq, sessionid);
        return true;
    }

    // Route: /api/template/bulk-generate
    if (path == "/api/template/bulk-generate") {
        handleTemplateBulkGenerate(curreq, sessionid);
@@ -1532,8 +1538,15 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq,

    json_object *templateIdsObj = nullptr;
    json_object *rowsObj = nullptr;
    json_object *overwriteExistingObj = nullptr;
    json_object *checkOnlyObj = nullptr;
    json_object_object_get_ex(req, "template_ids", &templateIdsObj);
    json_object_object_get_ex(req, "rows", &rowsObj);
    json_object_object_get_ex(req, "overwrite_existing", &overwriteExistingObj);
    json_object_object_get_ex(req, "check_only", &checkOnlyObj);

    const bool overwriteExisting = overwriteExistingObj && json_object_get_boolean(overwriteExistingObj);
    const bool checkOnly = checkOnlyObj && json_object_get_boolean(checkOnlyObj);

    if (!templateIdsObj || !rowsObj ||
        !json_object_is_type(templateIdsObj, json_type_array) ||
@@ -1596,7 +1609,9 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq,
    }

    json_object *createdArr = json_object_new_array();
    json_object *conflictsArr = json_object_new_array();
    size_t createdCount = 0;
    size_t conflictsCount = 0;

    for (size_t rowIndex = 0; rowIndex < rowCount; ++rowIndex) {
        json_object *rowObj = json_object_array_get_idx(rowsObj, rowIndex);
@@ -1631,20 +1646,57 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq,
            const std::string generatedXml = replacePlaceholders(tpl.xml, rowValues);
            const std::string targetGroup = rowDomain.empty() ? tpl.group : rowDomain;

            std::string newDocId = _db.saveDocument(uid,
            std::string existingDocId;
            const bool exists = _db.findDocumentIdByNameGroup(uid,
                                                              sessionDomain,
                                                              tpl.name,
                                                              targetGroup,
                                                              existingDocId);

            if (exists && !overwriteExisting) {
                ++conflictsCount;
                json_object *conflictObj = json_object_new_object();
                json_object_object_add(conflictObj, "id", json_object_new_string(existingDocId.c_str()));
                json_object_object_add(conflictObj, "name", json_object_new_string(tpl.name.c_str()));
                json_object_object_add(conflictObj, "group", json_object_new_string(targetGroup.c_str()));
                json_object_object_add(conflictObj, "template_id", json_object_new_string(tpl.id.c_str()));
                json_object_object_add(conflictObj, "row_index", json_object_new_int64(static_cast<long long>(rowIndex)));
                json_object_array_add(conflictsArr, conflictObj);
                continue;
            }

            if (checkOnly) {
                continue;
            }

            std::string changedDocId;
            bool updated = false;
            if (exists && overwriteExisting) {
                changedDocId = _db.updateDocument(uid,
                                                  existingDocId,
                                                  tpl.name,
                                                  generatedXml,
                                                  author,
                                                  targetGroup);
            if (!newDocId.empty()) {
                updated = true;
            } else {
                changedDocId = _db.saveDocument(uid,
                                                sessionDomain,
                                                tpl.name,
                                                generatedXml,
                                                author,
                                                targetGroup);
            }

            if (!changedDocId.empty()) {
                ++createdCount;
                json_object *createdObj = json_object_new_object();
                json_object_object_add(createdObj, "id", json_object_new_string(newDocId.c_str()));
                json_object_object_add(createdObj, "id", json_object_new_string(changedDocId.c_str()));
                json_object_object_add(createdObj, "name", json_object_new_string(tpl.name.c_str()));
                json_object_object_add(createdObj, "group", json_object_new_string(targetGroup.c_str()));
                json_object_object_add(createdObj, "template_id", json_object_new_string(tpl.id.c_str()));
                json_object_object_add(createdObj, "row_index", json_object_new_int64(static_cast<long long>(rowIndex)));
                json_object_object_add(createdObj, "updated", json_object_new_boolean(updated));
                json_object_array_add(createdArr, createdObj);
            }
        }
@@ -1653,15 +1705,43 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq,
    json_object *resp = json_object_new_object();
    json_object_object_add(resp, "status", json_object_new_string("ok"));
    json_object_object_add(resp, "created_count", json_object_new_int64(static_cast<long long>(createdCount)));
    json_object_object_add(resp, "conflicts_count", json_object_new_int64(static_cast<long long>(conflictsCount)));
    json_object_object_add(resp, "template_count", json_object_new_int64(static_cast<long long>(templates.size())));
    json_object_object_add(resp, "row_count", json_object_new_int64(static_cast<long long>(rowCount)));
    json_object_object_add(resp, "check_only", json_object_new_boolean(checkOnly));
    json_object_object_add(resp, "overwrite_existing", json_object_new_boolean(overwriteExisting));
    json_object_object_add(resp, "created", createdArr);
    json_object_object_add(resp, "conflicts", conflictsArr);

    sendJson(curreq, resp);
    json_object_put(resp);
    json_object_put(req);
}

void webedit::Api::handleListTemplates(libhttppp::HttpRequest &curreq,
                                       const std::string &sessionid) {
    std::string uid;
    std::string domain;
    _session.getData(sessionid, "uid", uid);
    _session.getData(sessionid, "domain", domain);

    if (uid.empty()) {
        sendJsonError(curreq, 400, "Missing user session");
        return;
    }

    std::string jsonStr = _db.listDocumentsForOwnerDomain(uid, domain);
    json_object *arr = json_tokener_parse(jsonStr.c_str());
    if (!arr) {
        arr = json_object_new_array();
    }

    json_object *resp = json_object_new_object();
    json_object_object_add(resp, "templates", arr);
    sendJson(curreq, resp);
    json_object_put(resp);
}

// --- Load document from DB ---

void webedit::Api::handleLoadDocument(libhttppp::HttpRequest &curreq,
+1 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ namespace webedit {
        void handleListDocuments(libhttppp::HttpRequest &curreq, const std::string &sessionid);
        void handleDeleteDocument(libhttppp::HttpRequest &curreq, const std::string &sessionid,
                                  const std::string &docId);
        void handleListTemplates(libhttppp::HttpRequest &curreq, const std::string &sessionid);
        void handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq, const std::string &sessionid);

        // Revision handlers
+56 −0
Original line number Diff line number Diff line
@@ -409,6 +409,62 @@ std::string webedit::Database::listDocuments(const std::string &domain) {
    return result;
}

std::string webedit::Database::listDocumentsForOwnerDomain(const std::string &ownerUid,
                                                           const std::string &domain) {
    dbpp::SQL sql;
    dbpp::DBResult res;
    std::vector<char> escapedUid, escapedDomain;

    sql << "SELECT id, name, created, modified, group_name FROM documents "
        << "WHERE owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str())
        << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str())
        << "' ORDER BY group_name, name, modified DESC;";

    int rows = _db->exec(sql, res);

    json_object *arr = json_object_new_array();

    for (int i = 0; i < rows; ++i) {
        json_object *obj = json_object_new_object();
        json_object_object_add(obj, "id", json_object_new_string(res[i][0]));
        json_object_object_add(obj, "name", json_object_new_string(res[i][1]));
        json_object_object_add(obj, "created", json_object_new_string(res[i][2]));
        json_object_object_add(obj, "modified", json_object_new_string(res[i][3]));
        json_object_object_add(obj, "group", json_object_new_string(res[i][4]));
        json_object_array_add(arr, obj);
    }

    std::string result = json_object_to_json_string_ext(arr, JSON_C_TO_STRING_NOSLASHESCAPE);
    json_object_put(arr);
    return result;
}

bool webedit::Database::findDocumentIdByNameGroup(const std::string &ownerUid,
                                                  const std::string &domain,
                                                  const std::string &name,
                                                  const std::string &group,
                                                  std::string &docId) {
    dbpp::SQL sql;
    dbpp::DBResult res;
    std::vector<char> escapedUid, escapedDomain, escapedName, escapedGroup;

    sql << "SELECT id FROM documents WHERE owner_uid='"
        << dbpp::SQL::escaped(escapedUid, ownerUid.c_str())
        << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str())
        << "' AND name='" << dbpp::SQL::escaped(escapedName, name.c_str())
        << "' AND group_name='" << dbpp::SQL::escaped(escapedGroup, group.c_str())
        << "' ORDER BY modified DESC LIMIT 1;";

    int rows = _db->exec(sql, res);
    if (rows < 1) {
        docId.clear();
        return false;
    }

    docId = std::string(res[0][0]);
    return true;
}

std::string webedit::Database::listRevisions(const std::string &docId) {
    dbpp::SQL sql;
    dbpp::DBResult res;
Loading