Add AutoConnectFile

pull/57/head
Hieromon Ikasamo 6 years ago
parent fc1b95726a
commit 062779b5e8
  1. 91
      src/AutoConnectAux.cpp
  2. 1
      src/AutoConnectAux.h
  3. 7
      src/AutoConnectElement.h
  4. 26
      src/AutoConnectElementBasis.h
  5. 27
      src/AutoConnectElementBasisImpl.h
  6. 22
      src/AutoConnectElementJson.h
  7. 40
      src/AutoConnectElementJsonImpl.h

@ -2,8 +2,8 @@
* Implementation of AutoConnectAux class.
* @file AutoConnectAuxBasisImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
#include <algorithm>
@ -43,7 +43,7 @@ const char AutoConnectAux::_PAGE_AUX[] PROGMEM = {
"{{MENU_AUX}}"
"{{MENU_POST}}"
"<div class=\"base-panel\"><div class=\"aux-page\">"
"<form id='_aux' method=\"post\" onsubmit=\"return false;\">"
"<form id='_aux' method=\"post\" onsubmit=\"return false;\" {{ENC_TYPE}}>"
"<ul class=\"noorder\">"
"{{AUX_ELEMENT}}"
"</ul>"
@ -263,6 +263,23 @@ const String AutoConnectAux::_indicateUri(PageArgument& args) {
return lastUri;
}
/**
* Modifying the form of attribute depending on the type of `input` tag
* contained. If the custom web page contains `input type=file` then
* allows multipart as ENCTYPE attribute.
* @param args A reference of PageArgument but unused.
* @return HTML string that should be inserted.
*/
const String AutoConnectAux::_indicateEncType(PageArgument& args) {
AC_UNUSED(args);
String encType = String("");
for (AutoConnectElement& elm : _addonElm)
if (elm.typeOf() == AC_File) {
return String(F("enctype='multipart/form-data'"));
}
return AutoConnect::_emptyString;
}
/**
* Insert the token handler of PageBuilder. This handler inserts HTML
* elements generated by the whole AutoConnectElements to the auxiliary page.
@ -328,6 +345,7 @@ PageElement* AutoConnectAux::_setupPage(const String& uri) {
elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, mother, std::placeholders::_1));
elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, mother, std::placeholders::_1));
elm->addToken(String(FPSTR("AUX_URI")), std::bind(&AutoConnectAux::_indicateUri, this, std::placeholders::_1));
elm->addToken(String(FPSTR("ENC_TYPE")), std::bind(&AutoConnectAux::_indicateEncType, this, std::placeholders::_1));
elm->addToken(String(FPSTR("AUX_ELEMENT")), std::bind(&AutoConnectAux::_insertElement, this, std::placeholders::_1));
}
}
@ -363,6 +381,20 @@ void AutoConnectAux::_storeElements(WebServerClass* webServer) {
#ifndef AUTOCONNECT_USE_JSON
/**
* Get AutoConnectElementBasis element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementBasis*>(elm));
}
return reinterpret_cast<AutoConnectElementBasis&>(_nullElement());
}
/**
* Get AutoConnectButtonBasis element.
* @param name An element name.
@ -397,6 +429,23 @@ AutoConnectCheckboxBasis& AutoConnectAux::getElement(const String& name) {
return reinterpret_cast<AutoConnectCheckboxBasis&>(_nullElement());
}
/**
* Get AutoConnectFileBasis element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectFileBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectFileBasis&>(_nullElement());
}
/**
* Get AutoConnectInputBasis element.
* @param name An element name.
@ -484,6 +533,20 @@ AutoConnectTextBasis& AutoConnectAux::getElement(const String& name) {
#else
/**
* Get AutoConnectElementJson element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementJson*>(elm));
}
return reinterpret_cast<AutoConnectElementJson&>(_nullElement());
}
/**
* Get AutoConnectButtonJson element.
* @param name An element name.
@ -518,6 +581,23 @@ AutoConnectCheckboxJson& AutoConnectAux::getElement(const String& name) {
return reinterpret_cast<AutoConnectCheckboxJson&>(_nullElement());
}
/**
* Get AutoConnectFile element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectFileJson&>(_nullElement());
}
/**
* Get AutoConnectInputJson element.
* @param name An element name.
@ -702,6 +782,10 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
AutoConnectCheckbox* cert_elm = new AutoConnectCheckbox;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_File: {
AutoConnectFile* cert_elm = new AutoConnectFile;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
}
case AC_Input: {
AutoConnectInput* cert_elm = new AutoConnectInput;
return reinterpret_cast<AutoConnectElement*>(cert_elm);
@ -949,6 +1033,7 @@ ACElement_t AutoConnectAux::_asElementType(const String& type) {
{ AUTOCONNECT_JSON_TYPE_ACBUTTON, AC_Button },
{ AUTOCONNECT_JSON_TYPE_ACCHECKBOX, AC_Checkbox },
{ AUTOCONNECT_JSON_TYPE_ACELEMENT, AC_Element },
{ AUTOCONNECT_JSON_TYPE_ACFILE, AC_File },
{ AUTOCONNECT_JSON_TYPE_ACINPUT, AC_Input },
{ AUTOCONNECT_JSON_TYPE_ACRADIO, AC_Radio },
{ AUTOCONNECT_JSON_TYPE_ACSELECT, AC_Select },

@ -80,6 +80,7 @@ class AutoConnectAux : public PageBuilder {
const String _injectTitle(PageArgument& args) const { (void)(args); return _title; } /**< Returns title of this page to PageBuilder */
const String _injectMenu(PageArgument& args); /**< Inject menu title of this page to PageBuilder */
const String _indicateUri(PageArgument& args); /**< Inject the uri that caused the request */
const String _indicateEncType(PageArgument& args); /**< Inject the ENCTYPE attribute */
void _storeElements(WebServerClass* webServer); /**< Store element values from contained in request arguments */
static AutoConnectElement& _nullElement(void); /**< A static returning value as invalid */

@ -2,8 +2,8 @@
* Alias declarations for an accessible the AutoConnectElement class.
* @file AutoConnectAux.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2018-03-11
* @copyright MIT license.
*/
@ -17,6 +17,7 @@
using AutoConnectElement = AutoConnectElementJson;
using AutoConnectButton = AutoConnectButtonJson;
using AutoConnectCheckbox = AutoConnectCheckboxJson;
using AutoConnectFile = AutoConnectFileJson;
using AutoConnectInput = AutoConnectInputJson;
using AutoConnectRadio = AutoConnectRadioJson;
using AutoConnectSelect = AutoConnectSelectJson;
@ -27,6 +28,7 @@ using AutoConnectText = AutoConnectTextJson;
using AutoConnectElement = AutoConnectElementBasis;
using AutoConnectButton = AutoConnectButtonBasis;
using AutoConnectCheckbox = AutoConnectCheckboxBasis;
using AutoConnectFile = AutoConnectFileBasis;
using AutoConnectInput = AutoConnectInputBasis;
using AutoConnectRadio = AutoConnectRadioBasis;
using AutoConnectSelect = AutoConnectSelectBasis;
@ -42,6 +44,7 @@ using AutoConnectText = AutoConnectTextBasis;
#define ACElement(n, v) AutoConnectElement n(#n, v)
#define ACButton(n, ...) AutoConnectButton n(#n, ##__VA_ARGS__)
#define ACCheckbox(n, ...) AutoConnectCheckbox n(#n, ##__VA_ARGS__)
#define ACFile(n, ...) AutoConnectFile n(#n, ##__VA_ARGS__)
#define ACInput(n, ...) AutoConnectInput n(#n, ##__VA_ARGS__)
#define ACRadio(n, ...) AutoConnectRadio n(#n, ##__VA_ARGS__)
#define ACSelect(n, ...) AutoConnectSelect n(#n, ##__VA_ARGS__)

@ -2,8 +2,8 @@
* Declaration of AutoConnectElement basic class.
* @file AutoConnectElementBasis.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-12-29
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
@ -17,12 +17,13 @@ typedef enum {
AC_Button,
AC_Checkbox,
AC_Element,
AC_File,
AC_Input,
AC_Radio,
AC_Select,
AC_Submit,
AC_Text,
AC_Unknown
AC_Unknown = -1
} ACElement_t; /**< AutoConnectElement class type */
typedef enum {
@ -90,6 +91,25 @@ class AutoConnectCheckboxBasis : virtual public AutoConnectElementBasis {
bool checked; /**< The element should be pre-selected */
};
/**
* File-select input arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled file-select input box that can be added by user sketch.
* @param name File-select input box name string.
* @param value A string value entered by the selected file name.
* @param label A label string that follows file-select box, optionally.
* The label is placed in front of file-select box.
*/
class AutoConnectFileBasis : virtual public AutoConnectElementBasis {
public:
explicit AutoConnectFileBasis(const char* name = "", const char* value= "", const char* label = "") : AutoConnectElementBasis(name, value), label(String(label)) {
_type = AC_File;
}
virtual ~AutoConnectFileBasis() {}
const String toHTML(void) const override;
String label; /**< A label for a subsequent input box */
};
/**
* Input-box arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled input-box that can be added by user sketch.

@ -2,8 +2,8 @@
* Implementation of AutoConnectElementBasis classes.
* @file AutoConnectElementImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-12-29
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
@ -46,6 +46,22 @@ const String AutoConnectCheckboxBasis::toHTML(void) const {
return html;
}
/**
* Generate an HTML <input type=file> element.
* The entered value can be obtained using the user callback function
* registered by AutoConnectAux::on after the form is sent in
* combination with AutoConnectSubmit.
* @return String an HTML string.
*/
const String AutoConnectFileBasis::toHTML(void) const {
String html = String("");
if (label.length())
html = String(F("<label for=\"")) + name + String(F("\">")) + label + String(F("</label>"));
html += String(F("<input type=\"file\" id=\"")) + name + String(F("\" name=\"")) + name + String(F("\"><br>"));
return html;
}
/**
* Generate an HTML <input type=text> element.
* If the value member is contained, it is reflected in the placeholder
@ -208,7 +224,12 @@ const String AutoConnectSubmitBasis::toHTML(void) const {
* @return String an HTML string.
*/
const String AutoConnectTextBasis::toHTML(void) const {
return String(F("<div style=\"")) + style + String("\">") + value + String(F("</div>"));
String html = String("<div");
if (style.length())
html += String(F(" style=\"")) + style + String("\"");
html += String(">") + value + String(F("</div>"));
return html;
}
#endif // _AUTOCONNECTELEMENTBASISIMPL_H_

@ -33,6 +33,7 @@
#define AUTOCONNECT_JSON_TYPE_ACBUTTON "ACButton"
#define AUTOCONNECT_JSON_TYPE_ACCHECKBOX "ACCheckBox"
#define AUTOCONNECT_JSON_TYPE_ACELEMENT "ACElement"
#define AUTOCONNECT_JSON_TYPE_ACFILE "ACFile"
#define AUTOCONNECT_JSON_TYPE_ACINPUT "ACInput"
#define AUTOCONNECT_JSON_TYPE_ACRADIO "ACRadio"
#define AUTOCONNECT_JSON_TYPE_ACSELECT "ACSelect"
@ -105,6 +106,27 @@ class AutoConnectCheckboxJson : public AutoConnectElementJson, public AutoConnec
void serialize(JsonObject& json) override;
};
/**
* File-select input arrangement class, a part of AutoConnectAux element.
* Place a optionally labeled file-select input box that can be added by user sketch.
* @param name File-select input box name string.
* @param value A string value entered by the selected file name.
* @param label A label string that follows file-select box, optionally.
* The label is placed in front of file-select box.
*/
class AutoConnectFileJson : public AutoConnectElementJson, public AutoConnectFileBasis {
public:
explicit AutoConnectFileJson(const char* name = "", const char* value= "", const char* label = "") {
AutoConnectFileBasis::name = String(name);
AutoConnectFileBasis::value = String(value);
AutoConnectFileBasis::label = String(label);
}
~AutoConnectFileJson() {}
size_t getObjectSize(void) const override;
bool loadMember(const JsonObject& json) override;
void serialize(JsonObject& json) override;
};
/**
* Input-box arrangement class, a part of AutoConnectAux element with
* handling JSON object.

@ -2,8 +2,8 @@
* Implementation of AutoConnectElementJson classes.
* @file AutoConnectElementImpl.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
@ -140,6 +140,42 @@ void AutoConnectCheckboxJson::serialize(JsonObject& json) {
json.set(F(AUTOCONNECT_JSON_KEY_CHECKED), checked);
}
/**
* Returns JSON object size.
* @return An object size for JsonBuffer.
*/
size_t AutoConnectFileJson::getObjectSize() const {
return AutoConnectElementJson::getObjectSize() + JSON_OBJECT_SIZE(1);
}
/**
* Load a file-select element attribute member from the JSON object.
* @param json JSON object with the definition of AutoConnectElement.
* @return true AutoConnectElement loaded
* @return false Type of AutoConnectElement is mismatched.
*/
bool AutoConnectFileJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE));
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACFILE))) {
_setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL));
return true;
}
return false;
}
/**
* Serialize AutoConnectFile to JSON.
* @param json JSON object to be serialized.
*/
void AutoConnectFileJson::serialize(JsonObject& json) {
_serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACFILE));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value);
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label);
}
/**
* Returns JSON object size.
* @return An object size for JsonBuffer.

Loading…
Cancel
Save