Commit 2bf25847 authored by Sven Franck's avatar Sven Franck

added replicate storage over local/erp5 storage. breaks all

parent a16a2965
{
"first_name": "Sven",
"last_name": "Franck",
"translated_validation_state_title": "Validated",
"default_address_city": "Bespin",
"default_email_text": "sven.franck@nexedi.com",
"default_telephone_text": "0190-123-456",
"default_address_street_address": "Blvd Clemenceau 2781234521",
"default_address_zip_code": "0",
"_debug": "document",
"_relative_url": "person_module/20140115-10A5B70",
"_actions": {
"request_ticket": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_requestTicketFromJio",
"method": "POST"
},
"request_computer_network": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_requestComputerNetworkFromJio",
"method": "POST"
},
"request": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_requestInstanceFromJio",
"method": "POST"
},
"request_computer": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_requestComputerFromJio",
"method": "POST"
}
},
"_embedded": {
"_view": {
"career_listbox": {
"line_list": [
{
"Function": null,
"Status": null,
"Begin": "XXX Serialize DateTime",
"End": "XXX Serialize DateTime",
"Title": "default_career",
"url": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/default_career/ERP5Document_getHateoas?portal_skin=Hal",
"Organisation": null,
"Grade": null,
"Role": "Member",
"ID": "default_career"
}
],
"type": "ListBox",
"column_list": [
"ID",
"Title",
"Organisation",
"Role",
"Grade",
"Function",
"Begin",
"End",
"Status"
]
},
"my_default_address_zip_code": {
"description": "The postal code",
"title": "Postal Code",
"default": "0",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_default_address_zip_code",
"hidden": 0,
"type": "StringField"
},
"my_default_image_absolute_url": {
"description": "",
"title": "Photo",
"default": "",
"css_class": "",
"required": 0,
"editable": 0,
"key": "field_my_default_image_absolute_url",
"hidden": 0,
"type": "ImageField"
},
"my_default_address_region": {
"description": "The region.",
"title": "Region",
"default": "",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_default_address_region",
"hidden": 0,
"type": "ListField"
},
"my_first_name": {
"description": "The first name of the person.",
"title": "First Name",
"default": "Sven",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_first_name",
"hidden": 0,
"type": "StringField"
},
"latest_content_listbox": {
"line_list": [],
"type": "ListBox",
"column_list": [
"Reference",
"Short Title",
"Validation State",
"Type",
"Creation Date",
"Modification Date"
]
},
"my_default_email_text": {
"description": "",
"title": "Email",
"default": "sven.franck@nexedi.com",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_default_email_text",
"hidden": 0,
"type": "EmailField"
},
"my_gender": {
"description": "The person's gender.",
"title": "Gender",
"default": "",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_gender",
"hidden": 0,
"type": "ListField"
},
"form_id": {
"description": "",
"title": "form_id",
"default": "Person_viewAsWeb",
"css_class": "",
"required": 1,
"editable": 0,
"key": "form_id",
"hidden": 1,
"type": "StringField"
},
"my_nationality": {
"description": "The person's nationality.",
"title": "Nationality",
"default": "",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_nationality",
"hidden": 0,
"type": "ListField"
},
"assignment_listbox": {
"line_list": [],
"type": "ListBox",
"column_list": [
"ID",
"Title",
"Organisation",
"Site",
"Group",
"Function",
"Activity",
"Begin",
"End",
"Status"
]
},
"my_last_name": {
"description": "The last name of the person.",
"title": "Last Name",
"default": "Franck",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_last_name",
"hidden": 0,
"type": "StringField"
},
"my_translated_validation_state_title": {
"description": "The current state of the document.",
"title": "State",
"default": "Validated",
"css_class": "",
"required": 0,
"editable": 0,
"key": "field_my_translated_validation_state_title",
"hidden": 0,
"type": "StringField"
},
"my_default_address_street_address": {
"description": "The street address.\n\nThis usually contains the street name, building number and apartment number (if any).",
"title": "Street Address",
"default": "Blvd Clemenceau 2781234521",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_default_address_street_address",
"hidden": 0,
"type": "TextAreaField"
},
"my_default_fax_text": {
"description": "",
"title": "FAX",
"default": "",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_default_fax_text",
"hidden": 0,
"type": "StringField"
},
"my_mobile_telephone_text": {
"description": "The mobile telephone number.",
"title": "Mobile Telephone",
"default": "",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_mobile_telephone_text",
"hidden": 0,
"type": "StringField"
},
"my_default_telephone_text": {
"description": "",
"title": "Telephone",
"default": "0190-123-456",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_default_telephone_text",
"hidden": 0,
"type": "StringField"
},
"my_career_subordination_title": {
"description": "The organisation for which the person works.",
"title": "Organisation",
"default": "",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_career_subordination_title",
"hidden": 0,
"type": "RelationStringField"
},
"my_default_address_city": {
"description": "The city.",
"title": "City",
"default": "Bespin",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_default_address_city",
"hidden": 0,
"type": "StringField"
},
"my_description": {
"description": "General description of a document in ERP5. Descriptions are not supposed to be internal, and in a case of certain documents such as invoices for example, will be seen by your customers.",
"title": "Description",
"default": "",
"css_class": "",
"required": 0,
"editable": 1,
"key": "field_my_description",
"hidden": 0,
"type": "TextAreaField"
},
"_embedded": {
"form_definition": {
"_links": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas?mode=form_definition&skin_id=Person_viewAsWeb",
"name": "Person_viewAsWeb"
},
"group_list": [
["left",
[
["my_first_name", {"meta_type": "ProxyField"}],
["my_last_name", {"meta_type": "ProxyField"}],
["my_career_subordination_title", {"meta_type": "ProxyField"}],
["my_gender", {"meta_type": "ProxyField"}],
["my_nationality", {"meta_type": "ProxyField"}]
]
],
["right",
[
["my_default_email_text", {"meta_type": "ProxyField"}],
["my_default_telephone_text", {"meta_type": "ProxyField"}],
["my_mobile_telephone_text", {"meta_type": "ProxyField"}],
["my_default_fax_text", {"meta_type": "ProxyField"}],
["my_default_address_street_address", {"meta_type": "ProxyField"}],
["my_default_address_zip_code", {"meta_type": "ProxyField"}],
["my_default_address_city", {"meta_type": "ProxyField"}],
["my_default_address_region", {"meta_type": "ProxyField"}],
["my_default_image_absolute_url", {"meta_type": "ProxyField"}],
["my_translated_validation_state_title", {"meta_type": "ProxyField"}]
]
],
["center",
[
["my_description", {"meta_type": "ProxyField"}]
]
],
["bottom",
[
["assignment_listbox", {"meta_type": "ProxyField"}],
["career_listbox", {"meta_type": "ProxyField"}],
["latest_content_listbox", {"meta_type": "ProxyField"}]
]
]
]
}
},
"_actions": {
"put": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_edit",
"method": "POST"
}
},
"_links": {
"self": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_viewAsWeb"
},
"form_definition": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas?mode=form_definition&skin_id=Person_viewAsWeb",
"name": "Person_viewAsWeb"
},
"context": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/ERP5Document_getHateoas",
"name": "person_module/20140115-10A5B70",
"title": "Sven Franck"
}
}
}
},
"_links": {
"slapos_jump": [
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas?query=portal_type%3A%22Hosting%20Subscription%22%20AND%20validation_state%3A%22validated%22%20AND%20default_destination_section_uid%3A22187208L&mode=search",
"name": "current_hosting_subscription",
"_query": "portal_type:\"Hosting Subscription\" AND validation_state:\"validated\" AND default_destination_section_uid:22187208L"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas?query=validation_state%3A%22validated%22%20AND%20portal_type%3A%22Computer%22%20AND%20default_strict_allocation_scope_uid%3A%21%3D%226697458%22&mode=search",
"name": "current_computer",
"_query": "validation_state:\"validated\" AND portal_type:\"Computer\" AND default_strict_allocation_scope_uid:!=\"6697458\""
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas?query=portal_type%3A%22Computer%20Network%22&mode=search",
"name": "current_network",
"_query": "portal_type:\"Computer Network\""
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas?query=NOT%20title%3A%22Reversal%20Transaction%20for%20%25%22%20AND%20portal_type%3A%22Sale%20Invoice%20Transaction%22%20AND%20default_destination_section_uid%3A22187208L&mode=search",
"name": "current_invoice",
"_query": "NOT title:\"Reversal Transaction for %\" AND portal_type:\"Sale Invoice Transaction\" AND default_destination_section_uid:22187208L"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas?query=portal_type%3A%28%22Support%20Request%22%20OR%20%22Regularisation%20Request%22%29%20AND%20default_destination_decision_uid%3A22187208L&mode=search",
"name": "current_ticket",
"_query": "portal_type:(\"Support Request\" OR \"Regularisation Request\") AND default_destination_decision_uid:22187208L"
}
],
"action_object_search": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Folder_viewSearchDialog",
"name": "search",
"title": "Search"
},
"action_object_jump": [
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_jumpToAccountingTransaction?from_entity=1",
"name": "jump_to_accounting",
"title": "Accounting"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_jumpToRelatedObject?base_category=destination_section&portal_type=Hosting+Subscription",
"name": "jump_to_hosting_subscription",
"title": "Hosting Subscriptions"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_jumpToRelatedObject?base_category=destination&portal_type=Sale+Packing+List",
"name": "jump_to_sale_packing_list",
"title": "Sale Packing List"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_jumpToRelatedObject?base_category=destination_decision&portal_type=Credential+Update",
"name": "jump_to_credential_update",
"title": "Credential Update"
}
],
"self": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/ERP5Document_getHateoas"
},
"action_object_web_view": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_viewAsWeb",
"name": "web_view",
"title": "Web View"
},
"action_user": [
{
"href": "https://www.tiolive.com/vifiberp5/personalize_form",
"name": "preferences",
"title": "Preferences"
},
{
"href": "https://www.tiolive.com/vifiberp5/logout",
"name": "logout",
"title": "Log out"
}
],
"site_root": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/ERP5Document_getHateoas",
"name": "Hateoas"
},
"action_object_view": [
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_view",
"name": "view",
"title": "View"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_viewDetails",
"name": "details",
"title": "Details"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_viewAssignment",
"name": "assignment",
"title": "Assignments"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Entity_viewAccountingTransactionList",
"name": "transactions",
"title": "Transactions"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_viewFinancialInformationList",
"name": "financial_view",
"title": "Financial Information"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewDocumentList",
"name": "document_view",
"title": "Documents"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewEventList",
"name": "view_event_list",
"title": "Events"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewContentTranslation",
"name": "content_translation",
"title": "Translation"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewHistory",
"name": "history",
"title": "History"
}
],
"action_object_action": [
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_resetPassword",
"name": "reset_password",
"title": "Reset Password"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Person_shiftDefaultCareer",
"name": "terminate_career",
"title": "Terminate the Current Career Step"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewAddEventDialog",
"name": "add_event",
"title": "Create New Event"
}
],
"action_global": {
"href": "https://www.tiolive.com/vifiberp5/ERP5Site_viewNewPersonCredentialUpdateDialog",
"name": "update_credentials",
"title": "Update Credentials"
},
"action_object_sort": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Folder_viewSortOnDialog",
"name": "sort_on",
"title": "Sort"
},
"action_object_ui": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewUIDialog",
"name": "list_ui",
"title": "Modify UI"
},
"action_object_report": [
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/accounting_module/AccountModule_viewGeneralLedgerReportDialog?mirror_section=person_module/20140115-10A5B70",
"name": "general_ledger_report",
"title": "General Ledger"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/accounting_module/AccountModule_viewAccountStatementReportDialog?mirror_section=person_module/20140115-10A5B70",
"name": "account_statement_report",
"title": "Account Statement"
}
],
"action_object_button": [
{
"href": "https://www.tiolive.com/vifiberp5/accounting_module/AccountingTransactionModule_viewGroupingFastInputDialog?reset:int=1&mirror_section=person_module/20140115-10A5B70",
"name": "grouping_reference_fast_input",
"title": "Grouping Reference Fast Input"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewNewFileDialog",
"name": "create_new_file",
"title": "Attach Document"
}
],
"type": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/portal_types/Person/ERP5Document_getHateoas",
"name": "Person"
},
"action_object_exchange": [
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/accounting_module/AccountModule_viewGeneralLedgerReportDialog?mirror_section=person_module/20140115-10A5B70&your_portal_skin=ODS&your_format=",
"name": "general_ledger_export",
"title": "General Ledger"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/accounting_module/AccountModule_viewAccountStatementReportDialog?mirror_section=person_module/20140115-10A5B70&your_portal_skin=ODS&your_format=",
"name": "account_statement_export",
"title": "Account Statement"
},
{
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewAsODSDialog",
"name": "ods_export",
"title": "Export to Spreadsheet"
}
],
"action_object_print": {
"href": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas/person_module/20140115-10A5B70/Base_viewPrintDialog",
"name": "print",
"title": "Print"
}
}
}
\ No newline at end of file
{
"property_dict": {},
"children": [
{
"type": "p",
"direct": {"className": "translate"},
"attributes": {"data-i18n": "global_dict.find_out_more_details"},
"logic": {"text": "For additional information, please refer to the following sections:"}
},
{
"generate": "widget",
"type": "listview",
"class_list": null,
"theme": "slapos-black",
"form": null,
"property_dict": {
"inset": true
},
"children": [
{"type": "item", "href": "http://community.slapos.org/wiki", "external": true, "left": {"icon":"book"}, "center": {"text": [{"type": "h1", "text": "Documentation", "text_i18n":"global_dict.documentation"}]}},
{"type": "item", "href": "http://community.slapos.org/download", "external": true, "left": {"icon":"download"}, "center": {"text": [{"type": "h1", "text": "Download", "text_i18n":"global_dict.download"}]}},
{"type": "item", "href": "http://community.slapos.org/forum", "external": true, "left": {"icon":"comments-alt"}, "center": {"text": [{"type": "h1", "text": "Forum", "text_i18n":"global_dict.forum"}]}},
{"type": "item", "href": "http://community.slapos.org/blog", "external": true, "left": {"icon":"rss-sign"}, "center": {"text": [{"type": "h1", "text": "Blog", "text_i18n":"global_dict.blog"}]}},
{"type": "item", "href": "http://www.vifib.com/vifib-Pricing", "external": true, "left": {"icon":"dollar"}, "center": {"text": [{"type": "h1", "text": "Pricing", "text_i18n":"global_dict.pricing"}]}}
]
}
]
}
\ No newline at end of file
......@@ -22,10 +22,17 @@
"type": "makeStorage",
"property_dict": {
"definition": {
"type":"hateoas",
"username":"slapos",
"url": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas",
"application_name": "items"
"type": "replicate",
"storage_list": [{
"type":"hateoas",
"username":"slapos",
"url": "https://www.tiolive.com/vifiberp5/web_site_module/hateoas",
"application_name": "items"
}, {
"type": "local",
"username": "slapos",
"application_name": "items"
}]
}
}
}]
......
......@@ -22,6 +22,7 @@
<script type="text/javascript" src="js/libs/jio/complex_queries.js"></script>
<script type="text/javascript" src="js/libs/jio/localstorage.js"></script>
<script type="text/javascript" src="js/libs/uritemplate/uritemplate-min.js"></script>
<script type="text/javascript" src="js/libs/jio/replicatestorage.js"></script>
<script type="text/javascript" src="js/libs/jio/hateoasstorage.js"></script>
<!-- plugins -->
......
var priv = {};
/* ====================================================================== */
/* ERP5 CONVERTER */
/* ====================================================================== */
// since we are making something generic!
/**
* map ERP5 field type to HTML elements
* @method mapFieldType
* @param {string} type ERP5 field type
* @return {string} element
*/
priv.mapFieldType = function (type) {
var element;
switch (type) {
case "StringField":
case "RelationStringField":
case "IntegerField":
element = "input";
break;
case "ListField":
element = "select";
break;
case "TextareaField":
element = "textarea";
break;
};
return element;
};
/**
* map ERP5 field type to input type
* @method mapFieldType
* @param {string} type ERP5 field type
* @return {string} element
*/
priv.mapInputType = function (type) {
var field_type = null;
switch (type) {
case "StringField":
case "RelationStringField":
field_type = "text";
break;
case "IntegerField":
field_type = "number";
break;
}
return field_type;
};
/**
* Build a string from array
* @method: buildValue
* @param: {string/array} value String/Array passed
* @returns: {string} string
*/
priv.buildValue = function (value) {
var i = 0,
setter = "",
property;
if (typeof value === "string") {
setter = value;
} else if (typeof value === "object") {
for (property in value) {
if (value.hasOwnProperty(property)) {
setter += (i === 0 ? "" : ", ") + value[property];
i += 1
}
}
} else {
for (i; i < value.length; i += 1) {
setter += (i === 0 ? "" : ", ") + value[i];
}
}
return setter || "could not generate value";
};
/**
* Append values in form
* @method: setValue
* @param: {string} type Type of object
* @param: {string} key Key to set
* @param: {string/array} value Value to set key to
*/
priv.setValue = function (type, key, value) {
var i,
j,
k,
unit,
element,
getter,
single_option,
elements = document.getElementsByName(type + "_" + key),
setter = priv.buildValue(value),
// ...PFFFFFFFFFFFFFF standards require so much customization...
dublin_core_date_time_fields = [
"date",
"created",
"modified",
"effective_date",
"expiration_date"
],
time_fields = ["year", "month", "day"];
// can't be generic... yet
for (i = 0; i < dublin_core_date_time_fields.length; i += 1) {
if (key === dublin_core_date_time_fields[i]) {
for (k = 0; k < time_fields.length; k += 1) {
unit = time_fields[k];
element = document.getElementsByName(
type + "_" + key + "_" + unit
);
if (element.length > 0) {
single_option = element[0].getElementsByTagName("option");
switch(unit) {
case "year":
getter = new Date(setter).getFullYear();
break;
case "month":
getter = new Date(setter).getMonth() + 1;
break;
case "day":
getter = new Date(setter).getDate();
break;
}
if (single_option.length === 1) {
single_option[0].setAttribute("value", getter);
single_option[0].text = getter;
single_option[0].parentNode.parentNode.getElementsByTagName("span")[0].innerHTML = getter;
} else {
element[0].value = getter;
}
}
}
}
}
for (j = 0; j < elements.length; j += 1) {
elements[j].value = setter;
}
};
/**
* Generate input form for an item
* @method generateItem
* @param {string} mode View Clone/Edit/Add
* @param {string} item Element to show
*/
// NOTE: this should be in another gadget/file
priv.generateItem = function (mode, item) {
if (item) {
// fetch data
priv.erp5.get({"_id": item}, function (error, response) {
var property, value, abort;
if (response) {
for (property in response) {
if (response.hasOwnProperty(property)) {
value = response[property];
priv.setValue(response.type.toLowerCase(), property, value);
}
}
} else {
abort = confirm("Error trying to retrieve data! Go back to overview?");
if (abort === true) {
$.mobile.changePage("computers.html");
}
}
});
}
};
/**
* Create a serialized object from all values in the form
* @method serializeObject
* @param {object} form Form to serialize
* @returns {string} JSON form values
*/
priv.serializeObject = function(form) {
var o = {};
var a = form.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
// date conversion object container
priv.dates = {};
/**
* Create a serialized object from all values in the form
* @method validateObject
* @param {object} serialized object
* @returns {object} object ready to pass to JIO
*/
// TODO: should be made generic by passing the type and a recipe for
// which fields to format how
priv.validateObject = function (object) {
var validatedObject = {},
property,
setter,
value,
i,
j,
clean_property,
add_property,
date_property,
date_component,
new_date,
// NOTE: ... to time to be generic...
convertToArray = ["contributor", "category"],
seperator_character = ",",
convertToDate = ["effective_date", "expiration_date"];
for (property in object) {
add_property = true;
if (object.hasOwnProperty(property)) {
value = object[property];
clean_property = property.replace("computer_", "");
// multiple entries
if (typeof value !== "string") {
if(value.length > 0) {
// this should only happen if a field is in the form multiple times!
// NOTE: not nice
setter = value[0];
}
} else {
setter = value;
}
// convert to array
for (i = 0; i < convertToArray.length; i += 1) {
if (convertToArray[i] === clean_property ) {
setter = object[property].split(seperator_character);
}
}
// set up date conversion
for (j = 0; j < convertToDate.length; j += 1) {
date_property = convertToDate[j];
if (clean_property.search(date_property) !== -1) {
add_property = false;
if (priv.dates[date_property] === undefined) {
priv.dates[date_property] = {};
}
// ...
date_component = clean_property.split("_")[2];
priv.dates[date_property][date_component] = value;
}
}
if (add_property) {
validatedObject[clean_property] = setter;
}
}
}
// timestamp modified
validatedObject.modified = new Date().toJSON();
// timestamp create and date
if (validatedObject.date === undefined) {
validatedObject.date = validatedObject.modified;
}
if (validatedObject.create === undefined) {
validatedObject.create = validatedObject.modified;
}
// HACK: add missing type!
if (validatedObject.type === undefined || validatedObject.type === "") {
validatedObject.type = "Computer";
}
// build dates
for (date in priv.dates) {
if (priv.dates.hasOwnProperty(date)) {
new_date = priv.dates[date];
validatedObject[date] = new Date(
new_date["year"], new_date["month"], new_date["day"]
).toJSON();
// delete this date
delete priv.dates[date];
}
}
return validatedObject;
}
/**
* Store object in EPR5
* @method modifyObject
* @param {object} object Validated object
* @param {method} string PUT or POST
*/
priv.modifyObject = function (object, method, callback) {
priv.erp5[method](object, function (error, response) {
if (error) {
alert("oops..., an error occurred trying to store");
} else {
alert("worked");
if (callback) {
callback();
}
}
});
};
/**
* Create array of URL parameters
* @method splitSearchParams
* @param {string} url URL to split
* @returns {array} array of url parameters
*/
priv.splitSearchParams = function (url) {
var path;
if (url === undefined) {
path = window.location;
} else {
path = url;
}
return $.mobile.path.parseUrl(path).search.slice(1).split("&");
}
/**
* Replace substrings to another strings
* @method recursiveReplace
* @param {string} string The string to do replacement
* @param {array} list_of_replacement An array of couple
* ["substring to select", "selected substring replaced by this string"].
* @return {string} The replaced string
*/
priv.recursiveReplace = function (string, list_of_replacement) {
var i, split_string = string.split(list_of_replacement[0][0]);
if (list_of_replacement[1]) {
for (i = 0; i < split_string.length; i += 1) {
split_string[i] = priv.recursiveReplace(
split_string[i],
list_of_replacement.slice(1)
);
}
}
return split_string.join(list_of_replacement[0][1]);
};
/**
* Changes & to %26
* @method convertToUrlParameter
* @param {string} parameter The parameter to convert
* @return {string} The converted parameter
*/
priv.convertToUrlParameter = function (parameter) {
return priv.recursiveReplace(parameter, [[" ", "%20"], ["&", "%26"]]);
};
/**
* Create a URL string for authentication (same as ERP5 storage)
* @method createEncodedLogin
*/
priv.createEncodedLogin = function () {
return "__ac_name=" + priv.convertToUrlParameter(priv.username) +
"&" + (typeof priv.password === "string" ?
"__ac_password=" +
priv.convertToUrlParameter(priv.password) + "&" : "");
};
/**
* Modify an ajax object to add default values
* @method makeAjaxObject
* @param {object} json The JSON object
* @param {object} option The option object
* @param {string} method The erp5 request method
* @param {object} ajax_object The ajax object to override
* @return {object} A new ajax object with default values
*/
priv.makeAjaxObject = function (key) {
var ajax_object = {};
ajax_object.url = priv.url + key + "?" + priv.createEncodedLogin() + "disable_cookie_login__=1";
// exception: ajax_object.url = priv.username + ":" + priv.password + "@" + priv.url + key;
ajax_object.dataType = "text/plain";
ajax_object.async = ajax_object.async === false ? false : true;
ajax_object.crossdomain = ajax_object.crossdomain === false ? false : true;
return ajax_object;
};
/**
* Runs all ajax requests for propertyLookups
* @method getERP5property
* @param {string} id The id of the object to query
* @param {string} lookup The method to retrieve the property
* @return {string} The property value
*/
// NOTE: need a different way because this triggers a ton of http requests!
priv.getERP5property = function (id, lookup) {
var key = id + "/" + lookup;
// return $.ajax(priv.makeAjaxObject(key));
return {"error":"foo"}
};
/* ********************************************************************** */
/* TAB FIELD LIST */
/* ********************************************************************** */
/**
* Create tab menu
* @method constructTabs
* @param {object} element Base table to enhance
* @param {string} mode View to display
* @param {string} item Id of item to display
* @param {object} properties Properties of item to display
* @returns {object} html object / deferred
*/
priv.constructTabs = function (element, mode, item, properties) {
var property,
value,
abort,
i,
j,
k,
set,
collapsible,
tab,
tag,
box,
content,
wrap,
field,
overrides,
config,
exist,
validate,
element_wrap,
fragment = window.document.createDocumentFragment(),
// tab config
gadget_id = element.getAttribute("data-gadget-id"),
settings = priv.gadget_properties[gadget_id],
portal_type = settings.portal_type_title,
// wrapper - could be a slot, too
$parent = $(element.parentNode);
// TODO: get settings here if not loaded
if (settings !== undefined) {
// tab container
set = priv.generateElement(
"div",
{"className": "ui-dynamic-tabs"},
{"data-role": "collapsible-set", "data-tabs": settings.layout.length || 1, "data-type": "tabs"}
);
// tabs
for (i = 0; i < settings.layout.length; i += 1) {
tab = settings.layout[i];
collapsible = priv.generateElement(
"div",
{},
{"data-role":"collapsible", "data-icon":"false", "data-collapsed": i === 0 ? false : true}
);
collapsible.appendChild(priv.generateElement(
"h1",
{"className":"translate"},
{"data-i18n": tab.i18n},
{"text": tab.title}
));
if (tab.blocks !== undefined) {
for (j = 0; j < tab.blocks.length; j += 1) {
box = tab.blocks[j];
// content element
content = priv.generateElement(
"div",
{"className": box.fullscreen ? " content_element_fullscreen content_element" : "content_element"}
);
// fields
if (box.fields) {
for (k = 0; k < box.fields.length; k += 1) {
field = box.fields[k];
config = priv.field_definitions[portal_type][field];
overrides = box.overrides[field] || {};
// all-in-one...
content.appendChild(priv.generateFormField(config, overrides));
}
fragment.appendChild(content);
}
// actions
if (box.actions) {
for (l = 0; l < box.actions.length; l += 1) {
content.appendChild(priv.generateControlgroup(box.actions[l]));
}
}
// nested gadgets ASYNC
if (box.view) {
// $.when(priv[box.view.renderWith](content, box.view.gadget_id)).then(function(fragment) {
// $(fragment.target).append(fragment.element).enhanceWithin();
// });
}
collapsible.appendChild(content);
}
}
set.appendChild(collapsible);
}
// add dynamic tabs
if (settings.configuration.editable) {
collapsible = priv.generateElement("div",
{"className": "dashed add_tab"},
{"data-role":"collapsible", "data-icon": "plus", "data-expanded-icon":"plus"},
{}
);
collapsible.appendChild(priv.generateElement("h1",
{"className":"translate"},
{"data-i18n": "generic.layouts.tabs.add"},
{"text":"Add tab"}
)
);
set.appendChild(collapsible);
}
fragment.appendChild(set);
if (settings.configuration.editable) {
fragment.appendChild(
priv.generateElement("p",
{"className":"center ui-dynamic-info translate"},
{"data-i18n": "generic.messages.tabs.empty"},
{"text":"Your dashboard is empty. Click above to add tabs and gadgets displaying key information to your dashboard."}
)
);
}
// la viola - we touch the DOM once!!
$parent.empty().append( fragment ).enhanceWithin();
} else {
element.appendChild(
priv.generateElement("p",
{"className":"center translate"},
{"data-i18n": "generic.errors.no_settings"},
{"text": "Error: No configuration available for this type of data!"}
)
);
}
};
/* ********************************************************************** */
/* action menu */
/* ********************************************************************** */
/*
* Creates a controlgroup (just a passthrough method)
* @constructActionMenu
* @param {object} element Wrapper element
* @returns {object} document fragment
*/
priv.constructActionMenu = function (element) {
var gadget_id = element.getAttribute("data-gadget-id"),
settings = priv.gadget_properties[gadget_id],
portal_type = settings.portal_type_title,
$parent = $(element.parentNode);
fragment = priv.generateControlgroup(settings.layout);
$(element.parentNode).empty().append( fragment ).enhanceWithin();
};
/* ====================================================================== */
/* SETUP */
/* ====================================================================== */
// NOTE: custom, content generation methods = non generic stuff needed to
// display custom content. Above this section = generic, below = custom
/* ********************************************************************** */
/* table search/config methods */
/* ********************************************************************** */
/**
* generates a popup contents
* @method generatePopupContents
* @param {object} e Event that triggered opening a popup
* @param {string} type Pointer to object holding popup config info
* @param {string} portal_type To be loaded and referenced
* @param {object} view gadget Configuration properties (pass through)
* @oaram {string} gadget_id
*/
priv.generatePopupContents = function (e, type, portal_type, view, gadget_id) {
var property,
i,
field,
popup_body,
popup_content,
popup_message,
popup_title,
popup_info,
popup_method,
element,
reference,
popup = document.getElementById(e.target.href.split("#")[1]),
state = popup.getAttribute("data-state");
switch(type) {
case "self":
reference = e.target.getAttribute("data-reference");
// portal_type should be defined
break;
case "action":
element = e.target.parentNode.getElementsByTagName("input")[0];
reference = element.getAttribute("data-reference");
portal_type = element.getAttribute("data-relation");
break;
};
// only regenerate the popup if switching content
if (state !== reference) {
popup_body = document.createDocumentFragment();
switch (reference) {
// NOTE: table wrapper configure menu
// TODO: a global dump for reusable button config would be nice!
case "configure":
popup_title = "Configuration";
popup_info = "Please select columns to display and priority of display on smaller screens (6-1). Drag columns to modify the order of display"
popup_methods = ["generatePortalTypeFieldSelector", "generateDefaultColumnConfig"];
popup_footer = {
"type": "controlgroup",
"direction": "horizontal",
"class": "ui-grid ui-table-wrapper-bottom ui-table-wrapper-inset ui-corner-all",
"controls_class": "ui-grid-3",
"buttons": [
{
"type": "a",
"direct": {"className": "ui-grid-button ui-link ui-btn ui-icon-remove ui-btn-icon-right ui-shadow ui-corner-all ui-first-child"},
"attributes": {"data-i18n": "", "data-enhanced":"true", "data-role": "button", "data-iconpos": "right", "data-icon":"remove", "data-rel": "back"},
"logic": {"text":"Cancel"}
}, {
"type": "a",
"direct": {"className": "ui-grid-button table_action ui-link ui-btn ui-icon-refresh ui-btn-icon-right ui-shadow ui-corner-all"},
"attributes": {"data-i18n": "", "data-enhanced":"true", "data-role": "button", "data-iconpos": "right", "data-icon":"refresh", "data-action": "rest"},
"logic": {"text":"Reset"}
}, {
"type": "a",
"direct": {"className": "ui-grid-button table_action ui-btn-active ui-link ui-btn ui-icon-save ui-btn-icon-right ui-shadow ui-corner-all ui-last-child"},
"attributes": {"data-i18n": "generic.buttons.save", "data-role": "button", "data-iconpos": "right", "data-icon":"save", "data-action": "save"},
"logic": {"text":"Save"}
}
]
};
popup_action = "add_criteria_config";
popup_hint = "Add Columns";
break;
// NOTE: table wrapper detail search
case "details":
popup_title = "Detail Search";
popup_info = "Create a multi field search by adding fields below. For faster lookups, you can save your search criteria if needed."
popup_methods = ["generatePortalTypeFieldSelector"];
popup_footer = {
"type": "controlgroup",
"direction": "horizontal",
"class": "ui-grid ui-table-wrapper-bottom ui-table-wrapper-inset ui-corner-all",
"controls_class": "ui-grid-2",
"buttons": [
{
"type": "a",
"direct": {"className": "ui-grid-button ui-link ui-btn ui-icon-remove ui-btn-icon-right ui-shadow ui-corner-all ui-first-child"},
"attributes": {"data-i18n": "", "data-enhanced":"true", "data-role": "button", "data-iconpos": "right", "data-icon":"remove", "data-rel": "back"},
"logic": {"text":"Cancel"}
}, {
"type": "a",
"direct": {"className": "ui-grid-button table_action ui-btn-active ui-link ui-btn ui-icon-search ui-btn-icon-right ui-shadow ui-corner-all ui-last-child"},
"attributes": {"data-i18n": "", "data-enhanced":"true", "data-role": "button", "data-iconpos": "right", "data-icon":"search", "data-action": "search"},
"logic": {"text":"Search"}
}
]
};
popup_action = "add_criteria_search";
popup_hint = "Select Search Criteria";
break;
}
// header
if (popup_title) {
popup_body.appendChild(priv.generateHeader({"title":popup_title}));
}
// content
popup_content = priv.generateElement("div", {"className":"ui-content"},{"data-role":"content"},{});
if (popup_info) {
popup_content.appendChild(priv.generateElement("p", {},{},{"text": popup_info || null}));
}
// data
for (i = 0; i < popup_methods.length; i += 1) {
popup_content.appendChild( priv[popup_methods[i]]( view, gadget_id, popup_action, popup_hint ) );
}
popup_body.appendChild( popup_content);
// footer
if (popup_footer) {
popup_body.appendChild( priv.generateFooter(popup_footer));
}
popup.setAttribute("data-state", reference);
popup.setAttribute("data-type", portal_type);
// empty popup
popup.innerHTML = "";
// add content directly
$(popup).append( popup_body ).enhanceWithin();
}
};
/**
* generates a detail search field for the portal_type
* @method generatePortalTypeFieldSelector
* @param {object} table The table configuration
* @return {object} element The element fragment
*/
priv.generatePortalTypeFieldSelector = function (table, gadget_id, action, hint) {
var controls,
property,
config,
unique_field_name,
all_options = [];
for (property in table) {
if (table.hasOwnProperty(property)) {
field = table[property];
unique_field_name = "search_" + gadget_id + "_" + property;
all_options.push({
"value":gadget_id + ":" + property,
"text": priv.capFirstLetter(property)
});
}
}
controls = priv.generateElement("div",
{"className":"ui-controlgoup ui-controlgroup-horizontal ui-popup-menu"},
{"data-role":"controlgroup", "data-type":"horizontal"},
{}
);
controls.appendChild(priv.generateElement("label",
{"className": "ui-hidden-accessible"},{"for": action + "_" + gadget_id}, {"text": hint}
));
controls.appendChild(priv.generateElement("select",
{"name": action + "_" + gadget_id, "id": action + "_" + gadget_id },
{},
{"options": all_options}
));
controls.appendChild(priv.generateElement("a",
{"className": "responsive ui-btn-active table_action"},
{"data-role":"button", "data-iconpos":"right", "data-icon":"plus", "data-action":action},
{"text":"Add"}
));
return controls;
};
/**
* generates a grid configuration entry
* @method generateConfigCriteria
* @param {object} element clicked element
*/
priv.generateConfigCriteria = function (element, id, prop) {
var field,
property,
grid,
cell,
i,
unique_field_name,
prev,
val,
portal_type,
property;
if (typeof element === "object") {
prev = element.previousSibling.getElementsByTagName("select")[0],
val = prev.options[prev.selectedIndex].value,
gadget_id = val.split(":")[0],
property = val.split(":")[1];
} else {
val = "skip";
gadget_id = id;
property = prop;
}
if (val === "" || val === undefined) {
alert("Please select a valid column!");
} else {
// look up field in gadget_id, generate grid and add it to form
field = priv.gadget_properties[gadget_id].view[property];
if (field) {
unique_field_name = "configure_" + gadget_id + "_" + property;
grid = priv.generateElement("div",
{"className":"ui-grid-d ui-grid-row"}, {}, {"grid":5}
);
for (i = 0; i < grid.childNodes.length; i += 1) {
cell = grid.childNodes[i];
switch(i) {
case 0:
cell.className = "ui-block-a ui-grid-title";
cell.appendChild(priv.generateElement("span",
{}, {}, {"text": priv.capFirstLetter(property)}
));
break;
case 1:
cell.className = "ui-block-b";
cell.appendChild(priv.generateElement("label",
{"className": "ui-hidden-accessible"},
{"for": unique_field_name + "_priority"},
{"text": "Set priority"}
));
cell.appendChild(priv.generateElement("input",
{
"name": unique_field_name + "_priority",
"id": unique_field_name + "_priority",
"min":1,
"max":6,
"type":"number",
"value": field.priority || ""
},
{"data-mini": "true"},
{"disabled": field.priority === undefined ? "disabled" : null}
));
break;
case 2:
cell.className = "ui-block-c";
cell.appendChild(priv.generateElement("label",
{"className": "ui-hidden-accessible"},
{"for": unique_field_name + "_toggle"},
{"text": "Set visibility"}
));
cell.appendChild(priv.generateElement("select",
{"name": unique_field_name + "_toggle", "id": unique_field_name + "_toggle"},
{"data-mini": "true", "data-role":"slider"},
{
"disabled": field.priority === undefined ? "disabled" : null,
"options": [
{"text": "Show", "value": "on", "selected": field.show ? "selected": null},
{"text": "Hide", "value": "off", "selected": field.show ? "selected": null}
]
}
));
break;
case 3:
cell.className = "ui-block-d";
cell.appendChild(priv.generateElement(
"label",
{"className": "ui-hidden-accessible"},
{"for": unique_field_name + "_sort"},
{"text": "Set sorting"})
);
cell.appendChild(priv.generateElement("select",
{"name": unique_field_name + "_sort", "id": unique_field_name + "_sort"},
{"data-mini": "true", "data-role":"slider"},
{
"disabled": field.priority === undefined ? "disabled" : null,
"options": [
{"text": "Sort", "value": "on", "selected": field.show ? "selected": null},
{"text": "Static", "value": "off", "selected": field.show ? "selected": null}
]
}
));
break;
case 4:
cell.className = "ui-block-e ui-grid-action";
cell.appendChild(priv.generateElement("a",
{"className":"table_action"},
{"data-role":"button", "data-icon":"delete", "data-iconpos":"notext", "data-action":"delete_criteria"},
{"text":"Delete"}
));
break;
};
}
return grid;
} else {
alert("Field name does not exist in field defition list!");
}
}
};
/**
* generates a grid search criteria entry
* @method generateSearchCriteria
* @param {object} element clicked element
*/
priv.generateSearchCriteria = function (element) {
var grid,
cell,
opts = [],
i,
j,
field,
new_form,
prev = element.previousSibling.getElementsByTagName("select")[0],
val = prev.options[prev.selectedIndex].value,
portal_type = val.split(":")[0],
property = val.split(":")[1],
form = $( element ).closest(".ui-popup").find("form");
// form should be create here instead to keep column selector generic
if (form.length === 0) {
new_form = document.createElement("form");
}
if (val === "" || val === undefined) {
alert("Please select a valid criteria!");
} else {
// look up field in portal_type, generate grid and add it to form
field = priv.gadget_properties[portal_type].view[property];
if (field) {
grid = priv.generateElement("div",
{"className":"ui-grid-d ui-grid-row"}, {}, {"grid":4}
);
for (i = 0; i < grid.childNodes.length; i += 1) {
cell = grid.childNodes[i];
switch(i) {
case 0:
cell.className = "ui-block-a ui-grid-title";
cell.appendChild(priv.generateElement("span",
{}, {}, {"text": priv.capFirstLetter(property)}
));
break;
case 1:
cell.className = "ui-block-b ui-grid-search";
if (field.search !== undefined) {
cell.appendChild(priv.generateElement("label",
{"className": "ui-hidden-accessible"},
{"for": "run_search_" + portal_type + "_" + property},
{"text": "Search Term"})
);
switch(field.search.type) {
case "text":
cell.appendChild(priv.generateElement("input",
{
"name": "run_search_" + portal_type + "_" + property,
"id": "run_search_" + portal_type + "_" + property,
"type": field.search.type
},
{"data-clear-btn": "true"}
));
break;
case "select":
for (j = 0; j < field.search.options.length; j += 1) {
if (j === 0) {
opts.push({"value":"","text":"", "selected":"selected"})
}
opts.push({"value":field.search.options[j], "text":field.search.options[j]})
}
cell.appendChild(priv.generateElement("select",
{"name": "run_search_" + portal_type + "_" + property, "id": "run_search_" + portal_type + "_" + property,},
{},
{"options": opts}
));
break;
}
}
break;
case 2:
cell.className = "ui-block-c ui-grid-search";
if (field.search !== undefined) {
cell.appendChild(priv.generateElement("label",
{"className": "ui-hidden-accessible"},
{"for": "run_search_finetune_" + portal_type + "_" + property},
{"text": "Specify"})
);
switch(field.search.subsearch) {
case "flip":
for (i = 0; i < field.search.options.length; i += 1) {
opts.push({"value":field.search.options[i], "text":field.search.options[i], "selected": i === 0 ? "selected" : null})
}
cell.appendChild(priv.generateElement("select",
{"name": "run_search_finetune_" + portal_type + "_" + property, "id": "run_search_finetune_" + portal_type + "_" + property},
{"data-mini":"true", "data-role":"slider"},
{"options": opts}
));
break;
case "checkbox":
cell.lastChild.className = "";
cell.appendChild(priv.generateElement("input",
{
"name":"run_search_finetune_" + portal_type + "_" + property,
"id":"run_search_finetune_" + portal_type + "_" + property,
"type":"checkbox",
"value": field.search.value
},
{"data-mini":"true"},
{}
));
break;
};
}
break;
case 3:
cell.className = "ui-block-e ui-grid-action";
cell.appendChild(priv.generateElement("a",
{"className":"table_action"},
{"data-role":"button", "data-icon":"delete", "data-iconpos":"notext", "data-action":"delete_criteria"},
{"text":"Delete"}
));
break;
}
}
// first row
if (form.length === 0) {
new_form.appendChild(grid);
return new_form;
}
// other rows
return grid;
} else {
alert("Field name does not exist in field defition list!");
}
}
};
/**
* generates a configuration form for the portal_type
* @method generateDefaultColumnConfig
* @param {object} table The table configuration
* @return {object} element The element fragment
*/
priv.generateDefaultColumnConfig = function (table, gadget_id) {
var element = priv.generateElement("form",
{"className": "draggable"}, {"data-sortable":"true"}, {}
);
for (property in table) {
if (table.hasOwnProperty(property)) {
field = table[property];
if (field.show) {
element.appendChild(priv.generateConfigCriteria("none", gadget_id, property));
}
}
}
return element;
};
/* ********************************************************************** */
/* login popup */
/* ********************************************************************** */
// NOTE: This should be loaded as the HTML content of a login gadget
// TODO: convert to JSON configuration!
/**
* Generates the content of the login popup
* @method generateLoginPopup
* @return {object} HTML fragment
*/
priv.generateLoginPopup = function () {
var popup_element,
external,
// NOTE: in case we need a classic login (yet again) uncomment below
//internal,
//form,
//note,
p,
img,
content,
info,
hint = document.createDocumentFragment(),
login_form = document.createDocumentFragment(),
popup_content = document.createDocumentFragment(),
img = priv.generateElement(
"div", {"className": "popup_element logo_wrap"}
);
img.appendChild(priv.generateElement(
"img", {"src":"img/slapos.png", "alt": "slapos logo"}
));
popup_content.appendChild(img);
login_form.appendChild(priv.generateElement(
"p",{},{},{"text":"Sign in using"}
));
external = priv.generateElement(
"div",
{"className":"ui-controlgroup"},
{"data-role":"controlgroup"}
);
//internal = external.cloneNode();
external.appendChild(priv.generateElement(
"a",
{"href":"#", "className":"signin_google ui-link ui-btn ui-icon-google-plus-sign ui-btn-icon-left ui-first-child"},
{"data-role":"button", "data-icon":"google-plus-sign", "data-iconpos":"left", "data-enhanced":"true"},
{"text":"Google"}
));
external.appendChild(priv.generateElement(
"a",
{"href":"#", "className":"signin_fb ui-link ui-btn ui-icon-facebook-sign ui-btn-icon-left"},
{"data-role":"button", "data-icon":"facebook-sign", "data-iconpos":"left", "data-enhanced":"true"},
{"text":"Facebook"}
));
external.appendChild(priv.generateElement(
"a",
{"href":"#", "className":"signin_browser ui-link ui-btn ui-icon-lock ui-btn-icon-left ui-last-child"},
{"data-role":"button", "data-icon":"lock", "data-iconpos":"left", "data-enhanced":"true"},
{"text":"Browser ID"}
));
login_form.appendChild(external);
// // classic login
// login_form.appendChild(priv.generateElement(
// "p", {},{},{"text":"Classic Login"}
// ));
// form = priv.generateElement("form");
// internal.appendChild(priv.generateElement(
// "label",
// {"className":"ui-hidden-accessible"},
// {"for":"login", "data-i18n":"generic.text.login"},
// {"text":"Login"}
// ));
// internal.appendChild(priv.generateElement(
// "input",
// {"name":"login", "id":"login", "type":"text"},
// {
// "placeholder":"Login",
// "data-icon":"user",
// "data-i18n":"[placeholder]generic.text.login;generic.text.login"
// }
// ));
// internal.appendChild(priv.generateElement(
// "label",
// {"className":"ui-hidden-accessible"},
// {"for":"password","data-i18n":"generic.text.password"},
// {"text":"Password"}
// ));
// internal.appendChild(priv.generateElement(
// "input",
// {"name":"password", "id":"password", "type":"password"},
// {
// "placeholder":"Password",
// "data-icon":"lock"
// "data-i18n":"[placeholder]generic.text.password;generic.text.password"
// }
// ));
// internal.appendChild(priv.generateElement(
// "label",
// {"className":"ui-hidden-accessible"},
// {"for":"submit","data-i18n":"generic.text.go"},
// {"text":"Go"}
// ));
// internal.appendChild(priv.generateElement(
// "input",
// {
// "className":"submit_form",
// "name":"submit",
// "id":"submit",
// "type":"button",
// "value":"submit"},
// {"data-i18n":"[placeholder]generic.text.go;generic.text.go"}
// ));
// form.appendChild(internal);
// login_form.appendChild(form)
// note = priv.generateElement(
// "span", {"className":"mini right note"}
// );
// note.appendChild(
// priv.generateElement(
// "a", {"href":"#"},{},{"text":"Forgot Password"}
// )
// );
// login_form.appendChild(note);
content = priv.generateElement(
"div", {"className": "popup_element"}
);
content.appendChild(login_form);
popup_content.appendChild(content);
p = priv.generateElement("p", {"className":"mini"});
p.appendChild(
priv.generateElement(
"span", {"className":"note"},{},{"text":"Please note:"}
)
);
p.appendChild(
priv.generateElement(
"span",
{
"innerHTML":"To maintain sufficient resources, a minimal fee of 1 " +
"EUR will be charged if you use SlapOS services for <strong>more " +
" than 24 hours</strong>. By clicking on one of the signup " +
"buttons, you agree that you are subscribing to a payable service." +
" All services you request will be invoiced to you at the end of" +
" the month."
}
)
);
hint.appendChild(p);
hint.appendChild(priv.generateElement(
"p", {},{},{"text":"To find out more, please refer to"}
));
hint.appendChild(priv.generateElement(
"a",
{
"href":"#",
"className":"ui-btn ui-btn-icon-left ui-icon-eur ui-shadow ui-corner-all"
},
{"data-i18n":"generic.text.pricing"},
{"text":"SlapOS Pricing"}
));
info = priv.generateElement(
"div", {"className": "popup_element"}
);
info.appendChild(hint);
popup_content.appendChild(info);
return popup_content;
};
// /* ====================================================================== */
// /* TRASH BUT STILL HERE */
// /* ====================================================================== */
// // this invokes all gadgets on a page
// // TODO: should be done differently, the data-gadget property is only used
// // here to pick the correct function. Later on, the function should be
// // called form inside the gadget
// $(document).on("pagebeforeshow", "#computer", function (e, data) {
// // NOTE: it should not be necessary to fetch this data from the URL
// // because JQM should pass it in data, too
// var mode,
// item,
// properties = {},
// parameters = decodeURIComponent(
// $.mobile.path.parseUrl(window.location.href).search.split("?")[1]
// ).split("&");
//
// mode = parameters[0].split("=")[1];
// if (parameters.length > 1) {
// item = parameters[1].split("=")[1];
// }
//
// $(".erp5_single").each(function (index, element) {
// // load data
// if (mode === "get" || mode === "clone") {
// priv.erp5.get({"_id": item}, function (error, response) {
// if (response) {
// // set to properties, so response
// properties = {};
// priv.constructTabs(element, mode, item, properties);
// } else {
// abort = confirm("Error trying to retrieve data! Go back to overview?");
// if (abort === true) {
// $.mobile.changePage("computers.html", {"rel":"back"});
// }
// }
// });
// } else {
// priv.constructTabs(element, mode, item, properties);
// }
// });
//
// // we can set later
// // priv.generateItem(mode, item);
// })
// /* ====================================================================== */
// /* BINDINGS */
// /* ====================================================================== */
// // NOTE: should also not be done here, but in the respective gadget
// // NOTE: still if a form contains 10 relationfields, we should not generate
// // 10 popups and handlers, but only use a single popup shared across all
// // load item from table
// .on("click", "table tbody td a, .navbar li a.new_item", function (e) {
// var i,
// item,
// spec = {},
// url = e.target.getAttribute("href").split("?"),
// target = url[0],
// parameters = url[1].split("&");
//
// e.preventDefault();
// for (i = 0; i < parameters.length; i += 1) {
// item = parameters[i].split("=");
// spec[item[0]] = item[1];
// }
//
// $.mobile.changePage(target, {
// "transition": "fade",
// "data": spec
// });
// })
// .on("click", "a.remove_item", function (e) {
// var i,
// params = priv.splitSearchParams(),
// callback = function () {
// $.mobile.changePage("computers.html", {
// "transition":"fade",
// "reverse": "true"
// });
// };
//
// // item in URL?
// for (i = 0; i < params.length; i += 1) {
// parameter = params[i].split("=");
// if (parameter[0] === "item") {
// priv.modifyObject({"_id": decodeURIComponent(parameter[1])}, "remove", callback );
// }
// }
// })
// // save form
// .on("click", "a.save_object", function (e) {
// var i,
// parameter,
// method,
// object,
// // check the URL for the state we are in
// // NOTE: not nice, change later
// params = priv.splitSearchParams(),
// callback = function () {
// $.mobile.changePage("computers.html", {
// "transition":"fade",
// "reverse":"true"
// });
// };
//
// for (i = 0; i < params.length; i += 1) {
// parameter = params[i].split("=");
// if (parameter[0] === "mode") {
// switch (parameter[1]) {
// case "edit":
// method = "put";
// break;
// case "clone":
// case "add":
// method = "post";
// break;
// }
// if (method !== undefined) {
// object = priv.validateObject(
// priv.serializeObject($(".display_object"))
// );
// // fallback to eliminate _id on clone
// // TODO: do somewhere else!
// if (method === "post") {
// delete object._id;
// }
// priv.modifyObject(object, method, callback);
// } else {
// alert("missing command!, cannot store");
// }
// }
// }
// })
// // update navbar depending on item selected
// .on("change", "table tbody th input[type=checkbox]", function(e) {
// var allChecks = $(e.target).closest("tbody").find("th input[type=checkbox]:checked"),
// selected = allChecks.length,
// trigger = $(".navbar .new_item");
//
// if (selected === 1) {
// trigger.addClass("ui-btn-active clone_item").attr("href","computer.html?mode=clone&item=" + e.target.id);
// } else {
// trigger.removeClass("ui-btn-active clone_item").attr("href","computer.html?mode=add");
// }
//
// });
// form = document.getElementById(e.target.getAttribute("data-form"));
// target = e.target.href;
//
// e.preventDefault();
//
// if (util.testForClass(form.className), "validate") {
// valid = $(form).triggerHandler( "submitForm" );
// } else {
// valid = $(form).serialize();
// }
//
// // // TODO: how to update status?
// // if (valid !== false) {
// // jIO.util.ajax({
// // "url": "data/" + attachment + ".json", "dataType":"json"
// // })
// // }
// //
// // target = e.target.href,
// // id = form.id,
// // pointer = "response:" + id,
// // proceed = function (data, target) {
// // // changePage with fragment_cache pointer
// // $.mobile.changePage(target, {"transition": "slide", "data": data});
// // };
// //
// // // stop
// // // fetch and proceed
// // if (valid !== false) {
// // $.ajax({
// // "type":"POST",
// // "url": "foo.php",
// // "data": valid
// // }).done(function(data) {
// // // overwrite cache
// // // NOTE: FAKE data until working
// // priv.fragment_cache[id] = priv.getFakeRecords["payment"];
// // proceed(pointer, target);
// // }).fail(function(jqXHR) {
// // // fake it
// // priv.fragment_cache[id] = priv.getFakeRecords["payment"];
// // proceed(pointer, target);
// // });
// // }
// // });
// // }
// // });
// PAGE BINDINGS
.end()
// form validation initializer
.find("form")
// .filter(function () {
// return this.getAttribute("data-bound") !== true;
// })
// .each(function (i, element) {
// element.setAttribute("data-bound", true);
// // TODO: how to add custom validations here?
// // TODO: async?
// $(element).validVal({
// validate: {
// onKeyup: "valid",
// onBlur: "valid"
// },
// form: {
// onInvalid: function() { return;}
// }
// });
// })
// .end()
// //TODO: can't set bindings, because we don't have a parent?
// // or always set on document for local and global should be autoset?
// // popup content handling
// if (search_popup) {
// $parent.on("click", "a.extended_search", function (e) {
// priv.generatePopupContents(e, "self", portal_type, settings.view, gadget_id);
// });
// }
//
// // table actions
// if (search_popup) {
// // NOTE: can't bind to $parent, because JQM moves the popup
// // outside of $parent
// page = $parent.closest("div.ui-page");
//
// if (page.data("bindings") === undefined) {
// page.data("bindings", {});
// }
// if (page.data("bindings")["table_action"] === undefined) {
// page.data("bindings")["table_action"] = true;
//
// $(document).on("click", "a.table_action", function (e) {
// var target,
// action = e.target.getAttribute("data-action"),
// popup = $(e.target).closest(".ui-popup"),
// form = popup.find("form");
//
// if (form.length === 0) {
// target = popup.find(".ui-content");
// } else {
// target = form;
// }
// switch (action) {
// case "add_criteria_search":
// target.append(priv.generateSearchCriteria(e.target))
// .enhanceWithin();
// break;
//
// case "add_criteria_config":
// target.append(priv.generateConfigCriteria(e.target))
// .enhanceWithin();
// break;
// case "delete_criteria":
// $(e.target).closest("div.ui-grid-row").remove();
// break;
// }
// });
// }
// }
//
// });
......@@ -8,7 +8,7 @@
// *************************************************************************
// WARNING:
// WARNING: HACKED TOGETHER SO IT WORKS FOR DEMO PURPOSE ONLY!!!
// WARNING: HACKED TOGETHER SO IT WORKS - FOR DEMO PURPOSE ONLY!!!
// WARNING:
// *************************************************************************
......@@ -26,8 +26,7 @@
/* ====================================================================== */
/**
* Mapping data structure to factory (actions, gadgets, buttons, utilities)
* @object map
* HACKED Select options
**/
map = {};
......@@ -533,12 +532,10 @@
]
}
};
/**
* Custom handlers necessary to make calls to ERP5 storage. These should
* not be needed, but are currently necessary.
* @object map.handlers
* HACKED handlers
**/
// TODO: remove!
map.handlers = {
/**
......
/*
* JIO extension for resource replication.
* Copyright (C) 2013 Nexedi SA
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, module, require, jIO, RSVP */
(function (root, dependencies, factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
return define(dependencies, function () {
return factory(require);
});
}
if (typeof require === 'function') {
module.exports = factory(require);
return;
}
root.replicate_storage = factory(function (name) {
return {
"jio": jIO,
"rsvp": RSVP
}[name];
});
}(this, ['jio', 'rsvp'], function (require) {
"use strict";
var Promise = require('rsvp').Promise,
all = require('rsvp').all,
dictUpdate = require('jio').util.dictUpdate,
addStorageFunction = require('jio').addStorage;
/**
* Test if the a value is a date
*
* @param {String,Number,Date} date The date to test
* @return {Boolean} true if success, else false
*/
function isDate(date) {
if (!isNaN((new Date(date === null ? undefined : date)).getTime())) {
return true;
}
return false;
}
/**
* Executes a sequence of *then* callbacks. It acts like
* `smth().then(callback).then(callback)...`. The first callback is called
* with no parameter.
*
* Elements of `then_list` array can be a function or an array contaning at
* most three *then* callbacks: *onFulfilled*, *onRejected*, *onNotified*.
*
* When `cancel()` is executed, each then promises are cancelled at the same
* time.
*
* sequence(then_list): Promise
*
* @param {Array} then_list An array of *then* callbacks
* @return {Promise} A new promise
*/
function sequence(then_list) {
var promise_list = [];
return new Promise(function (resolve, reject, notify) {
var i, length = then_list.length;
promise_list[0] = new Promise(function (resolve) {
resolve();
});
for (i = 0; i < length; i += 1) {
if (Array.isArray(then_list[i])) {
promise_list[i + 1] = promise_list[i].
then(then_list[i][0], then_list[i][1], then_list[i][2]);
} else {
promise_list[i + 1] = promise_list[i].then(then_list[i]);
}
}
promise_list[i].then(resolve, reject, notify);
}, function () {
var i, length = promise_list.length;
for (i = 0; i < length; i += 1) {
promise_list[i].cancel();
}
});
}
function success(promise) {
return new Promise(function (resolve, reject, notify) {
/*jslint unparam: true*/
promise.then(resolve, resolve, notify);
}, function () {
promise.cancel();
});
}
// /**
// * Awaits for an answer from one promise only. Promises are cancelled only
// * by calling `first(promise_list).cancel()`.
// *
// * first(promise_list): Promise
// *
// * @param {Array} promise_list An array of promises
// * @return {Promise} A new promise
// */
// function first(promise_list) {
// var length = promise_list.length;
// promise_list = promise_list.slice();
// return new Promise(function (resolve, reject, notify) {
// var index, count = 0;
// function rejecter(answer) {
// count += 1;
// if (count === length) {
// return reject(answer);
// }
// }
// function notifier(index) {
// return function (notification) {
// notify({
// "index": index,
// "value": notification
// });
// };
// }
// for (index = 0; index < length; index += 1) {
// promise_list[index].then(resolve, rejecter, notifier(index));
// }
// }, function () {
// var index;
// for (index = 0; index < length; index += 1) {
// promise_list[index].cancel();
// }
// });
// }
/**
* Responds with the last resolved promise answer recieved. If all promises
* are rejected, it returns the latest rejected promise answer
* received. Promises are cancelled only by calling
* `last(promise_list).cancel()`.
*
* last(promise_list): Promise
*
* @param {Array} promise_list An array of promises
* @return {Promise} A new promise
*/
function last(promise_list) {
var length = promise_list.length;
promise_list = promise_list.slice();
return new Promise(function (resolve, reject, notify) {
var index, last_answer, count = 0, error_count = 0;
function resolver() {
return function (answer) {
count += 1;
if (count === length) {
return resolve(answer);
}
last_answer = answer;
};
}
function rejecter() {
return function (answer) {
error_count += 1;
if (error_count === length) {
return reject(answer);
}
count += 1;
if (count === length) {
return resolve(last_answer);
}
};
}
function notifier(index) {
return function (notification) {
notify({
"index": index,
"value": notification
});
};
}
for (index = 0; index < length; index += 1) {
promise_list[index].then(resolver(), rejecter(), notifier(index));
}
}, function () {
var index;
for (index = 0; index < length; index += 1) {
promise_list[index].cancel();
}
});
}
/**
* Responds with the last modified document recieved. If all promises are
* rejected, it returns the latest rejected promise answer received. Promises
* are cancelled only by calling `lastModified(promise_list).cancel()`. USE
* THIS FUNCTION ONLY FOR GET METHOD!
*
* lastModified(promise_list): Promise
*
* @param {Array} promise_list An array of promises
* @return {Promise} A new promise
*/
function lastModified(promise_list) {
var length = promise_list.length;
promise_list = promise_list.slice();
return new Promise(function (resolve, reject, notify) {
var index, last_good_answer, last_answer, count = 0, error_count = 0;
function resolver(answer) {
last_answer = answer;
if (last_good_answer === undefined) {
if (isDate(answer.data.modified)) {
last_good_answer = answer;
}
} else {
if (isDate(answer.data.modified)) {
if (new Date(last_good_answer.data.modified) <
new Date(answer.data.modified)) {
last_good_answer = answer;
}
}
}
count += 1;
if (count === length) {
return resolve(last_good_answer);
}
}
function rejecter(answer) {
error_count += 1;
if (error_count === length) {
return reject(answer);
}
count += 1;
if (count === length) {
return resolve(last_good_answer || last_answer);
}
}
function notifier(index) {
return function (notification) {
notify({
"index": index,
"value": notification
});
};
}
for (index = 0; index < length; index += 1) {
promise_list[index].then(resolver, rejecter, notifier(index));
}
}, function () {
var index;
for (index = 0; index < length; index += 1) {
promise_list[index].cancel();
}
});
}
// /**
// * An Universal Unique ID generator
// *
// * @return {String} The new UUID.
// */
// function generateUuid() {
// function S4() {
// return ('0000' + Math.floor(
// Math.random() * 0x10000 /* 65536 */
// ).toString(16)).slice(-4);
// }
// return S4() + S4() + "-" +
// S4() + "-" +
// S4() + "-" +
// S4() + "-" +
// S4() + S4() + S4();
// }
function ReplicateStorage(spec) {
if (!Array.isArray(spec.storage_list)) {
throw new TypeError("ReplicateStorage(): " +
"storage_list is not of type array");
}
this._storage_list = spec.storage_list;
}
ReplicateStorage.prototype.post = function (command, metadata, option) {
var promise_list = [], index, length = this._storage_list.length;
if (!isDate(metadata.modified)) {
command.error(
409,
"invalid 'modified' metadata",
"The metadata 'modified' should be a valid date string or date object"
);
return;
}
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(this._storage_list[index]).post(metadata, option)
);
}
sequence([function () {
return last(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.put = function (command, metadata, option) {
var promise_list = [], index, length = this._storage_list.length;
if (!isDate(metadata.modified)) {
command.error(
409,
"invalid 'modified' metadata",
"The metadata 'modified' should be a valid date string or date object"
);
return;
}
for (index = 0; index < length; index += 1) {
promise_list[index] =
command.storage(this._storage_list[index]).put(metadata, option);
}
sequence([function () {
return last(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.putAttachment = function (command, param, option) {
var promise_list = [], index, length = this._storage_list.length;
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(this._storage_list[index]).putAttachment(param, option)
);
}
sequence([function () {
return last(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.remove = function (command, param, option) {
var promise_list = [], index, length = this._storage_list.length;
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(this._storage_list[index]).remove(param, option)
);
}
sequence([function () {
return last(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.removeAttachment = function (
command,
param,
option
) {
var promise_list = [], index, length = this._storage_list.length;
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(this._storage_list[index]).
removeAttachment(param, option)
);
}
sequence([function () {
return last(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.get = function (command, param, option) {
var promise_list = [], index, length = this._storage_list.length;
for (index = 0; index < length; index += 1) {
promise_list[index] =
command.storage(this._storage_list[index]).get(param, option);
}
sequence([function () {
return lastModified(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.getAttachment = function (command, param, option) {
var promise_list = [], index, length = this._storage_list.length;
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(this._storage_list[index]).getAttachment(param, option)
);
}
sequence([function () {
return last(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.allDocs = function (command, param, option) {
/*jslint unparam: true */
var promise_list = [], index, length = this._storage_list.length;
for (index = 0; index < length; index += 1) {
promise_list[index] =
success(command.storage(this._storage_list[index]).allDocs(option));
}
sequence([function () {
return all(promise_list);
}, function (answers) {
// merge responses
var i, j, k, found, rows;
// browsing answers
for (i = 0; i < answers.length; i += 1) {
if (answers[i].result === "success") {
if (!rows) {
rows = answers[i].data.rows;
} else {
// browsing answer rows
for (j = 0; j < answers[i].data.rows.length; j += 1) {
found = false;
// browsing result rows
for (k = 0; k < rows.length; k += 1) {
if (rows[k].id === answers[i].data.rows[j].id) {
found = true;
break;
}
}
if (!found) {
rows.push(answers[i].data.rows[j]);
}
}
}
}
}
return {"data": {"total_rows": (rows || []).length, "rows": rows || []}};
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.check = function (command, param, option) {
var promise_list = [], index, length = this._storage_list.length;
for (index = 0; index < length; index += 1) {
promise_list[index] = success(
command.storage(this._storage_list[index]).check(param, option)
);
}
sequence([function () {
return all(promise_list);
}, [command.success, command.error]]);
};
ReplicateStorage.prototype.repair = function (command, param) {
var promise_list = [], index, that, length = this._storage_list.length;
that = this;
if (typeof param._id !== 'string' || !param._id) {
command.success();
return;
}
for (index = 0; index < length; index += 1) {
promise_list[index] =
success(command.storage(this._storage_list[index]).get(param));
}
sequence([function () {
return all(promise_list);
}, function (answers) {
var i, list = [], winner = null;
for (i = 0; i < answers.length; i += 1) {
if (answers[i].result === "success") {
if (isDate(answers[i].data.modified)) {
list[i] = answers[i].data;
if (winner === null ||
new Date(winner.modified) <
new Date(answers[i].data.modified)) {
winner = answers[i].data;
}
}
} else if (answers[i].status === 404) {
list[i] = 0;
}
}
for (i = 0; i < list.length; i += 1) {
if (list[i] && new Date(list[i].modified) < new Date(winner.modified)) {
list[i] = success(command.storage(that._storage_list[i]).put(winner));
} else if (list[i] === 0) {
list[i] = dictUpdate({}, winner);
delete list[i]._id;
list[i] =
success(command.storage(that._storage_list[i]).post(list[i]));
}
}
list = list.reduce(function (previous, current) {
if (current) {
previous.push(current);
}
return previous;
}, []);
return all(list);
}, function (answers) {
var i;
for (i = 0; i < answers.length; i += 1) {
if (answers[i].result !== "success") {
return command.error(409);
}
}
command.success();
}]);
};
addStorageFunction('replicate', ReplicateStorage);
}));
(function(window, document, $) {
/*
// NOTE:
// beware to update all display texts when using multiple languages
// NOTE:
// temporary setup to keep user settings!
// this is USER-SETTINGS
var User = jIO.newJio({
"type": "local",
"username": "setup",
"application_name": "slapos"
});
User.get({"_id":"configuration"}, function (err, response) {
if (err) {
// no user config stored, load default
$.when($.ajax({
"url": "data/default_configuration.json",
"dataType": "json"
})
).then(function(data, textStatus, jqXHR) {
console.log(data);
}
).fail(function(data, textStatus, jqXHR) {
alert("Could not load application configuration");
}
);
} else {
}
});
*/
// TODO: save user settings in JIO localstorage
// tab handler
var count = 0,
parent,
create_tab,
tab_index,
tab_body,
tab_add_gadget,
tab_header,
tab_text,
tab_edit,
tab_delete,
tab;
factory_link = document.createElement("a");
factory_link.setAttribute("data-role", "button");
factory_link.setAttribute("href", "#");
factory_header = document.createElement("h1");
factory_div = document.createElement("div");
// add a new tab
$("div.ui-dynamic-tabs div.tab_add").on("collapsiblebeforeexpand", function (e) {
e.preventDefault();
parent = e.target.parentNode;
if (count === 0) {
if (parent.className.match(/(?:^|\s)ui-dynamic-tabs-added(?!\S)/) === null) {
parent.className += " ui-dynamic-tabs-added";
}
}
tab_index = "Tab-" + count;
count += 1;
create_tab = prompt("Please name your new tab", tab_index);
if (create_tab !== null && create_tab !== undefined) {
tab = factory_div.cloneNode();
tab.setAttribute("data-role", "collapsible");
tab.setAttribute("data-collapsed", "true");
tab.setAttribute("data-icon", "false");
tab_header = factory_header.cloneNode();
tab_edit = factory_link.cloneNode();
tab_edit.setAttribute("data-iconpos", "notext");
tab_edit.setAttribute("data-icon", "pencil");
tab_edit.setAttribute("data-rel", "edit");
tab_edit.setAttribute("class", "tab_action");
tab_edit.appendChild( document.createTextNode("Edit"));
tab_delete = factory_link.cloneNode();
tab_delete.setAttribute("data-iconpos", "notext");
tab_delete.setAttribute("data-icon", "remove");
tab_delete.setAttribute("data-rel", "delete");
tab_delete.setAttribute("class", "tab_action tab_action_last");
tab_delete.appendChild( document.createTextNode("Delete"));
tab_body = window.document.createDocumentFragment();
// add active gadgets here!
tab_add_piece = factory_link.cloneNode();
tab_add_piece.setAttribute("href","gadgetCatalog");
tab_add_piece.setAttribute("data-icon", "puzzle-piece");
tab_add_piece.setAttribute("data-iconpos", "left");
tab_add_piece.setAttribute("data-inline", "true");
tab_add_piece.className = "dashed gadget_add";
tab_add_piece.appendChild( document.createTextNode("Add Gadget") );
tab_body.appendChild(tab_add_piece);
tab_header.appendChild(document.createTextNode( create_tab ));
tab_header.appendChild(tab_edit);
tab_header.appendChild(tab_delete);
tab.appendChild(tab_header);
tab.appendChild(tab_body);
parent.insertBefore(tab, e.target);
// enhance, set edit and remove bindings
$(parent)
.collapsibleset("refresh")
.enhanceWithin()
.find(".tab_action")
.on("click", function (e) {
var action, collapsible, proceed;
// prevent action on collapsible
e.stopPropagation();
e.stopImmediatePropagation();
action = e.target.getAttribute("data-rel");
if (action === "delete") {
proceed = confirm("Do you really want to remove this tab and included gadgets?");
if (proceed) {
collapsible = e.target.parentNode.parentNode;
collapsible.parentNode.removeChild(collapsible);
// reset
$(parent).collapsibleset("refresh");
// update parent
count -= 1;
if (count === 0) {
parent.className = parent.className.replace(/(?:^|\s)ui-dynamic-tabs-added(?!\S)/g , '')
}
}
} else if (action === "edit") {
proceed = prompt("Please rename your tab", e.target.parentNode.childNodes[0].text);
if (proceed !== null) {
e.target.parentNode.childNodes[0].innerHTML = proceed;
}
}
});
}
});
}(window, document, jQuery));
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment