Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

181
LINES

< > BotCompany Repo | #1026001 - HCRUD - CRUD in HTML with pluggable data handler

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (15624L/109K).

sclass HCRUD extends HAbstractRenderable {
  HCRUD_Data data;
  int defaultTextFieldCols = 80;
  bool mutationRights = true;
  bool allowCreateOrDelete = true;
  bool singleton;
  bool cmdsLeft; // put commands on the left instead of the right
  S tableClass; // CSS class for table
  Set<S> uneditableFields, unshownFields;
  
  *() {}
  *(HCRUD_Data *data) {}
  *(S *baseLink, HCRUD_Data *data) {}
  
  S newLink() { ret appendQueryToURL(baseLink, cmd := "new"); }
  S deleteLink(O id) { ret appendQueryToURL(baseLink, "delete_" + id, 1); }
  S editLink(O id) { ret appendQueryToURL(baseLink, edit := id); }
  S duplicateLink(O id) { ret appendQueryToURL(baseLink, duplicate := id); }
  
  // also handles commands if withCmds=true
  S render(bool withCmds, SS params) {
    if (!withCmds) ret renderTable(false);
    
    try answer handleCommands(params);
    
    ret renderMsgs(params)
      + (singleton || !allowCreateOrDelete ? "" : p(ahref(newLink(), "New " + itemName())))
      + renderTable(withCmds);
  }

  S handleCommands(SS params) {
    new LS msgs;
    
    if (eqGet(params, "action", "create")) {
      O id = data.createObject(subMapStartingWith_dropPrefix(params, "f_"));
      msgs.add(itemName() + " created (ID: " + id + ")");
    }
    
    if (eqGet(params, "action", "update"))
      msgs.add(data.updateObject(params.get("id"),
        subMapStartingWith_dropPrefix(params, "f_")));

    for (S toDelete : keysDeprefixNemptyValue(params, "delete_"))
      msgs.add(data.deleteObject(toDelete));

    ret nempty(msgs) ? refreshWithMsgs(msgs) : "";
  }
  
  S encodeField(S s) {
    ret or(data.fieldNameToHTML(s), s);
  }
  
  // in table
  S renderValue(S field, O value) {
    if (value cast HTML) ret value.html;
    ret htmlEncode_nlToBr_withIndents(strOrEmpty(value));
  }
  
  S renderTable(bool withCmds) {
    ret renderTable(withCmds, data.list());
  }
  
  S renderTable(bool withCmds, L<MapSO> l) {
    if (empty(l)) ret p("No entries");
    //LS fields = data.fields();
    //if (fields == null) fields = allKeysFromList_inOrder();
    l = map(l, map -> {
      map = mapMinusKeys(map, unshownFields);
      MapSO map2 = postProcessTableRow(map, mapToMap(
        (key, value) -> pair(encodeField(key), renderValue(key, value)),
        map));
      if (singleton)
        map2.remove(data.fieldNameToHTML(data.idField())); // don't show ID in table in singleton mode
      if (withCmds)
        map2 = addCmdsToTableRow(map, map2);
      ret map2;
    });
    ret htmlTable2_noHtmlEncode(l, tableParams());
  }
  
  MapSO addCmdsToTableRow(MapSO map, MapSO map2) {
    map2.put(cmdsKey(), renderCmds(map));
    if (cmdsLeft)
      map2 = putKeysFirst(map2, cmdsKey());
    ret map2;
  }
  
  /*swappable*/ O[] tableParams() {
    ret litparams(
      tdParams := litparams(valign := "top"),
      tableParams := litparams(class := tableClass));
  }
  
  S renderForm(Map<S, O> map) {
    map = mapMinusKeys(map, joinSets(unshownFields, uneditableFields));
    ret htableRaw_valignTop(
      map(map, (field, value) -> {
        S help = data.fieldHelp(field);
        ret ll(
          encodeField(field),
          renderInput(field, value)
            + (empty(help) ? "" : "<br> " + small(help))
        );
      })
    , border := 1, cellpadding := 4);
  }
  
  S renderInput(S field, O value) {
    S name = "f_" + field;
    HCRUD_Data.Renderer r = data.getRenderer(field);
    if (r cast HCRUD_Data.TextArea)
      ret htextarea(strOrEmpty(value), +name, cols := r.cols, rows := r.rows);
    if (r cast HCRUD_Data.TextField)
      ret htextfield(name, strOrEmpty(value), size := r.cols, style := "font-family: monospace");
    if (r cast HCRUD_Data.ComboBox)
      ret hselect_list(r.entries, strOrEmpty(value), +name);
    if (r cast HCRUD_Data.CheckBox)
      //ret hcheckbox(name, isTrue(value));
      ret htrickcheckboxWithText(name, "", isTrue(value));
    ret renderInput_default(field, value);
  }
  
  S renderInput_default(S field, O value) {
    S name = "f_" + field;
    ret htextfield(name, strOrEmpty(value), size := defaultTextFieldCols);
  }
  
  S renderNewForm() {
    ret renderNewForm(data.emptyObject());
  }
  
  S renderNewForm(MapSO map1) {
    //printStruct("renderNewForm", map1);
    Map<S, O> map = mapWithoutKey(map1, data.idField());
    //printStruct("renderNewForm", map);
    ret hpostform(
      hhidden("action", "create") +
      renderForm(map)
      + p(hsubmit("Create")),
      action := baseLink);
  }
  
  S renderEditForm(S id) {
    Map<S, O> map = mapWithoutKey(data.getObject(id), data.idField());
    if (map == null) ret htmlEncode2("Entry " + id + " not found");
    ret hpostform(
      hhidden("action", "update") +
      hhidden(+id) +
      renderForm(map)
      + p(hsubmit("Save changes")),
      action := baseLink);
  }
  
  S renderPage(SS params) {
    if (eqGet(params, "cmd", "new"))
      ret frame("New " + itemName(), renderNewForm());
    if (nempty(params.get("edit")))
      ret frame("Edit " + itemName(), renderEditForm(params.get("edit")));
    if (nempty(params.get("duplicate")))
      ret frame("New " + itemName(), renderNewForm(data.getObject(params.get("duplicate"))));
    ret frame(ahref(baseLink, firstToUpper(singleton ? data.itemName() : data.itemNamePlural())), render(mutationRights, params));
  }
  
  HCRUD makeFrame(MakeFrame makeFrame) { super.makeFrame(makeFrame); this; }
  
  S cmdsKey() { ret "<!-- cmds -->"; }
  
  S itemName() { ret data.itemName(); }
  
  swappable MapSO postProcessTableRow(MapSO data, MapSO rendered) { ret rendered; }
  
  swappable S renderCmds(MapSO item) {
    O id = item.get(data.idField());
    ret joinNemptiesWithVBar(
      ahref(editLink(id), "edit"),
      singleton || !allowCreateOrDelete ? null : ahrefWithConfirm(
        "Really delete item " + id + "?", deleteLink(id), htmlEncode2(unicode_DEL())),
      singleton || !allowCreateOrDelete ? null : ahref(duplicateLink(id), "dup", title := "duplicate")
    );
  }
}

download  show line numbers  debug dex   

Travelled to 4 computer(s): mqqgnosmbjvj, onxytkatvevr, tvejysmllsmz, xrpafgyirdlv

No comments. add comment

Snippet ID: #1026001
Snippet name: HCRUD - CRUD in HTML with pluggable data handler
Eternal ID of this version: #1026001/60
Text MD5: 20838146d5d9552711475a71e1e5990f
Transpilation MD5: 4cadb437754c22d86c3470b9ac344142
Author: stefan
Category: javax / html
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-07-02 12:45:26
Source code size: 6179 bytes / 181 lines
Pitched / IR pitched: No / No
Views / Downloads: 201 / 626
Version history: 59 change(s)
Referenced in: [show references]

Formerly at http://tinybrain.de/1026001 & http://1026001.tinybrain.de