From 0c15e719fcb7f641548487cacaad9b5441b718aa Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 2 Aug 2018 15:21:01 +0200 Subject: [PATCH 01/63] display billing info in details --- frontend/src/constants/ordersConstants.js | 6 +++++- .../src/containers/orders/components/OrderInfo.jsx | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/frontend/src/constants/ordersConstants.js b/frontend/src/constants/ordersConstants.js index 6eaaeee..fb282fc 100644 --- a/frontend/src/constants/ordersConstants.js +++ b/frontend/src/constants/ordersConstants.js @@ -161,7 +161,11 @@ export const orderTexts = { INSTALLATION_DATE: 'Installation date', INSTALLATION_NOT_REQUIRED:'Installation is not required for this package', PRELIMINARY_INSTALLATION_DATE_LABEL: 'Preliminary installation date', - PROJECT: 'Project' + PROJECT: 'Project', + BILLING_FIRST_NAME: 'Billing first name', + BILLING_LAST_NAME: 'Billing last name', + BILLING_MAIL: 'Invoice mail', + BILLING_ADDRESS: 'Billing address' }, buttons: { ACCEPT_INSTALLATION: 'I agree', diff --git a/frontend/src/containers/orders/components/OrderInfo.jsx b/frontend/src/containers/orders/components/OrderInfo.jsx index 89bd912..fd69b6f 100644 --- a/frontend/src/containers/orders/components/OrderInfo.jsx +++ b/frontend/src/containers/orders/components/OrderInfo.jsx @@ -65,6 +65,16 @@ class OrderInfo extends Component { {orderInfo.commercialLead} + +
{orderTexts.labels.BILLING_FIRST_NAME}:
+ {orderInfo.billingFirstName || '-'} +
{orderTexts.labels.BILLING_LAST_NAME}:
+ {orderInfo.billingLastName || '-'} +
{orderTexts.labels.BILLING_MAIL}:
+ {orderInfo.billingMail || '-'} +
{orderTexts.labels.BILLING_ADDRESS}:
+ {orderInfo.billingAddress || '-'} +
{orderTexts.labels.REFERENCE}:
From a03832df51eecb39db2b032c0ca2f9a0c062034f Mon Sep 17 00:00:00 2001 From: GotPPay Date: Tue, 14 Aug 2018 18:21:38 +0200 Subject: [PATCH 02/63] add new fields to customer acceptance form --- ...ivery_action_customer_acceptance_form.json | 897 ++++++++++-------- .../delivery_action_manual_form.json | 37 +- .../delivery_action_schedule_meeting.json | 25 +- ...ry_action_validate_questionnaire_form.json | 37 +- ...delivery_process_normal_delivery_form.json | 70 +- 5 files changed, 606 insertions(+), 460 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json index 0b7fe6b..0839e31 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json @@ -1,387 +1,524 @@ { "0": { - "title": "DELIVERY ACTION TYPE: Customer acceptance", - "description": "The customer must accept the implementation before further actions can be taken. If the customer isn't satisfied, the problems or discrepancies must be fixed in order to gen an acceptance.", - "labelPlacement": "top_label", - "descriptionPlacement": "below", - "button": { - "type": "text", - "text": "Submit", - "imageUrl": "" - }, - "fields": [ - { - "type": "workflow_user", - "id": 2, - "label": "customer-id", - "adminLabel": "customer-id", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "administrative", - "inputs": null, - "choices": [ - ], - "formId": 10, - "description": "", - "allowsPrepopulate": true, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "customer-id", - "noDuplicates": false, - "defaultValue": "", - "conditionalLogic": "", - "failed_validation": "", - "productField": "", - "multipleFiles": false, - "maxFiles": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "", - "enablePrice": "", - "gravityflowUsersRoleFilter": "" + "title": "DELIVERY ACTION TYPE: Customer acceptance", + "description": "The customer must accept the implementation before further actions can be taken. If the customer isn't satisfied, the problems or discrepancies must be fixed in order to gen an acceptance.", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "" }, - { - "type": "date", - "id": 6, - "label": "Actual date", - "adminLabel": "", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "visible", - "inputs": null, - "dateType": "datepicker", - "calendarIconType": "none", - "formId": 10, - "description": "", - "allowsPrepopulate": false, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "", - "noDuplicates": false, - "defaultValue": "", - "choices": "", - "conditionalLogic": "", - "calendarIconUrl": "", - "dateFormat": "ymd_dash", - "productField": "", - "multipleFiles": false, - "maxFiles": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "" - }, - { - "type": "fileupload", - "id": 7, - "label": "Acceptance document", - "adminLabel": "", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "visible", - "inputs": null, - "formId": 10, - "description": "Upload your acceptance document", - "allowsPrepopulate": false, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "", - "noDuplicates": false, - "defaultValue": "", - "choices": "", - "conditionalLogic": "", - "maxFileSize": "", - "maxFiles": "", - "multipleFiles": false, - "allowedExtensions": "", - "productField": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "" - } - ], - "version": "2.3.2", - "id": 10, - "useCurrentUserAsAuthor": true, - "postContentTemplateEnabled": false, - "postTitleTemplateEnabled": false, - "postTitleTemplate": "", - "postContentTemplate": "", - "lastPageButton": null, - "pagination": null, - "firstPageCssClass": null, - "confirmations": [ - { - "id": "5b5f75f7494b7", - "name": "Default Confirmation", - "isDefault": true, - "type": "message", - "message": "Thanks for contacting us! We will get in touch with you shortly.", - "url": "", - "pageId": "", - "queryString": "" - } - ], - "notifications": [ - { - "id": "5b5f75f748cee", - "to": "{admin_email}", - "name": "Admin Notification", - "event": "form_submission", - "toType": "email", - "subject": "New submission from {form_title}", - "message": "{all_fields}" - } - ], - "feeds": { - "gravityflow": [ - { - "id": "22", - "form_id": "10", - "is_active": "1", - "feed_order": "0", - "meta": { - "step_name": "Upload acceptance file", - "description": "", - "step_type": "user_input", - "step_highlight": "0", - "step_highlight_type": "color", - "step_highlight_color": "#dd3333", - "feed_condition_conditional_logic": "0", - "feed_condition_conditional_logic_object": [], - "scheduled": "0", - "schedule_type": "delay", - "schedule_date": "", - "schedule_delay_offset": "", - "schedule_delay_unit": "hours", - "schedule_date_field_offset": "0", - "schedule_date_field_offset_unit": "hours", - "schedule_date_field_before_after": "after", - "type": "select", - "assignees": [ - "role|administrator", - "assignee_user_field|2" - ], - "editable_fields": [ - "5" - ], - "routing": "", - "assignee_policy": "any", - "highlight_editable_fields_enabled": "0", - "highlight_editable_fields_class": "green-triangle", - "instructionsEnable": "0", - "instructionsValue": "", - "display_fields_mode": "selected_fields", - "display_fields_selected": [ - "5" - ], - "default_status": "hidden", - "note_mode": "not_required", - "assignee_notification_enabled": "0", - "assignee_notification_from_name": "", - "assignee_notification_from_email": "{admin_email}", - "assignee_notification_reply_to": "", - "assignee_notification_bcc": "", - "assignee_notification_subject": "Upload order acceptance file", - "assignee_notification_message": "A new entry requires your input.", - "assignee_notification_disable_autoformat": "0", - "resend_assignee_emailEnable": "0", - "resend_assignee_emailValue": "7", - "resend_assignee_email_repeatEnable": "0", - "resend_assignee_email_repeatValue": "3", - "in_progress_notification_enabled": "0", - "in_progress_notification_type": "select", - "in_progress_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "in_progress_notification_from_name": "", - "in_progress_notification_from_email": "{admin_email}", - "in_progress_notification_reply_to": "", - "in_progress_notification_bcc": "", - "in_progress_notification_subject": "", - "in_progress_notification_message": "Entry {entry_id} has been updated and remains in progress.", - "in_progress_notification_disable_autoformat": "0", - "complete_notification_enabled": "0", - "complete_notification_type": "select", - "complete_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "complete_notification_from_name": "", - "complete_notification_from_email": "{admin_email}", - "complete_notification_reply_to": "", - "complete_notification_bcc": "", - "complete_notification_subject": "", - "complete_notification_message": "Entry {entry_id} has been updated completing the step.", - "complete_notification_disable_autoformat": "0", - "confirmation_messageEnable": "0", - "confirmation_messageValue": "Thank you.", - "expiration": "0", - "expiration_type": "delay", - "expiration_date": "", - "expiration_delay_offset": "7", - "expiration_delay_unit": "days", - "expiration_date_field_offset": "0", - "expiration_date_field_offset_unit": "hours", - "expiration_date_field_before_after": "after", - "status_expiration": "expired", - "destination_expired": "next", - "destination_complete": "next" + "fields": [ + { + "type": "workflow_user", + "id": 2, + "label": "customer-id", + "adminLabel": "customer-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "administrative", + "inputs": null, + "choices": [ + ], + "formId": 1, + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "customer-id", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "failed_validation": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "", + "gravityflowUsersRoleFilter": "" }, - "addon_slug": "gravityflow", - "event_type": null - }, - { - "id": "30", - "form_id": "10", - "is_active": "1", - "feed_order": "0", - "meta": { - "step_name": "Approve customer acceptance", - "description": "", - "step_type": "approval", - "step_highlight": "0", - "step_highlight_type": "color", - "step_highlight_color": "#dd3333", - "feed_condition_conditional_logic": "0", - "feed_condition_conditional_logic_object": [], - "scheduled": "0", - "schedule_type": "delay", - "schedule_date": "", - "schedule_delay_offset": "", - "schedule_delay_unit": "hours", - "schedule_date_field_offset": "0", - "schedule_date_field_offset_unit": "hours", - "schedule_date_field_before_after": "after", - "type": "select", - "assignees": [ - "role|administrator" - ], - "routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "assignee_policy": "any", - "instructionsEnable": "0", - "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", - "display_fields_mode": "all_fields", - "assignee_notification_enabled": "0", - "assignee_notification_from_name": "", - "assignee_notification_from_email": "{admin_email}", - "assignee_notification_reply_to": "", - "assignee_notification_bcc": "", - "assignee_notification_subject": "", - "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", - "assignee_notification_disable_autoformat": "0", - "resend_assignee_emailEnable": "0", - "resend_assignee_emailValue": "7", - "resend_assignee_email_repeatEnable": "0", - "resend_assignee_email_repeatValue": "3", - "rejection_notification_enabled": "0", - "rejection_notification_type": "select", - "rejection_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "rejection_notification_from_name": "", - "rejection_notification_from_email": "{admin_email}", - "rejection_notification_reply_to": "", - "rejection_notification_bcc": "", - "rejection_notification_subject": "", - "rejection_notification_message": "Entry {entry_id} has been rejected", - "rejection_notification_disable_autoformat": "0", - "approval_notification_enabled": "0", - "approval_notification_type": "select", - "approval_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "approval_notification_from_name": "", - "approval_notification_from_email": "{admin_email}", - "approval_notification_reply_to": "", - "approval_notification_bcc": "", - "approval_notification_subject": "", - "approval_notification_message": "Entry {entry_id} has been approved", - "approval_notification_disable_autoformat": "0", - "revertEnable": "0", - "revertValue": "22", - "note_mode": "not_required", - "expiration": "0", - "expiration_type": "delay", - "expiration_date": "", - "expiration_delay_offset": "", - "expiration_delay_unit": "hours", - "expiration_date_field_offset": "0", - "expiration_date_field_offset_unit": "hours", - "expiration_date_field_before_after": "after", - "status_expiration": "rejected", - "destination_expired": "next", - "destination_rejected": "22", - "destination_approved": "next" + { + "type": "date", + "id": 6, + "label": "Actual date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "none", + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" }, - "addon_slug": "gravityflow", - "event_type": null - } - ] - } + { + "type": "radio", + "id": 8, + "label": "acceptance", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "choices": [ + { + "text": "not-accepted", + "value": "not-accepted", + "isSelected": true, + "price": "" + }, + { + "text": "accept", + "value": "accept", + "isSelected": false, + "price": "" + }, + { + "text": "decline", + "value": "decline", + "isSelected": false, + "price": "" + } + ], + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "productField": "", + "enableOtherChoice": "", + "enablePrice": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + }, + { + "type": "date", + "id": 9, + "label": "Expiration date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "none", + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + }, + { + "type": "text", + "id": 10, + "label": "Reason", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "" + }, + { + "type": "fileupload", + "id": 12, + "label": "File", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "formId": 1, + "description": "Upload customer acceptance file", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "maxFileSize": "", + "maxFiles": "", + "multipleFiles": true, + "allowedExtensions": "pdf,docx,doc,xlsx,xls,odt,ods,jpg,png,jpeg", + "productField": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false + } + ], + "version": "2.3.2", + "id": 1, + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "is_active": "1", + "date_created": "2018-08-09 16:03:22", + "is_trash": "0", + "notifications": [ + { + "id": "5b5f75f748cee", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], + "confirmations": [ + { + "id": "5b5f75f7494b7", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "feeds": { + "gravityflow": [ + { + "id": "1", + "form_id": "1", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Upload acceptance file", + "description": "", + "step_type": "user_input", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "schedule_date_field": "6", + "type": "select", + "assignees": [ + "role|administrator", + "assignee_user_field|2" + ], + "routing": "", + "assignee_policy": "any", + "highlight_editable_fields_enabled": "0", + "highlight_editable_fields_class": "green-triangle", + "instructionsEnable": "0", + "instructionsValue": "", + "display_fields_mode": "selected_fields", + "default_status": "hidden", + "note_mode": "not_required", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "Upload order acceptance file", + "assignee_notification_message": "A new entry requires your input.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "in_progress_notification_enabled": "0", + "in_progress_notification_type": "select", + "in_progress_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "in_progress_notification_from_name": "", + "in_progress_notification_from_email": "{admin_email}", + "in_progress_notification_reply_to": "", + "in_progress_notification_bcc": "", + "in_progress_notification_subject": "", + "in_progress_notification_message": "Entry {entry_id} has been updated and remains in progress.", + "in_progress_notification_disable_autoformat": "0", + "complete_notification_enabled": "0", + "complete_notification_type": "select", + "complete_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "complete_notification_from_name": "", + "complete_notification_from_email": "{admin_email}", + "complete_notification_reply_to": "", + "complete_notification_bcc": "", + "complete_notification_subject": "", + "complete_notification_message": "Entry {entry_id} has been updated completing the step.", + "complete_notification_disable_autoformat": "0", + "confirmation_messageEnable": "0", + "confirmation_messageValue": "Thank you.", + "expiration": "1", + "expiration_type": "date_field", + "expiration_date": "", + "expiration_delay_offset": "7", + "expiration_delay_unit": "days", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "expiration_date_field": "9", + "status_expiration": "expired", + "destination_expired": "2", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "2", + "form_id": "1", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Approve customer acceptance", + "description": "", + "step_type": "approval", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "type": "select", + "assignees": [ + "role|administrator" + ], + "routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "assignee_policy": "any", + "instructionsEnable": "0", + "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", + "display_fields_mode": "all_fields", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "", + "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "rejection_notification_enabled": "0", + "rejection_notification_type": "select", + "rejection_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "rejection_notification_from_name": "", + "rejection_notification_from_email": "{admin_email}", + "rejection_notification_reply_to": "", + "rejection_notification_bcc": "", + "rejection_notification_subject": "", + "rejection_notification_message": "Entry {entry_id} has been rejected", + "rejection_notification_disable_autoformat": "0", + "approval_notification_enabled": "0", + "approval_notification_type": "select", + "approval_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "approval_notification_from_name": "", + "approval_notification_from_email": "{admin_email}", + "approval_notification_reply_to": "", + "approval_notification_bcc": "", + "approval_notification_subject": "", + "approval_notification_message": "Entry {entry_id} has been approved", + "approval_notification_disable_autoformat": "0", + "revertEnable": "0", + "revertValue": 1, + "note_mode": "not_required", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "", + "expiration_delay_unit": "hours", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "status_expiration": "rejected", + "destination_expired": "next", + "destination_rejected": 1, + "destination_approved": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + } + ] + } }, - "version": "2.3.2.6" + "version": "2.3.2" } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_manual_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_manual_form.json index f975650..cbca857 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_manual_form.json +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_manual_form.json @@ -30,7 +30,7 @@ "text": "wpUser" } ], - "formId": 12, + "formId": 4, "description": "", "allowsPrepopulate": true, "inputMask": false, @@ -71,7 +71,7 @@ "inputs": null, "dateType": "datepicker", "calendarIconType": "calendar", - "formId": 12, + "formId": 4, "description": "", "allowsPrepopulate": false, "inputMask": false, @@ -102,7 +102,7 @@ } ], "version": "2.3.2", - "id": 12, + "id": 4, "useCurrentUserAsAuthor": true, "postContentTemplateEnabled": false, "postTitleTemplateEnabled": false, @@ -111,17 +111,9 @@ "lastPageButton": null, "pagination": null, "firstPageCssClass": null, - "notifications": [ - { - "id": "5b5f9ebc520f3", - "to": "{admin_email}", - "name": "Admin Notification", - "event": "form_submission", - "toType": "email", - "subject": "New submission from {form_title}", - "message": "{all_fields}" - } - ], + "is_active": "1", + "date_created": "2018-08-09 15:36:00", + "is_trash": "0", "confirmations": [ { "id": "5b5f9ebc52a80", @@ -134,11 +126,22 @@ "queryString": "" } ], + "notifications": [ + { + "id": "5b5f9ebc520f3", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], "feeds": { "gravityflow": [ { - "id": "27", - "form_id": "12", + "id": "6", + "form_id": "4", "is_active": "1", "feed_order": "0", "meta": { @@ -245,5 +248,5 @@ ] } }, - "version": "2.3.2.6" + "version": "2.3.2" } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_schedule_meeting.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_schedule_meeting.json index 4c9bff0..be4ebb0 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_schedule_meeting.json +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_schedule_meeting.json @@ -30,7 +30,7 @@ "text": "wpUser" } ], - "formId": 13, + "formId": 2, "description": "", "allowsPrepopulate": true, "inputMask": false, @@ -70,7 +70,7 @@ "inputs": null, "dateType": "datepicker", "calendarIconType": "calendar", - "formId": 13, + "formId": 2, "description": "", "allowsPrepopulate": false, "inputMask": false, @@ -111,7 +111,7 @@ "inputs": null, "dateType": "datepicker", "calendarIconType": "calendar", - "formId": 13, + "formId": 2, "description": "", "allowsPrepopulate": false, "inputMask": false, @@ -141,7 +141,7 @@ } ], "version": "2.3.2", - "id": 13, + "id": 2, "useCurrentUserAsAuthor": true, "postContentTemplateEnabled": false, "postTitleTemplateEnabled": false, @@ -150,6 +150,9 @@ "lastPageButton": null, "pagination": null, "firstPageCssClass": null, + "is_active": "1", + "date_created": "2018-08-09 15:35:59", + "is_trash": "0", "confirmations": [ { "id": "5b60b12baa00e", @@ -176,8 +179,8 @@ "feeds": { "gravityflow": [ { - "id": "31", - "form_id": "13", + "id": "3", + "form_id": "2", "is_active": "1", "feed_order": "0", "meta": { @@ -286,8 +289,8 @@ "event_type": null }, { - "id": "32", - "form_id": "13", + "id": "4", + "form_id": "2", "is_active": "1", "feed_order": "0", "meta": { @@ -377,7 +380,7 @@ "approval_notification_message": "Entry {entry_id} has been approved", "approval_notification_disable_autoformat": "0", "revertEnable": "0", - "revertValue": "31", + "revertValue": 3, "note_mode": "not_required", "expiration": "0", "expiration_type": "delay", @@ -390,7 +393,7 @@ "expiration_date_field": "4", "status_expiration": "rejected", "destination_expired": "next", - "destination_rejected": "31", + "destination_rejected": 3, "destination_approved": "complete" }, "addon_slug": "gravityflow", @@ -399,5 +402,5 @@ ] } }, - "version": "2.3.2.6" + "version": "2.3.2" } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_validate_questionnaire_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_validate_questionnaire_form.json index 340ad0d..e5e55f1 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_validate_questionnaire_form.json +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_validate_questionnaire_form.json @@ -30,7 +30,7 @@ "text": "wpUser" } ], - "formId": 9, + "formId": 3, "description": "", "allowsPrepopulate": true, "inputMask": false, @@ -71,7 +71,7 @@ "inputs": null, "dateType": "datepicker", "calendarIconType": "none", - "formId": 9, + "formId": 3, "description": "", "allowsPrepopulate": false, "inputMask": false, @@ -101,7 +101,7 @@ } ], "version": "2.3.2", - "id": 9, + "id": 3, "useCurrentUserAsAuthor": true, "postContentTemplateEnabled": false, "postTitleTemplateEnabled": false, @@ -110,17 +110,9 @@ "lastPageButton": null, "pagination": null, "firstPageCssClass": null, - "notifications": [ - { - "id": "5b5f68818822e", - "to": "{admin_email}", - "name": "Admin Notification", - "event": "form_submission", - "toType": "email", - "subject": "New submission from {form_title}", - "message": "{all_fields}" - } - ], + "is_active": "1", + "date_created": "2018-08-09 15:36:00", + "is_trash": "0", "confirmations": [ { "id": "5b5f688188e90", @@ -133,11 +125,22 @@ "queryString": "" } ], + "notifications": [ + { + "id": "5b5f68818822e", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], "feeds": { "gravityflow": [ { - "id": "20", - "form_id": "9", + "id": "5", + "form_id": "3", "is_active": "1", "feed_order": "0", "meta": { @@ -257,5 +260,5 @@ ] } }, - "version": "2.3.2.6" + "version": "2.3.2" } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_process_normal_delivery_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_process_normal_delivery_form.json index 997729c..7258d6f 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_process_normal_delivery_form.json +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_process_normal_delivery_form.json @@ -21,7 +21,7 @@ "visibility": "visible", "inputs": null, "numberFormat": "decimal_dot", - "formId": "11", + "formId": 5, "description": "", "allowsPrepopulate": true, "inputMask": false, @@ -71,7 +71,7 @@ "text": "wpUser" } ], - "formId": "11", + "formId": 5, "description": "", "allowsPrepopulate": true, "inputMask": false, @@ -102,7 +102,7 @@ } ], "version": "2.3.2.6", - "id": "11", + "id": 5, "useCurrentUserAsAuthor": true, "postContentTemplateEnabled": false, "postTitleTemplateEnabled": false, @@ -112,20 +112,8 @@ "pagination": null, "firstPageCssClass": null, "is_active": "1", - "date_created": "2018-07-30 20:53:56", + "date_created": "2018-08-09 15:36:00", "is_trash": "0", - "notifications": [ - { - "id": "5b5f7ae4baced", - "to": "{admin_email}", - "name": "Admin Notification", - "event": "form_submission", - "toType": "email", - "subject": "New submission from {form_title}", - "message": "{all_fields}", - "isActive": false - } - ], "confirmations": [ { "id": "5b5f7ae4bb79e", @@ -138,11 +126,23 @@ "queryString": "" } ], + "notifications": [ + { + "id": "5b5f7ae4baced", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}", + "isActive": false + } + ], "feeds": { "gravityflow": [ { - "id": "28", - "form_id": "11", + "id": "7", + "form_id": "5", "is_active": "1", "feed_order": "0", "meta": { @@ -164,7 +164,7 @@ "schedule_date_field_before_after": "after", "instructionsEnable": "0", "instructionsValue": "", - "target_form_id": "9", + "target_form_id": 3, "store_new_entry_idEnable": "1", "new_entry_id_field": "6", "destination_complete": "next" @@ -173,8 +173,8 @@ "event_type": null }, { - "id": "33", - "form_id": "11", + "id": "8", + "form_id": "5", "is_active": "1", "feed_order": "0", "meta": { @@ -196,7 +196,7 @@ "schedule_date_field_before_after": "after", "instructionsEnable": "0", "instructionsValue": "", - "target_form_id": "12", + "target_form_id": 4, "store_new_entry_idEnable": "0", "new_entry_id_field": "", "destination_complete": "next" @@ -205,8 +205,8 @@ "event_type": null }, { - "id": "34", - "form_id": "11", + "id": "9", + "form_id": "5", "is_active": "1", "feed_order": "0", "meta": { @@ -228,7 +228,7 @@ "schedule_date_field_before_after": "after", "instructionsEnable": "0", "instructionsValue": "", - "target_form_id": "12", + "target_form_id": 4, "store_new_entry_idEnable": "0", "new_entry_id_field": "", "destination_complete": "next" @@ -237,8 +237,8 @@ "event_type": null }, { - "id": "29", - "form_id": "11", + "id": "10", + "form_id": "5", "is_active": "1", "feed_order": "0", "meta": { @@ -258,7 +258,7 @@ "schedule_date_field_offset": "0", "schedule_date_field_offset_unit": "hours", "schedule_date_field_before_after": "after", - "target_form_id": "10", + "target_form_id": 1, "store_new_entry_idEnable": "1", "new_entry_id_field": "7", "destination_complete": "next" @@ -267,8 +267,8 @@ "event_type": null }, { - "id": "36", - "form_id": "11", + "id": "11", + "form_id": "5", "is_active": "1", "feed_order": "0", "meta": { @@ -290,7 +290,7 @@ "schedule_date_field_before_after": "after", "instructionsEnable": "0", "instructionsValue": "", - "target_form_id": "12", + "target_form_id": 4, "store_new_entry_idEnable": "0", "new_entry_id_field": "", "destination_complete": "next", @@ -300,8 +300,8 @@ "event_type": null }, { - "id": "35", - "form_id": "11", + "id": "12", + "form_id": "5", "is_active": "1", "feed_order": "0", "meta": { @@ -323,7 +323,7 @@ "schedule_date_field_before_after": "after", "instructionsEnable": "0", "instructionsValue": "", - "target_form_id": "12", + "target_form_id": 4, "store_new_entry_idEnable": "0", "new_entry_id_field": "", "destination_complete": "next" @@ -334,5 +334,5 @@ ] } }, - "version": "2.3.2.6" + "version": "2.3.2" } \ No newline at end of file From aa4a3daaf66639cb47ab729d9ec00d15c92c108e Mon Sep 17 00:00:00 2001 From: GotPPay Date: Tue, 14 Aug 2018 23:02:25 +0200 Subject: [PATCH 03/63] add custom endpoints for customer acceptance --- .../class-wiaas-rest-delivery-process-api.php | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 5a8d493..9b8a11c 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -1,6 +1,14 @@ 'GET', 'callback' => array(__CLASS__, 'get_next_actions_for_user'), ) ); + + register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'get_customer_acceptance'), + ) ); + + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'get_form_entry'), + ) ); + + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)/field/(?P\d+(.\d+)?)', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'get_field_value_from_entry'), + ) ); + + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( + 'methods' => 'PUT', + 'callback' => array(__CLASS__, 'update_entry'), + ) ); + + register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( + 'methods' => 'POST', + 'callback' => array(__CLASS__, 'update_customer_acceptance'), + ) ); + + register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)/upload-file' , array( + 'methods' => 'POST', + 'callback' => array(__CLASS__, 'upload_file'), + ) ); } @@ -62,4 +100,161 @@ class Wiass_REST_Delivery_Process_API { return $response; } + + public static function get_form_entry($data) { + //TODO: check for permissions + return GFAPI::get_entry($data['entry_id']); + } + + public static function get_customer_acceptance($data){ + //TODO: check for permissions + $entry = GFAPI::get_entry($data['entry_id']); + if (!$entry){ + return self::generate_error('Customer acceptance entry not found', 404); + } + + $acceptance_documents = array(); + $uploaded_files = json_decode($entry[self::$UPLOADED_FILES_FIELD_ID]); + + foreach($uploaded_files as $file_url){ + $info = pathinfo($file_url); + $acceptance_documents_entry = array( + 'name' => $info['filename'], + 'extension' => $info['extension'], + 'url' => $file_url + ); + array_push($acceptance_documents, $acceptance_documents_entry); + } + + $acceptance_status = 0; + if ($entry[self::$ACCEPTANCE_STATUS_FIELD_ID]){ + $acceptance_status = ($entry[self::$ACCEPTANCE_STATUS_FIELD_ID] == 'accept') ? 1 : -1; + } + + $result = array( + 'documents' => $acceptance_documents, + 'expiration' => $entry[self::$EXPIRATION_DATE_FIELD_ID], + 'status' => $acceptance_status, + 'decline_reason' => $entry[self::$DECLINE_REASON_FIELD_ID] + ); + + return new WP_REST_Response($result); + } + + public static function get_field_value_from_entry($data){ + //TODO : check for permissions + $entry = GFAPI::get_entry($data['entry_id']); + $result = $entry[$data['field_id']] ?: ''; + return new WP_REST_Response ($result); + } + + public static function update_entry($data){ + //TODO : check for permissions + $entry = GFAPI::get_entry($data['entry_id']); + $new_values = json_decode($data->get_body()); + if ($new_values == NULL) { + return new WP_REST_Response (); + } + $keys = get_object_vars($new_values); + foreach($keys as $key => $value){ + $entry[$key] = $value; + } + $result = GFAPI::update_entry( $entry ); + return new WP_REST_Response ($result); + } + + public static function update_customer_acceptance($data){ + //TODO : check for permissions + $entry = GFAPI::get_entry($data['entry_id']); + + $entry[self::$DECLINE_REASON_FIELD_ID] = $_POST['declineReason']; + $entry[self::$ACCEPTANCE_STATUS_FIELD_ID] = $_POST['actionType']; + + $result = GFAPI::update_entry( $entry ); + return new WP_REST_Response ($result); + } + + public static function upload_file($data){ + //TODO : Check permissions + + $input_name = "file"; + if (!$_FILES[$input_name]){ + return self::generate_error("No file", 400); + } + + $entry = GFAPI::get_entry($data['entry_id']); + if (!$entry['form_id']){ + return self::generate_error("Entry not found", 404); + } + + $form = GFAPI::get_form($entry['form_id']); + $form_upload_path = GFFormsModel::get_upload_path( $form['id'] ); + + $target_path = $form_upload_path . '/' . date("Y") . '/' . date("m") . '/'; + wp_mkdir_p( $target_path ); + GFCommon::recursive_add_index_file( $target_path ); + + $upload_file_field = GFAPI::get_field($form['id'], self::$UPLOADED_FILES_FIELD_ID); + $file_name = $_FILES[$input_name]['name']; + $file_path_details = pathinfo($file_name); + + if ( GFCommon::file_name_has_disallowed_extension( $file_name ) ) { + return self::generate_error("File extension is not allowed", 400); + } + $allowed_extensions = ! empty( $upload_file_field->allowedExtensions ) ? GFCommon::clean_extensions( explode( ',', strtolower( $upload_file_field->allowedExtensions ) ) ) : array(); + if ( ! empty( $allowed_extensions ) ) { + if ( ! GFCommon::match_file_extension( $file_name, $allowed_extensions ) ) { + return self::generate_error("File extension is not allowed", 400); + } + } + + $new_file_name = $file_path_details['filename'] . '-' . time() . '.' . $file_path_details['extension']; + + if ( move_uploaded_file( $_FILES[$input_name]['tmp_name'], $target_path . $new_file_name ) ) { + GFFormsModel::set_permissions( $target_path . $new_file_name ); + } else { + return self::generate_error("Internal server error"); + } + + //Extract path relative to the root + //Last 6 strings (excluding last empty) are path relative to the root + $path_parts = explode("/", $target_path); + + $relative_path = ""; + $i = count($path_parts) - 7; + while($i < count($path_parts)-1){ + $relative_path = $relative_path . $path_parts[$i] . "/"; + $i++; + } + + $file_url = self::$BASE_NAME . $relative_path . $new_file_name; + + $uploaded_files = json_decode($entry[self::$UPLOADED_FILES_FIELD_ID]); + + if ($uploaded_files == NULL){ + $uploaded_files = []; + } + array_push($uploaded_files, $file_url); + + $entry[self::$UPLOADED_FILES_FIELD_ID] = json_encode($uploaded_files); + + if (GFAPI::update_entry( $entry )) { + return new WP_REST_Response($uploaded_files); + } + + return self::generate_error('Error updating entry'); + } + + public static function generate_error($message, $code = 500){ + $error = array( + 'status' => $code, + 'message' => $message, + ); + + $result = new WP_REST_Response($error); + $result->set_status($code); + return $result; + } + + } \ No newline at end of file From 04c7a7536ff9b44cc056756921dc216ab3d0d1e7 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Tue, 14 Aug 2018 23:02:44 +0200 Subject: [PATCH 04/63] use custom endpoints for customer acceptance --- .../orders/customerAcceptanceActions.js | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/frontend/src/actions/orders/customerAcceptanceActions.js b/frontend/src/actions/orders/customerAcceptanceActions.js index 59f5cf7..9f1365f 100644 --- a/frontend/src/actions/orders/customerAcceptanceActions.js +++ b/frontend/src/actions/orders/customerAcceptanceActions.js @@ -23,15 +23,12 @@ const recieveCustomerAcceptance = (json) => ({ customerAcceptance: json }); -export const fetchCustomerAcceptance = (idOrder) => { +export const fetchCustomerAcceptance = (idEntry) => { return dispatch => { dispatch(requestCustomerAcceptance()); return htmlClient.fetch({ - url: `${API_SERVER}/orders/api/getCustomerAcceptance`, - method: 'post', - data: { - idOrder - } + url: `${API_SERVER}/wp-json/wiaas/customer-acceptance/${idEntry}`, + method: 'get' }) .then(response => { if (response.data) { @@ -48,18 +45,15 @@ const uploadAcceptanceAction = () => ({ type: UPLOAD_CUSTOMER_ACCEPTANCE }); -export const uploadAcceptance = (idOrder, file) => { +export const uploadAcceptance = (idEntry, file) => { return dispatch => { dispatch(uploadAcceptanceAction()); return htmlClient.uploadFile(file, { - url: `${API_SERVER}/orders/api/uploadAcceptanceDocument`, - data: { - idOrder - } + url: `${API_SERVER}/wp-json/wiaas/customer-acceptance/${idEntry}/upload-file` }).then(response => { - if (typeof response.data !== 'undefined' && 'messages' in response.data) { - dispatch(updateMessages(response.data.messages, orderMessages)); - dispatch(fetchCustomerAcceptance(idOrder)); + if (typeof response.data !== 'undefined') { + //dispatch(updateMessages(response.data.messages, orderMessages)); + dispatch(fetchCustomerAcceptance(idEntry)); } }).catch(error => { htmlClient.onError(error, dispatch); @@ -77,14 +71,13 @@ const sendCustomerAcceptance = () => ({ type: SEND_CUSTOMER_ACCEPTANCE }); -export const acceptDeclineInstallation = (idOrder, actionType, declineReason) => { +export const acceptDeclineInstallation = (idEntry, actionType, declineReason) => { return dispatch => { dispatch(sendCustomerAcceptance()); return htmlClient.fetch({ - url: `${API_SERVER}/orders/api/acceptDeclineInstallation`, + url: `${API_SERVER}/wp-json/wiaas/customer-acceptance/${idEntry}`, method: 'post', data: { - idOrder, actionType, declineReason } @@ -92,7 +85,7 @@ export const acceptDeclineInstallation = (idOrder, actionType, declineReason) => .then(response => { if (response.data) { dispatch(updateMessages(response.data.messages, orderMessages)); - dispatch(fetchCustomerAcceptance(idOrder)); + dispatch(fetchCustomerAcceptance(idEntry)); } }) .catch(error => { From 8b5374ee2403f8c6bd097e606a5f5a1a0bc852b1 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Tue, 14 Aug 2018 23:31:12 +0200 Subject: [PATCH 05/63] change endpoints for order details, comments and documents --- frontend/src/actions/orders/processActions.js | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/frontend/src/actions/orders/processActions.js b/frontend/src/actions/orders/processActions.js index 9ea9ce4..922a218 100644 --- a/frontend/src/actions/orders/processActions.js +++ b/frontend/src/actions/orders/processActions.js @@ -24,7 +24,9 @@ import { SET_SCHEDULING_DISABLED_FLAG } from '../../constants/ordersConstants'; import HtmlClient from '../../helpers/HtmlClient'; -import {updateMessages} from '../notification/notificationActions'; +import { updateMessages } from '../notification/notificationActions'; +import { fromWCOrder } from '../../helpers/OrderHelper'; +import moment from 'moment'; const htmlClient = new HtmlClient(); @@ -42,15 +44,12 @@ export const fetchOrderInfo = (idOrder) => { return dispatch => { dispatch(requestOrderInfo()); return htmlClient.fetch({ - url: `${API_SERVER}/orders/api/getOrderInfo`, - method: 'post', - data: { - idOrder - } - }) + url: `${API_SERVER}/wp-json/wc/v2/orders/${idOrder}`, + method: 'get' + }) .then(response => { if (response.data) { - dispatch(recieveOrderInfo(response.data)); + dispatch(recieveOrderInfo(fromWCOrder(response.data))); } }) .catch(error => { @@ -66,19 +65,34 @@ const sendComment = () => ({ export const addComment = (idOrder, comment) => { return dispatch => { dispatch(sendComment()); + //TODO: get real user name and store in comment object return htmlClient.fetch({ - url: `${API_SERVER}/orders/api/addOrderComment`, - method: 'post', - data: { - idOrder, - comment - } - }) + url: `${API_SERVER}/wp-json/wc/v2/orders/${idOrder}`, + method: 'post', + data: { + meta_data: [ + { + key: `comment-${moment().unix()}`, + value: { + comment: comment, + addDate: moment().format("Do MMM, YY"), + username: 'username', + isOwner: 1 + } + } + ] + } + }) .then(response => { + if (response.data) { + dispatch(fetchOrderInfo(idOrder)); + } + /* if (response.data && response.data.messages) { dispatch(updateMessages(response.data.messages, orderMessages)); dispatch(fetchOrderInfo(idOrder)); } + */ }) .catch(error => { htmlClient.onError(error, dispatch); From 672fb627283f02d7ff30e213cb3d7714224f839b Mon Sep 17 00:00:00 2001 From: GotPPay Date: Tue, 14 Aug 2018 23:35:45 +0200 Subject: [PATCH 06/63] use new object properties for orders and process --- .../containers/orders/ProcessContainer.jsx | 8 ++--- .../components/process/CustomerAcceptance.jsx | 35 ++++++++++--------- .../components/process/OrderProcess.jsx | 4 +-- .../orders/components/process/ProcessStep.jsx | 2 +- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/frontend/src/containers/orders/ProcessContainer.jsx b/frontend/src/containers/orders/ProcessContainer.jsx index fe34fc6..a809ae6 100644 --- a/frontend/src/containers/orders/ProcessContainer.jsx +++ b/frontend/src/containers/orders/ProcessContainer.jsx @@ -44,7 +44,7 @@ class ProcessContainer extends Component { componentDidMount() { this.props.dispatch(fetchOrderInfo(this.props.idOrder)); - this.props.dispatch(getAllDataForInstallation(this.props.idOrder, usedForDirective, stepsNameForInstallation, fileType)); + //this.props.dispatch(getAllDataForInstallation(this.props.idOrder, usedForDirective, stepsNameForInstallation, fileType)); const orderPackagePairs = []; const isSchedulingDisabled = {}; isSchedulingDisabled[this.props.idOrder] = true; @@ -187,12 +187,12 @@ class ProcessContainer extends Component {
} { - (orderInfo && orderInfo.info && !isLoading) && + (orderInfo && !isLoading) &&
+ orderProcess={orderInfo.process}/> } { this.state.activeView === 'packages' && diff --git a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx index 50feaed..567ca40 100644 --- a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx +++ b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx @@ -26,15 +26,16 @@ class CustomerAcceptance extends Component { } downloadDocument(document){ - const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}` - const fileName = document.documentName + '.' + document.extension; + //const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}` + const fileUrl = document.url; + const fileName = document.name + '.' + document.extension; fileHandler.download(fileUrl, fileName); } - uploadFile(idOrder, acceptedFiles, rejectedFiles) { + uploadFile(idEntry, acceptedFiles, rejectedFiles) { if(acceptedFiles && acceptedFiles.length){ const file = acceptedFiles[0]; - this.props.dispatch(uploadAcceptance(idOrder, file)); + this.props.dispatch(uploadAcceptance(idEntry, file)); } if(rejectedFiles && rejectedFiles.length) { @@ -59,9 +60,9 @@ class CustomerAcceptance extends Component { } acceptDeclineInstallation() { - const {idOrder} = this.props.step; + const {idProcess} = this.props.step; const {actionType, reason} = this.state; - this.props.dispatch(acceptDeclineInstallation(idOrder, actionType, reason)); + this.props.dispatch(acceptDeclineInstallation(idProcess, actionType, reason)); this.setState({reason: ''}); } @@ -72,7 +73,7 @@ class CustomerAcceptance extends Component { '-1' : orderTexts.labels.DECLINED } - return messages[customerAcceptance.customerAccepted]; + return messages[customerAcceptance.status]; } onEditorChange(reason) { @@ -107,8 +108,8 @@ class CustomerAcceptance extends Component { } componentDidMount(){ - const {idOrder} = this.props.step; - this.props.dispatch(fetchCustomerAcceptance(idOrder)); + const {idProcess} = this.props.step; + this.props.dispatch(fetchCustomerAcceptance(idProcess)); } render() { @@ -121,14 +122,14 @@ class CustomerAcceptance extends Component { customerAcceptance && - {this.getAcceptanceMessage(customerAcceptance)}
+ {this.getAcceptanceMessage(customerAcceptance)}
} { - (customerAcceptance && customerAcceptance.customerAccepted === -1) && + (customerAcceptance && customerAcceptance.status === -1) && - {orderTexts.labels.REASON}: {customerAcceptance.customerDeclineReason} + {orderTexts.labels.REASON}: {customerAcceptance.decline_reason} } @@ -137,19 +138,19 @@ class CustomerAcceptance extends Component { multiple={false} accept=".pdf,.docx,.doc,.xlsx,.xls,.odt,.ods,.jpg,.png,.jpeg" activeClassName="upload-file-accept" - onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(step.idOrder, acceptedFiles, rejectedFiles)}}> + onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(step.idProcess, acceptedFiles, rejectedFiles)}}>
{orderTexts.labels.UPLOAD_ACCEPTANCE_LABEL}
{ - (customerAcceptance && customerAcceptance.acceptanceDocuments && customerAcceptance.acceptanceDocuments.length > 0) && + (customerAcceptance && customerAcceptance.documents && customerAcceptance.documents.length > 0) &&
{ - customerAcceptance.acceptanceDocuments.map(document =>
+ customerAcceptance.documents.map((document, index) =>
{this.downloadDocument(document)}}> - {document.documentName} ({document.extension}) + {document.name} ({document.extension}) {document.validation}
@@ -159,7 +160,7 @@ class CustomerAcceptance extends Component {
} { - (customerAcceptance && !customerAcceptance.acceptanceDocuments) && + (customerAcceptance && (!customerAcceptance.documents || customerAcceptance.documents.length === 0) ) &&
{orderTexts.labels.NO_DOCUMENTS_UPLOADED}
diff --git a/frontend/src/containers/orders/components/process/OrderProcess.jsx b/frontend/src/containers/orders/components/process/OrderProcess.jsx index b6087fb..3424e32 100644 --- a/frontend/src/containers/orders/components/process/OrderProcess.jsx +++ b/frontend/src/containers/orders/components/process/OrderProcess.jsx @@ -7,7 +7,7 @@ const completedOrdersStatuses = ['production', 'end-of-life']; class OrderProcess extends Component { isStepVisible(step) { - return (step.status === 'in-progress' || step.status === 'done') && step.isVisibleForCustomer === 1; + return (step.status === 'pending' || step.status === 'complete') && step.isVisibleForCustomer === 1; } render() { @@ -41,7 +41,7 @@ class OrderProcess extends Component { { - visibleSteps.map((step, index) => ) + visibleSteps.reverse().map((step, index) => ) } diff --git a/frontend/src/containers/orders/components/process/ProcessStep.jsx b/frontend/src/containers/orders/components/process/ProcessStep.jsx index a369c74..2f68ee2 100644 --- a/frontend/src/containers/orders/components/process/ProcessStep.jsx +++ b/frontend/src/containers/orders/components/process/ProcessStep.jsx @@ -11,7 +11,7 @@ const stepActions = { class OrderStep extends Component { isActiveStep(status) { - return status === 'in-progress' ; + return status === 'pending' ; } getStepTitle(step, stepNumber) { From beea3c95a00433e93fc189296f6722c500660d35 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Tue, 14 Aug 2018 23:36:49 +0200 Subject: [PATCH 07/63] add new css class for new status --- .../src/containers/orders/style/ProcessContainer.scss | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/containers/orders/style/ProcessContainer.scss b/frontend/src/containers/orders/style/ProcessContainer.scss index f3e72cf..225f339 100644 --- a/frontend/src/containers/orders/style/ProcessContainer.scss +++ b/frontend/src/containers/orders/style/ProcessContainer.scss @@ -139,11 +139,15 @@ $link-line-height: 1.5rem; background: $open-status-color; } -.done { +.complete { background: $done-status-color; } -.in-progress { +.processing { + background: $in-progress-status-color; +} + +.pending { background: $in-progress-status-color; } From b923b35323dcc4fc87f2d858ae452740b0271805 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 00:01:18 +0200 Subject: [PATCH 08/63] change file upload data --- frontend/src/helpers/HtmlClient.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/helpers/HtmlClient.js b/frontend/src/helpers/HtmlClient.js index 4bf4dab..33a6a18 100644 --- a/frontend/src/helpers/HtmlClient.js +++ b/frontend/src/helpers/HtmlClient.js @@ -46,9 +46,11 @@ class HtmlClient { let formData = new FormData(); formData.append('file', file, file.name); if(configParams) { + /* Object.keys(configParams.data).forEach((paramKey) => { formData.append(paramKey, configParams.data[paramKey]); }); + */ } configParams.data = formData; const params = Object.assign({}, uploadParams(), configParams); From aef9bc5ba902090e70154c7ddb5ab6efd38a6ac1 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 09:58:13 +0200 Subject: [PATCH 09/63] add helper functions for order and process object transformations --- frontend/src/helpers/OrderHelper.js | 122 ++++++++++++++++++++++++++ frontend/src/helpers/ProcessHelper.js | 19 ++++ 2 files changed, 141 insertions(+) create mode 100644 frontend/src/helpers/ProcessHelper.js diff --git a/frontend/src/helpers/OrderHelper.js b/frontend/src/helpers/OrderHelper.js index 9eafd55..9266928 100644 --- a/frontend/src/helpers/OrderHelper.js +++ b/frontend/src/helpers/OrderHelper.js @@ -1,4 +1,126 @@ import moment from 'moment'; +import {fromWiaasProcessStep} from './ProcessHelper'; + +const tempTransformationFunction = (order) => { + let processInfo = Object.assign({},order['delivery-process']); + if (order['delivery-process']){ + processInfo.steps = order['delivery-process'].steps.map(step=>fromWiaasProcessStep(step)); + } + /* + let processInfo = Object.assign({},order['delivery-process']); + processInfo.steps = order['delivery-process'].steps.map(step=>fromWiaasProcessStep(step)); + /* + processInfo[order['delivery-process'].id] = { + idProcess: order['delivery-process'].id, + processName: order['delivery-process'].name, + steps: order['delivery-process'].steps.map(step => { + return transformProcessStep(step, order['delivery-process'].id); + }) + }*/ + + let TransformedPackagesArray = order.line_items.map(packageItem => { + return { + endOfLife: null, + units: packageItem.quantity, + packageFixedPrice: packageItem.price, + packageRecurringPrice: 0, + packageServicePrice: 0, + status: 'no-process', + packagePayPeriod: 0, + servicesContractPeriod: 0, + maxContractPeriod: 0, + periodUnit: 'months', + paymentType: 'Managed service 36M rent', + idOrder: order.id, + idPackage: packageItem.id, + packageName: packageItem.name, + packageCurrency: { + currency: order.currency + }, + documents: [{ + idDocument: 1, + documentName: 'customerQuestionaire_343_32_2', + documentPath: 'path/to/document/withExtension.docx', + extension: 'docx', + documentType: 'Order Questionaire', + documentTypeName: 'orderQuestionarie', + idPackage: packageItem.id + }], + options: [], + additionalPackages: [], + idOrderPackagePair: `${order.id}-${packageItem.id}` + } + }); + + //going through same array again - for cleaner code + let newProductsObject = {}; + order.line_items.forEach(element => { + newProductsObject[element.id] = { + software: [{ + productName: 'Software product', + category: 'software', + idPackage: element.id + }], + hardware: [{ + productName: 'Hardware product', + category: 'hardware', + idPackage: element.id + }], + service: [{ + productName: 'Service product', + category: 'service', + idPackage: element.id + }], + installation: [{ + productName: 'Installation product', + category: 'installation', + idPackage: element.id + }] + } + }); + + let comments = []; + let processID = null; + order.meta_data.forEach(element => { + if (element.key.substring(0, 7) === 'comment') { + comments.push(element.value); + } + }); + + return { + info: { + id: order.id, + orderNumber: order.number, + orderDate: moment(order.date_created).format("Do MMM, YYYY"), + estimatedDeliveryDate: null, + billingFirstName: order.billing.first_name, + billingLastName: order.billing.last_name, + billingMail: order.billing.email, + billingAddress: order.billing.address_1 + ' ' + order.billing.address_2, + status: order.status, + reference: 'reference field', + tender: 'tender field', + idTerms: null, + idProject: null, + projectName: 'project name field', + assignedTo: 'assigned to', + customer: 'customer field', + phone: null, + mail: '', + idCommercialLead: null, + commercialLead: '', + endOfLife: null, + idProcess: processID, + }, + products: newProductsObject, + packages: TransformedPackagesArray, + process: processInfo, + orderDocuments: [], + selections: [], + orderComments: comments, + availableProcesses: [], + } +} function formatDate(date) { return date ? moment(date).format("Do MMM, YYYY") : undefined; diff --git a/frontend/src/helpers/ProcessHelper.js b/frontend/src/helpers/ProcessHelper.js new file mode 100644 index 0000000..74d1c8e --- /dev/null +++ b/frontend/src/helpers/ProcessHelper.js @@ -0,0 +1,19 @@ +import moment from "moment"; + +export const fromWiaasProcessStep = (step) => { + return { + actionCode: step.action_code, + actualDate: step.actual_date, + comments: step.comments, + fullDesc: step.full_desc, + idOrder: step.order_id, + idProcess: step.step_form_entry_id, //not sure about this + idProcessStep: step.step_id, //not sure about this + isNewCommentVisible: 1, //TODO : get this from backend + isVisibleForCustomer: 1, //TODO : get this from backend + now: moment().format("Do MMM YY"), + shortDesc: step.short_desc, + status: step.status, + stepType: step.step_type, + } +}; \ No newline at end of file From a9bcd9877445f0bb2872dbc012d72716939625e6 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:18:36 +0200 Subject: [PATCH 10/63] add commercial lead ID --- backend/app/plugins/wiaas/includes/class-wiaas-order.php | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-order.php b/backend/app/plugins/wiaas/includes/class-wiaas-order.php index b8fa3ff..816a168 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-order.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-order.php @@ -126,6 +126,7 @@ class Wiaas_Order { private static function _append_commercial_lead_info($data, $order, $request) { $data['commercial_lead'] = array( + 'id' => 1, 'name' => 'Coor Service Management', 'phone' => '123456789', 'email' => 'rikard@co-ideation.com' From 152804d6dc7f8de15ea533853aa129d030dcaf8e Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:19:05 +0200 Subject: [PATCH 11/63] comment function used for testing --- .../class-wiaas-rest-delivery-process-api.php | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 9b8a11c..26673ac 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -28,6 +28,10 @@ class Wiass_REST_Delivery_Process_API { 'callback' => array(__CLASS__, 'get_customer_acceptance'), ) ); + /* + + Used for some fast test and check + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( 'methods' => 'GET', 'callback' => array(__CLASS__, 'get_form_entry'), @@ -43,6 +47,8 @@ class Wiass_REST_Delivery_Process_API { 'callback' => array(__CLASS__, 'update_entry'), ) ); + */ + register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'POST', 'callback' => array(__CLASS__, 'update_customer_acceptance'), @@ -101,13 +107,9 @@ class Wiass_REST_Delivery_Process_API { return $response; } - public static function get_form_entry($data) { - //TODO: check for permissions - return GFAPI::get_entry($data['entry_id']); - } - public static function get_customer_acceptance($data){ //TODO: check for permissions + $entry = GFAPI::get_entry($data['entry_id']); if (!$entry){ return self::generate_error('Customer acceptance entry not found', 404); @@ -128,7 +130,7 @@ class Wiass_REST_Delivery_Process_API { $acceptance_status = 0; if ($entry[self::$ACCEPTANCE_STATUS_FIELD_ID]){ - $acceptance_status = ($entry[self::$ACCEPTANCE_STATUS_FIELD_ID] == 'accept') ? 1 : -1; + $acceptance_status = ($entry[self::$ACCEPTANCE_STATUS_FIELD_ID] === 'accept') ? 1 : -1; } $result = array( @@ -141,28 +143,6 @@ class Wiass_REST_Delivery_Process_API { return new WP_REST_Response($result); } - public static function get_field_value_from_entry($data){ - //TODO : check for permissions - $entry = GFAPI::get_entry($data['entry_id']); - $result = $entry[$data['field_id']] ?: ''; - return new WP_REST_Response ($result); - } - - public static function update_entry($data){ - //TODO : check for permissions - $entry = GFAPI::get_entry($data['entry_id']); - $new_values = json_decode($data->get_body()); - if ($new_values == NULL) { - return new WP_REST_Response (); - } - $keys = get_object_vars($new_values); - foreach($keys as $key => $value){ - $entry[$key] = $value; - } - $result = GFAPI::update_entry( $entry ); - return new WP_REST_Response ($result); - } - public static function update_customer_acceptance($data){ //TODO : check for permissions $entry = GFAPI::get_entry($data['entry_id']); @@ -231,7 +211,7 @@ class Wiass_REST_Delivery_Process_API { $uploaded_files = json_decode($entry[self::$UPLOADED_FILES_FIELD_ID]); - if ($uploaded_files == NULL){ + if ($uploaded_files === NULL){ $uploaded_files = []; } array_push($uploaded_files, $file_url); @@ -245,7 +225,40 @@ class Wiass_REST_Delivery_Process_API { return self::generate_error('Error updating entry'); } - public static function generate_error($message, $code = 500){ + //Used for testing and checking + /* + public static function get_form_entry($data) { + //TODO: check for permissions + return GFAPI::get_entry($data['entry_id']); + } + + public static function get_field_value_from_entry($data){ + //TODO : check for permissions + $entry = GFAPI::get_entry($data['entry_id']); + $result = $entry[$data['field_id']] ?: ''; + return new WP_REST_Response ($result); + } + + public static function update_entry($data){ + //TODO : check for permissions + $entry = GFAPI::get_entry($data['entry_id']); + $new_values = json_decode($data->get_body()); + if ($new_values === NULL) { + return new WP_REST_Response (); + } + $keys = get_object_vars($new_values); + foreach($keys as $key => $value){ + $entry[$key] = $value; + } + $result = GFAPI::update_entry( $entry ); + return new WP_REST_Response ($result); + } + + */ + + + //Helper function + private static function generate_error($message, $code = 500){ $error = array( 'status' => $code, 'message' => $message, From 768e3b919e3f3dc6c0072e4a70bb2f8a6cc826bd Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:19:24 +0200 Subject: [PATCH 12/63] change comments handling --- frontend/src/actions/orders/processActions.js | 21 +++++++++++-------- .../orders/components/OrderComments.jsx | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/frontend/src/actions/orders/processActions.js b/frontend/src/actions/orders/processActions.js index 922a218..808c40c 100644 --- a/frontend/src/actions/orders/processActions.js +++ b/frontend/src/actions/orders/processActions.js @@ -62,23 +62,26 @@ const sendComment = () => ({ type: SEND_ORDER_COMMENT }) -export const addComment = (idOrder, comment) => { +export const addComment = (idOrder, newComment, existingComments) => { return dispatch => { dispatch(sendComment()); //TODO: get real user name and store in comment object + const newCommentObject = { + comment : newComment, + date : moment().format("Do MMM, YY"), + username: 'username', + isOwner: 1, + } + const concatenatedComments = (existingComments) ? existingComments.concat(newCommentObject) : [newCommentObject]; + return htmlClient.fetch({ url: `${API_SERVER}/wp-json/wc/v2/orders/${idOrder}`, - method: 'post', + method: 'put', data: { meta_data: [ { - key: `comment-${moment().unix()}`, - value: { - comment: comment, - addDate: moment().format("Do MMM, YY"), - username: 'username', - isOwner: 1 - } + key:'comments', + value: JSON.stringify(concatenatedComments), } ] } diff --git a/frontend/src/containers/orders/components/OrderComments.jsx b/frontend/src/containers/orders/components/OrderComments.jsx index 85fc4c3..c30bcaa 100644 --- a/frontend/src/containers/orders/components/OrderComments.jsx +++ b/frontend/src/containers/orders/components/OrderComments.jsx @@ -18,7 +18,7 @@ class OrderComments extends Component { } addNewComment(){ - this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment)); + this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment, this.props.orderComments)); } onEditorChange(newComment){ @@ -48,7 +48,7 @@ class OrderComments extends Component {
-
{orderComment.username} - {orderComment.addDate}
+
{orderComment.username} - {orderComment.date}
From 5399e3901bc10a3eb1ad75b765a822b37e8962c1 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:20:02 +0200 Subject: [PATCH 13/63] remove hardcoded values and change comment handling --- frontend/src/helpers/OrderHelper.js | 140 ++++------------------------ 1 file changed, 19 insertions(+), 121 deletions(-) diff --git a/frontend/src/helpers/OrderHelper.js b/frontend/src/helpers/OrderHelper.js index 9266928..202f4a6 100644 --- a/frontend/src/helpers/OrderHelper.js +++ b/frontend/src/helpers/OrderHelper.js @@ -1,127 +1,6 @@ import moment from 'moment'; import {fromWiaasProcessStep} from './ProcessHelper'; -const tempTransformationFunction = (order) => { - let processInfo = Object.assign({},order['delivery-process']); - if (order['delivery-process']){ - processInfo.steps = order['delivery-process'].steps.map(step=>fromWiaasProcessStep(step)); - } - /* - let processInfo = Object.assign({},order['delivery-process']); - processInfo.steps = order['delivery-process'].steps.map(step=>fromWiaasProcessStep(step)); - /* - processInfo[order['delivery-process'].id] = { - idProcess: order['delivery-process'].id, - processName: order['delivery-process'].name, - steps: order['delivery-process'].steps.map(step => { - return transformProcessStep(step, order['delivery-process'].id); - }) - }*/ - - let TransformedPackagesArray = order.line_items.map(packageItem => { - return { - endOfLife: null, - units: packageItem.quantity, - packageFixedPrice: packageItem.price, - packageRecurringPrice: 0, - packageServicePrice: 0, - status: 'no-process', - packagePayPeriod: 0, - servicesContractPeriod: 0, - maxContractPeriod: 0, - periodUnit: 'months', - paymentType: 'Managed service 36M rent', - idOrder: order.id, - idPackage: packageItem.id, - packageName: packageItem.name, - packageCurrency: { - currency: order.currency - }, - documents: [{ - idDocument: 1, - documentName: 'customerQuestionaire_343_32_2', - documentPath: 'path/to/document/withExtension.docx', - extension: 'docx', - documentType: 'Order Questionaire', - documentTypeName: 'orderQuestionarie', - idPackage: packageItem.id - }], - options: [], - additionalPackages: [], - idOrderPackagePair: `${order.id}-${packageItem.id}` - } - }); - - //going through same array again - for cleaner code - let newProductsObject = {}; - order.line_items.forEach(element => { - newProductsObject[element.id] = { - software: [{ - productName: 'Software product', - category: 'software', - idPackage: element.id - }], - hardware: [{ - productName: 'Hardware product', - category: 'hardware', - idPackage: element.id - }], - service: [{ - productName: 'Service product', - category: 'service', - idPackage: element.id - }], - installation: [{ - productName: 'Installation product', - category: 'installation', - idPackage: element.id - }] - } - }); - - let comments = []; - let processID = null; - order.meta_data.forEach(element => { - if (element.key.substring(0, 7) === 'comment') { - comments.push(element.value); - } - }); - - return { - info: { - id: order.id, - orderNumber: order.number, - orderDate: moment(order.date_created).format("Do MMM, YYYY"), - estimatedDeliveryDate: null, - billingFirstName: order.billing.first_name, - billingLastName: order.billing.last_name, - billingMail: order.billing.email, - billingAddress: order.billing.address_1 + ' ' + order.billing.address_2, - status: order.status, - reference: 'reference field', - tender: 'tender field', - idTerms: null, - idProject: null, - projectName: 'project name field', - assignedTo: 'assigned to', - customer: 'customer field', - phone: null, - mail: '', - idCommercialLead: null, - commercialLead: '', - endOfLife: null, - idProcess: processID, - }, - products: newProductsObject, - packages: TransformedPackagesArray, - process: processInfo, - orderDocuments: [], - selections: [], - orderComments: comments, - availableProcesses: [], - } -} - function formatDate(date) { return date ? moment(date).format("Do MMM, YYYY") : undefined; } @@ -130,7 +9,18 @@ function formatAddress(addressObject) { return `${addressObject.address_1}, ${addressObject.city}, ${addressObject.country}, ${addressObject.postcode}`; } +function extractComments(metaDataArray){ + const commentsObject = metaDataArray.find(metaDataElement => { + return metaDataElement.key === "comments"; + }); + return commentsObject ? JSON.parse(commentsObject.value) : []; +} + export const fromWCOrder = (WCOrder) => { + let processInfo = Object.assign({},WCOrder['delivery-process']); + if (WCOrder['delivery-process']){ + processInfo.steps = WCOrder['delivery-process'].steps.map(step=>fromWiaasProcessStep(step)); + } return { id: WCOrder.id, number: WCOrder.number, @@ -144,6 +34,12 @@ export const fromWCOrder = (WCOrder) => { recurringPrice: 0, status: WCOrder.status, currency: WCOrder.currency, + billing:{ + firstName: WCOrder.billing.first_name, + lastName: WCOrder.billing.last_name, + email: WCOrder.billing.email, + address: formatAddress(WCOrder.billing) + }, packages: WCOrder['line_items'].map(packageLine => { return { id: packageLine['product_id'], @@ -162,6 +58,8 @@ export const fromWCOrder = (WCOrder) => { dateCompleted: formatDate(packageLine['date_completed']), }; }), + process: processInfo, + comments: extractComments(WCOrder.meta_data), deliveryAddress: formatAddress(WCOrder.shipping), customer: WCOrder.customer, commercialLead: WCOrder['commercial_lead'] From 74a6905a23566e02314554b407cd009c01c8c22b Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:21:29 +0200 Subject: [PATCH 14/63] use new object property names --- .../containers/orders/ProcessContainer.jsx | 40 +++++++++---------- .../orders/components/OrderDocuments.jsx | 4 +- .../orders/components/OrderDocumentsGroup.jsx | 1 + .../orders/components/OrderInfo.jsx | 16 ++++---- .../orders/components/PackagesNav.jsx | 6 +-- .../components/packages/PackageInfo.jsx | 28 ++++++------- .../components/packages/PackageName.jsx | 2 +- .../components/packages/ProcessPackage.jsx | 4 +- 8 files changed, 49 insertions(+), 52 deletions(-) diff --git a/frontend/src/containers/orders/ProcessContainer.jsx b/frontend/src/containers/orders/ProcessContainer.jsx index a809ae6..4c04de0 100644 --- a/frontend/src/containers/orders/ProcessContainer.jsx +++ b/frontend/src/containers/orders/ProcessContainer.jsx @@ -52,7 +52,7 @@ class ProcessContainer extends Component { if(this.props.orderInfo) { this.props.orderInfo.packages.forEach(orderPackage => { - orderPackagePairs.push(orderPackage.idOrder + '-' + orderPackage.idPackage); + orderPackagePairs.push(this.props.orderInfo.id + '-' + orderPackage.id); }); } this.setState({ @@ -71,11 +71,11 @@ class ProcessContainer extends Component { if(installCompanies && isComponentDisabled && earliestInstallDate) { if(nextProps.orderInfo) { + const idOrder = nextProps.orderInfo.id; nextProps.orderInfo.packages.forEach(orderPackage => { - const idOrder = orderPackage && orderPackage.idOrder; - const idOrderPackagePair = orderPackage ? idOrder + '-' + orderPackage.idPackage : ''; + const idOrderPackagePair = orderPackage ? idOrder + '-' + orderPackage.id : ''; orderPackage.idOrderPackagePair = idOrderPackagePair; - areComponentsDisabled[idOrder] = this.checkIfComponentIsDisabled(orderPackage.idOrder, isComponentDisabled, earliestInstallDate); + areComponentsDisabled[idOrder] = this.checkIfComponentIsDisabled(idOrder, isComponentDisabled, earliestInstallDate); const availableCompanies = {}; const selectedCompanies = {}; @@ -101,7 +101,7 @@ class ProcessContainer extends Component { }); const isSchedulingDisabled = Object.assign({}, this.state.isSchedulingDisabled); - isSchedulingDisabled[nextProps.orderInfo.info.id] = allPackagesScheduleInstallDisabled.every(isDisabled => {return isDisabled === true;}); + isSchedulingDisabled[nextProps.orderInfo.id] = allPackagesScheduleInstallDisabled.every(isDisabled => {return isDisabled === true;}); this.setState({ isSchedulingDisabled, areComponentsDisabled, @@ -126,16 +126,16 @@ class ProcessContainer extends Component { return true; } - calculatetTotalPrice(packages) { - let fixedPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.units * pkg.packageFixedPrice})); - let recurrentPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.units * pkg.packageRecuringPrice})); - let servicesPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.units * pkg.packageServicePrice})); + calculatetTotalPrice(packages, currency) { + let fixedPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.quantity * pkg.price})); + let recurrentPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.quantity * pkg.recurringPrice})); + let servicesPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.quantity * pkg.servicePrice})); return { fixedPrice, recurrentPrice: priceHelper.sumPrices([recurrentPrice, servicesPrice]), periodUnit: packages[0].periodUnit, - currency: packages[0].packageCurrency.currency + currency: currency } } @@ -158,15 +158,10 @@ class ProcessContainer extends Component { if(this.state.packageNameFilter === 'all') { return true; }else{ - return orderPackage.packageName === this.state.packageNameFilter; + return orderPackage.name === this.state.packageNameFilter; } } - getProcess(process){ - const processKeys = Object.keys(process) || []; - return processKeys.length > 0 ? process[processKeys[0]] : {}; - } - getButtonClass() { if(this.props.orderInfo) { return this.state.isSchedulingDisabled[this.props.orderInfo.id] ? 'schedule-inactive' : 'schedule-active'; @@ -198,7 +193,7 @@ class ProcessContainer extends Component { getActiveView: this.getActiveView, installationData: this.state }}> - + { this.state.activeView !== 'info' && @@ -221,9 +216,10 @@ class ProcessContainer extends Component { > { orderInfo.packages.filter(this.filterPackages).map(orderPackage => - ) } @@ -231,18 +227,18 @@ class ProcessContainer extends Component { } { this.state.activeView === 'comments' && - + } { this.state.activeView === 'documents' && - + }
} { - (orderInfo && !orderInfo.info && !isLoading) && + (!orderInfo && !isLoading) &&
{orderTexts.labels.NOT_AVAILABLE}!
diff --git a/frontend/src/containers/orders/components/OrderDocuments.jsx b/frontend/src/containers/orders/components/OrderDocuments.jsx index 555d86e..1b42f47 100644 --- a/frontend/src/containers/orders/components/OrderDocuments.jsx +++ b/frontend/src/containers/orders/components/OrderDocuments.jsx @@ -10,10 +10,10 @@ class OrderDocuments extends Component { return (
{ - orderInfo.packages.map(orderPackage => ) + orderInfo.packages.map(orderPackage => ) } { - orderInfo.orderDocuments && + orderInfo.orderDocuments && }
); diff --git a/frontend/src/containers/orders/components/OrderDocumentsGroup.jsx b/frontend/src/containers/orders/components/OrderDocumentsGroup.jsx index 5f15380..cd11fb0 100644 --- a/frontend/src/containers/orders/components/OrderDocumentsGroup.jsx +++ b/frontend/src/containers/orders/components/OrderDocumentsGroup.jsx @@ -57,6 +57,7 @@ class OrderDocumentsGroup extends Component { return (
{ + documentsGroup.documents && documentsGroup.documents.length > 0 && { diff --git a/frontend/src/containers/orders/components/OrderInfo.jsx b/frontend/src/containers/orders/components/OrderInfo.jsx index fd69b6f..5ba0603 100644 --- a/frontend/src/containers/orders/components/OrderInfo.jsx +++ b/frontend/src/containers/orders/components/OrderInfo.jsx @@ -27,7 +27,7 @@ class OrderInfo extends Component { setInstallationData(props) { const acceptedDate = {}; const proposedDate = {}; - const idOrder = props.orderDetails.info.id; + const idOrder = props.orderDetails.id; const {isInstallationInPackage} = props.installationData; const {confirmationDates, areAllShippingDatesConfirmed} = props; const isPreliminaryInstallationDate = areAllShippingDatesConfirmed && idOrder in areAllShippingDatesConfirmed ? !areAllShippingDatesConfirmed[idOrder] : true; @@ -53,27 +53,27 @@ class OrderInfo extends Component { const {acceptedDate, proposedDate, isPreliminaryInstallationDate, isInstallationInOrder} = this.state; const orderPackages = installationData.packages; const isInstallationInPackage = installationData.isInstallationInPackage; - const orderInfo = this.props.orderInfo.info; + const orderInfo = this.props.orderInfo; return (
{orderTexts.labels.ORDER_DATE}:
- {orderInfo.orderDate} + {orderInfo.dateCreated}
{orderTexts.labels.SOLD_BY}:
- {orderInfo.commercialLead} + {orderInfo.commercialLead.name}
{orderTexts.labels.BILLING_FIRST_NAME}:
- {orderInfo.billingFirstName || '-'} + {orderInfo.billing.firstName || '-'}
{orderTexts.labels.BILLING_LAST_NAME}:
- {orderInfo.billingLastName || '-'} + {orderInfo.billing.lastName || '-'}
{orderTexts.labels.BILLING_MAIL}:
- {orderInfo.billingMail || '-'} + {orderInfo.billing.email || '-'}
{orderTexts.labels.BILLING_ADDRESS}:
- {orderInfo.billingAddress || '-'} + {orderInfo.billing.address || '-'}
diff --git a/frontend/src/containers/orders/components/PackagesNav.jsx b/frontend/src/containers/orders/components/PackagesNav.jsx index 51207fe..a2eb098 100644 --- a/frontend/src/containers/orders/components/PackagesNav.jsx +++ b/frontend/src/containers/orders/components/PackagesNav.jsx @@ -21,9 +21,9 @@ class PackageNav extends Component {
{onPackageFilter('all')}}>{orderTexts.buttons.ALL}
{ packages.length > 0 && - packages.map((orderPackage) =>
{onPackageFilter(orderPackage.packageName)}} - className={this.getClass(orderPackage.packageName)}>{orderPackage.packageName}
) + packages.map((orderPackage) =>
{onPackageFilter(orderPackage.name)}} + className={this.getClass(orderPackage.name)}>{orderPackage.name}
) } diff --git a/frontend/src/containers/orders/components/packages/PackageInfo.jsx b/frontend/src/containers/orders/components/packages/PackageInfo.jsx index 27040ad..66d086e 100644 --- a/frontend/src/containers/orders/components/packages/PackageInfo.jsx +++ b/frontend/src/containers/orders/components/packages/PackageInfo.jsx @@ -29,8 +29,8 @@ class PackageInfo extends Component { } render() { - const {orderPackage, onViewChange} = this.props; - const shouldShowPriceInfo = orderPackage.packageRecuringPrice > 0 || orderPackage.packageServicePrice > 0; + const {orderPackage, currency, onViewChange} = this.props; + const shouldShowPriceInfo = orderPackage.recurringPrice > 0 || orderPackage.servicePrice > 0; return ( @@ -41,7 +41,7 @@ class PackageInfo extends Component { {orderTexts.labels.PACKAGE_PRICE}: {' '} { shouldShowPriceInfo && } @@ -49,43 +49,43 @@ class PackageInfo extends Component {
{orderTexts.labels.TOTAL_DELVIERY_PRICE}: {' '} - {(orderPackage.units * orderPackage.packageFixedPrice).toLocaleString() + ' ' + orderPackage.packageCurrency.currency} + {(orderPackage.quantity * orderPackage.price).toLocaleString() + ' ' + currency}
{ shouldShowPriceInfo &&
{orderTexts.labels.TOTAL_RECURRENT_PRICE}:{' '} - {(orderPackage.units * (orderPackage.packageRecuringPrice + orderPackage.packageServicePrice)).toLocaleString()} {orderPackage.packageCurrency.currency} + {(orderPackage.quantity * (orderPackage.recurringPrice + orderPackage.servicePrice)).toLocaleString()} {currency}
} { shouldShowPriceInfo && {orderPackage.paymentType}
- { orderPackage.packageRecuringPrice > 0 && + { orderPackage.recurringPrice > 0 &&
{orderTexts.labels.RECURRENT_PRICE}: - {(orderPackage.units * orderPackage.packageRecuringPrice).toLocaleString()} {orderPackage.packageCurrency.currency} / {orderPackage.periodUnit} + {(orderPackage.quantity * orderPackage.recurringPrice).toLocaleString()} {currency} / {orderPackage.periodUnit} { orderPackage.packagePayPeriod > 0 && - for {orderPackage.packagePayPeriod} {orderPackage.periodUnit} + for {orderPackage.payPeriod} {orderPackage.periodUnit} }
} - { orderPackage.packageServicePrice > 0 && + { orderPackage.servicePrice > 0 &&
{orderTexts.labels.SERVICES_PRICE}: - {(orderPackage.units * orderPackage.packageServicePrice).toLocaleString()} {orderPackage.packageCurrency.currency} / {orderPackage.periodUnit} + {(orderPackage.quantity * orderPackage.servicePrice).toLocaleString()} {currency} / {orderPackage.periodUnit} { orderPackage.servicesContractPeriod > 0 && @@ -101,7 +101,7 @@ class PackageInfo extends Component { } { - orderPackage.options.length > 0 && + orderPackage.options && orderPackage.options.length > 0 &&
{orderTexts.labels.OPTIONS}:
{ @@ -112,7 +112,7 @@ class PackageInfo extends Component { } { - orderPackage.additionalPackages.length > 0 && + orderPackage.additionalPackages && orderPackage.additionalPackages.length > 0 &&
{orderTexts.labels.ADDITIONAL_PACKAGES}:
{ diff --git a/frontend/src/containers/orders/components/packages/PackageName.jsx b/frontend/src/containers/orders/components/packages/PackageName.jsx index 79f8d28..3a665e0 100644 --- a/frontend/src/containers/orders/components/packages/PackageName.jsx +++ b/frontend/src/containers/orders/components/packages/PackageName.jsx @@ -7,7 +7,7 @@ class PackageName extends Component { return (
- {orderPackage.units + ' x ' + orderPackage.packageName} + {orderPackage.quantity + ' x ' + orderPackage.name}
); } diff --git a/frontend/src/containers/orders/components/packages/ProcessPackage.jsx b/frontend/src/containers/orders/components/packages/ProcessPackage.jsx index f1c9743..d08e742 100644 --- a/frontend/src/containers/orders/components/packages/ProcessPackage.jsx +++ b/frontend/src/containers/orders/components/packages/ProcessPackage.jsx @@ -6,13 +6,13 @@ import PackageName from './PackageName.jsx'; class ProcessPackage extends Component { render() { - const {orderPackage, idCommercialLead} = this.props; + const {orderPackage, currency, idCommercialLead} = this.props; return ( - + From 30faf9a9102d0fc8ed930cbb2c4fd10596bdc51a Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:29:01 +0200 Subject: [PATCH 15/63] use defined value from WP_HOME instead of hardcoded value --- .../includes/api/class-wiaas-rest-delivery-process-api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 26673ac..6893d45 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -2,7 +2,7 @@ class Wiass_REST_Delivery_Process_API { - private static $BASE_NAME = 'http://localhost/'; + private static $BASE_NAME = WP_HOME . "/"; private static $ACCEPTANCE_STATUS_FIELD_ID = 8; private static $EXPIRATION_DATE_FIELD_ID = 9; From 9134a44a711205a95b870e51eb0e0544d37bd3a2 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 16 Aug 2018 10:35:55 +0200 Subject: [PATCH 16/63] check comment owner by username --- frontend/src/actions/login/authActions.js | 1 + frontend/src/actions/orders/processActions.js | 3 +-- .../containers/orders/components/OrderComments.jsx | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/src/actions/login/authActions.js b/frontend/src/actions/login/authActions.js index b1b9881..55e2b4d 100644 --- a/frontend/src/actions/login/authActions.js +++ b/frontend/src/actions/login/authActions.js @@ -118,6 +118,7 @@ export const validateCredentials = (username, password) => { // if(decodedAceessToken.data.wiaas_user_type === 'customer'){ localStorage.setItem('accessToken', response.data.token); + localStorage.setItem('username', username); const serverTime = decodedAceessToken.nbf || 1; // refreshToken = response.data.refreshToken; startRefreshTimer(dispatch, serverTime); diff --git a/frontend/src/actions/orders/processActions.js b/frontend/src/actions/orders/processActions.js index 808c40c..e45d409 100644 --- a/frontend/src/actions/orders/processActions.js +++ b/frontend/src/actions/orders/processActions.js @@ -69,8 +69,7 @@ export const addComment = (idOrder, newComment, existingComments) => { const newCommentObject = { comment : newComment, date : moment().format("Do MMM, YY"), - username: 'username', - isOwner: 1, + username: localStorage.getItem('username') || '-', } const concatenatedComments = (existingComments) ? existingComments.concat(newCommentObject) : [newCommentObject]; diff --git a/frontend/src/containers/orders/components/OrderComments.jsx b/frontend/src/containers/orders/components/OrderComments.jsx index c30bcaa..9717e42 100644 --- a/frontend/src/containers/orders/components/OrderComments.jsx +++ b/frontend/src/containers/orders/components/OrderComments.jsx @@ -25,12 +25,12 @@ class OrderComments extends Component { this.setState({newComment}); } - getOffset(isOwner){ - return isOwner ? 6 : 0; + getOffset(username){ + return (username === localStorage.getItem('username')) ? 6 : 0; } - getClassByOwner(isOwner){ - return isOwner ? 'mine' : ''; + getClassByOwner(username){ + return (username === localStorage.getItem('username')) ? 'mine' : ''; } render() { @@ -46,8 +46,8 @@ class OrderComments extends Component { orderComments && orderComments.map((orderComment, index) => - -
+ +
{orderComment.username} - {orderComment.date}
From 5c91a57db8fb9d49fc58493dd2de2f0fddd29a7c Mon Sep 17 00:00:00 2001 From: GotPPay Date: Fri, 17 Aug 2018 21:03:49 +0200 Subject: [PATCH 17/63] remove customer acceptance expiration --- ...ivery_action_customer_acceptance_form.json | 1044 ++++++++--------- 1 file changed, 522 insertions(+), 522 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json index 0839e31..659e050 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json @@ -1,524 +1,524 @@ { - "0": { - "title": "DELIVERY ACTION TYPE: Customer acceptance", - "description": "The customer must accept the implementation before further actions can be taken. If the customer isn't satisfied, the problems or discrepancies must be fixed in order to gen an acceptance.", - "labelPlacement": "top_label", - "descriptionPlacement": "below", - "button": { - "type": "text", - "text": "Submit", - "imageUrl": "" - }, - "fields": [ - { - "type": "workflow_user", - "id": 2, - "label": "customer-id", - "adminLabel": "customer-id", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "administrative", - "inputs": null, - "choices": [ - ], - "formId": 1, - "description": "", - "allowsPrepopulate": true, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "customer-id", - "noDuplicates": false, - "defaultValue": "", - "conditionalLogic": "", - "failed_validation": "", - "productField": "", - "multipleFiles": false, - "maxFiles": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "", - "enablePrice": "", - "gravityflowUsersRoleFilter": "" - }, - { - "type": "date", - "id": 6, - "label": "Actual date", - "adminLabel": "", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "visible", - "inputs": null, - "dateType": "datepicker", - "calendarIconType": "none", - "formId": 1, - "description": "", - "allowsPrepopulate": false, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "", - "noDuplicates": false, - "defaultValue": "", - "choices": "", - "conditionalLogic": "", - "calendarIconUrl": "", - "dateFormat": "ymd_dash", - "productField": "", - "multipleFiles": false, - "maxFiles": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "" - }, - { - "type": "radio", - "id": 8, - "label": "acceptance", - "adminLabel": "", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "visible", - "inputs": null, - "choices": [ - { - "text": "not-accepted", - "value": "not-accepted", - "isSelected": true, - "price": "" - }, - { - "text": "accept", - "value": "accept", - "isSelected": false, - "price": "" - }, - { - "text": "decline", - "value": "decline", - "isSelected": false, - "price": "" - } - ], - "formId": 1, - "description": "", - "allowsPrepopulate": false, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "", - "noDuplicates": false, - "defaultValue": "", - "conditionalLogic": "", - "productField": "", - "enableOtherChoice": "", - "enablePrice": "", - "multipleFiles": false, - "maxFiles": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "" - }, - { - "type": "date", - "id": 9, - "label": "Expiration date", - "adminLabel": "", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "visible", - "inputs": null, - "dateType": "datepicker", - "calendarIconType": "none", - "formId": 1, - "description": "", - "allowsPrepopulate": false, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "", - "noDuplicates": false, - "defaultValue": "", - "choices": "", - "conditionalLogic": "", - "calendarIconUrl": "", - "dateFormat": "ymd_dash", - "productField": "", - "multipleFiles": false, - "maxFiles": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "" - }, - { - "type": "text", - "id": 10, - "label": "Reason", - "adminLabel": "", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "visible", - "inputs": null, - "formId": 1, - "description": "", - "allowsPrepopulate": false, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "", - "noDuplicates": false, - "defaultValue": "", - "choices": "", - "conditionalLogic": "", - "productField": "", - "enablePasswordInput": "", - "maxLength": "", - "multipleFiles": false, - "maxFiles": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false, - "displayOnly": "", - "enablePrice": "" - }, - { - "type": "fileupload", - "id": 12, - "label": "File", - "adminLabel": "", - "isRequired": false, - "size": "medium", - "errorMessage": "", - "visibility": "visible", - "inputs": null, - "formId": 1, - "description": "Upload customer acceptance file", - "allowsPrepopulate": false, - "inputMask": false, - "inputMaskValue": "", - "inputType": "", - "labelPlacement": "", - "descriptionPlacement": "", - "subLabelPlacement": "", - "placeholder": "", - "cssClass": "", - "inputName": "", - "noDuplicates": false, - "defaultValue": "", - "choices": "", - "conditionalLogic": "", - "maxFileSize": "", - "maxFiles": "", - "multipleFiles": true, - "allowedExtensions": "pdf,docx,doc,xlsx,xls,odt,ods,jpg,png,jpeg", - "productField": "", - "calculationFormula": "", - "calculationRounding": "", - "enableCalculation": "", - "disableQuantity": false, - "displayAllCategories": false, - "useRichTextEditor": false - } - ], - "version": "2.3.2", - "id": 1, - "useCurrentUserAsAuthor": true, - "postContentTemplateEnabled": false, - "postTitleTemplateEnabled": false, - "postTitleTemplate": "", - "postContentTemplate": "", - "lastPageButton": null, - "pagination": null, - "firstPageCssClass": null, - "is_active": "1", - "date_created": "2018-08-09 16:03:22", - "is_trash": "0", - "notifications": [ - { - "id": "5b5f75f748cee", - "to": "{admin_email}", - "name": "Admin Notification", - "event": "form_submission", - "toType": "email", - "subject": "New submission from {form_title}", - "message": "{all_fields}" - } - ], - "confirmations": [ - { - "id": "5b5f75f7494b7", - "name": "Default Confirmation", - "isDefault": true, - "type": "message", - "message": "Thanks for contacting us! We will get in touch with you shortly.", - "url": "", - "pageId": "", - "queryString": "" - } - ], - "feeds": { - "gravityflow": [ - { - "id": "1", - "form_id": "1", - "is_active": "1", - "feed_order": "0", - "meta": { - "step_name": "Upload acceptance file", - "description": "", - "step_type": "user_input", - "step_highlight": "0", - "step_highlight_type": "color", - "step_highlight_color": "#dd3333", - "feed_condition_conditional_logic": "0", - "feed_condition_conditional_logic_object": [], - "scheduled": "0", - "schedule_type": "delay", - "schedule_date": "", - "schedule_delay_offset": "", - "schedule_delay_unit": "hours", - "schedule_date_field_offset": "0", - "schedule_date_field_offset_unit": "hours", - "schedule_date_field_before_after": "after", - "schedule_date_field": "6", - "type": "select", - "assignees": [ - "role|administrator", - "assignee_user_field|2" - ], - "routing": "", - "assignee_policy": "any", - "highlight_editable_fields_enabled": "0", - "highlight_editable_fields_class": "green-triangle", - "instructionsEnable": "0", - "instructionsValue": "", - "display_fields_mode": "selected_fields", - "default_status": "hidden", - "note_mode": "not_required", - "assignee_notification_enabled": "0", - "assignee_notification_from_name": "", - "assignee_notification_from_email": "{admin_email}", - "assignee_notification_reply_to": "", - "assignee_notification_bcc": "", - "assignee_notification_subject": "Upload order acceptance file", - "assignee_notification_message": "A new entry requires your input.", - "assignee_notification_disable_autoformat": "0", - "resend_assignee_emailEnable": "0", - "resend_assignee_emailValue": "7", - "resend_assignee_email_repeatEnable": "0", - "resend_assignee_email_repeatValue": "3", - "in_progress_notification_enabled": "0", - "in_progress_notification_type": "select", - "in_progress_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "in_progress_notification_from_name": "", - "in_progress_notification_from_email": "{admin_email}", - "in_progress_notification_reply_to": "", - "in_progress_notification_bcc": "", - "in_progress_notification_subject": "", - "in_progress_notification_message": "Entry {entry_id} has been updated and remains in progress.", - "in_progress_notification_disable_autoformat": "0", - "complete_notification_enabled": "0", - "complete_notification_type": "select", - "complete_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "complete_notification_from_name": "", - "complete_notification_from_email": "{admin_email}", - "complete_notification_reply_to": "", - "complete_notification_bcc": "", - "complete_notification_subject": "", - "complete_notification_message": "Entry {entry_id} has been updated completing the step.", - "complete_notification_disable_autoformat": "0", - "confirmation_messageEnable": "0", - "confirmation_messageValue": "Thank you.", - "expiration": "1", - "expiration_type": "date_field", - "expiration_date": "", - "expiration_delay_offset": "7", - "expiration_delay_unit": "days", - "expiration_date_field_offset": "0", - "expiration_date_field_offset_unit": "hours", - "expiration_date_field_before_after": "after", - "expiration_date_field": "9", - "status_expiration": "expired", - "destination_expired": "2", - "destination_complete": "next" - }, - "addon_slug": "gravityflow", - "event_type": null - }, - { - "id": "2", - "form_id": "1", - "is_active": "1", - "feed_order": "0", - "meta": { - "step_name": "Approve customer acceptance", - "description": "", - "step_type": "approval", - "step_highlight": "0", - "step_highlight_type": "color", - "step_highlight_color": "#dd3333", - "feed_condition_conditional_logic": "0", - "feed_condition_conditional_logic_object": [], - "scheduled": "0", - "schedule_type": "delay", - "schedule_date": "", - "schedule_delay_offset": "", - "schedule_delay_unit": "hours", - "schedule_date_field_offset": "0", - "schedule_date_field_offset_unit": "hours", - "schedule_date_field_before_after": "after", - "type": "select", - "assignees": [ - "role|administrator" - ], - "routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "assignee_policy": "any", - "instructionsEnable": "0", - "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", - "display_fields_mode": "all_fields", - "assignee_notification_enabled": "0", - "assignee_notification_from_name": "", - "assignee_notification_from_email": "{admin_email}", - "assignee_notification_reply_to": "", - "assignee_notification_bcc": "", - "assignee_notification_subject": "", - "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", - "assignee_notification_disable_autoformat": "0", - "resend_assignee_emailEnable": "0", - "resend_assignee_emailValue": "7", - "resend_assignee_email_repeatEnable": "0", - "resend_assignee_email_repeatValue": "3", - "rejection_notification_enabled": "0", - "rejection_notification_type": "select", - "rejection_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "rejection_notification_from_name": "", - "rejection_notification_from_email": "{admin_email}", - "rejection_notification_reply_to": "", - "rejection_notification_bcc": "", - "rejection_notification_subject": "", - "rejection_notification_message": "Entry {entry_id} has been rejected", - "rejection_notification_disable_autoformat": "0", - "approval_notification_enabled": "0", - "approval_notification_type": "select", - "approval_notification_routing": [ - { - "assignee": "user_id|2", - "fieldId": "0", - "operator": "is", - "value": "", - "type": "" - } - ], - "approval_notification_from_name": "", - "approval_notification_from_email": "{admin_email}", - "approval_notification_reply_to": "", - "approval_notification_bcc": "", - "approval_notification_subject": "", - "approval_notification_message": "Entry {entry_id} has been approved", - "approval_notification_disable_autoformat": "0", - "revertEnable": "0", - "revertValue": 1, - "note_mode": "not_required", - "expiration": "0", - "expiration_type": "delay", - "expiration_date": "", - "expiration_delay_offset": "", - "expiration_delay_unit": "hours", - "expiration_date_field_offset": "0", - "expiration_date_field_offset_unit": "hours", - "expiration_date_field_before_after": "after", - "status_expiration": "rejected", - "destination_expired": "next", - "destination_rejected": 1, - "destination_approved": "next" - }, - "addon_slug": "gravityflow", - "event_type": null - } - ] - } - }, - "version": "2.3.2" + "0": { + "title": "DELIVERY ACTION TYPE: Customer acceptance", + "description": "The customer must accept the implementation before further actions can be taken. If the customer isn't satisfied, the problems or discrepancies must be fixed in order to gen an acceptance.", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "" + }, + "fields": [ + { + "type": "workflow_user", + "id": 2, + "label": "customer-id", + "adminLabel": "customer-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "administrative", + "inputs": null, + "choices": [ + ], + "formId": 1, + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "customer-id", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "failed_validation": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "", + "gravityflowUsersRoleFilter": "" + }, + { + "type": "date", + "id": 6, + "label": "Actual date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "none", + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + }, + { + "type": "radio", + "id": 8, + "label": "acceptance", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "choices": [ + { + "text": "not-accepted", + "value": "not-accepted", + "isSelected": true, + "price": "" + }, + { + "text": "accept", + "value": "accept", + "isSelected": false, + "price": "" + }, + { + "text": "decline", + "value": "decline", + "isSelected": false, + "price": "" + } + ], + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "productField": "", + "enableOtherChoice": "", + "enablePrice": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + }, + { + "type": "date", + "id": 9, + "label": "Expiration date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "none", + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + }, + { + "type": "text", + "id": 10, + "label": "Reason", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "formId": 1, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "" + }, + { + "type": "fileupload", + "id": 12, + "label": "File", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "formId": 1, + "description": "Upload customer acceptance file", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "maxFileSize": "", + "maxFiles": "", + "multipleFiles": true, + "allowedExtensions": "pdf,docx,doc,xlsx,xls,odt,ods,jpg,png,jpeg", + "productField": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false + } + ], + "version": "2.3.2", + "id": 1, + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "is_active": "1", + "date_created": "2018-08-15 20:30:18", + "is_trash": "0", + "confirmations": [ + { + "id": "5b5f75f7494b7", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "notifications": [ + { + "id": "5b5f75f748cee", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], + "feeds": { + "gravityflow": [ + { + "id": "1", + "form_id": "1", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Upload acceptance file", + "description": "", + "step_type": "user_input", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "schedule_date_field": "6", + "type": "select", + "assignees": [ + "role|administrator", + "assignee_user_field|2" + ], + "routing": "", + "assignee_policy": "any", + "highlight_editable_fields_enabled": "0", + "highlight_editable_fields_class": "green-triangle", + "instructionsEnable": "0", + "instructionsValue": "", + "display_fields_mode": "selected_fields", + "default_status": "hidden", + "note_mode": "not_required", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "Upload order acceptance file", + "assignee_notification_message": "A new entry requires your input.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "in_progress_notification_enabled": "0", + "in_progress_notification_type": "select", + "in_progress_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "in_progress_notification_from_name": "", + "in_progress_notification_from_email": "{admin_email}", + "in_progress_notification_reply_to": "", + "in_progress_notification_bcc": "", + "in_progress_notification_subject": "", + "in_progress_notification_message": "Entry {entry_id} has been updated and remains in progress.", + "in_progress_notification_disable_autoformat": "0", + "complete_notification_enabled": "0", + "complete_notification_type": "select", + "complete_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "complete_notification_from_name": "", + "complete_notification_from_email": "{admin_email}", + "complete_notification_reply_to": "", + "complete_notification_bcc": "", + "complete_notification_subject": "", + "complete_notification_message": "Entry {entry_id} has been updated completing the step.", + "complete_notification_disable_autoformat": "0", + "confirmation_messageEnable": "0", + "confirmation_messageValue": "Thank you.", + "expiration": "0", + "expiration_type": "date_field", + "expiration_date": "", + "expiration_delay_offset": "7", + "expiration_delay_unit": "days", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "expiration_date_field": "9", + "status_expiration": "expired", + "destination_expired": "2", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "2", + "form_id": "1", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Approve customer acceptance", + "description": "", + "step_type": "approval", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "type": "select", + "assignees": [ + "role|administrator" + ], + "routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "assignee_policy": "any", + "instructionsEnable": "0", + "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", + "display_fields_mode": "all_fields", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "", + "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "rejection_notification_enabled": "0", + "rejection_notification_type": "select", + "rejection_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "rejection_notification_from_name": "", + "rejection_notification_from_email": "{admin_email}", + "rejection_notification_reply_to": "", + "rejection_notification_bcc": "", + "rejection_notification_subject": "", + "rejection_notification_message": "Entry {entry_id} has been rejected", + "rejection_notification_disable_autoformat": "0", + "approval_notification_enabled": "0", + "approval_notification_type": "select", + "approval_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "approval_notification_from_name": "", + "approval_notification_from_email": "{admin_email}", + "approval_notification_reply_to": "", + "approval_notification_bcc": "", + "approval_notification_subject": "", + "approval_notification_message": "Entry {entry_id} has been approved", + "approval_notification_disable_autoformat": "0", + "revertEnable": "0", + "revertValue": 1, + "note_mode": "not_required", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "", + "expiration_delay_unit": "hours", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "status_expiration": "rejected", + "destination_expired": "next", + "destination_rejected": 1, + "destination_approved": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + } + ] + } + }, + "version": "2.3.2" } \ No newline at end of file From 46e51111d2488c28668e95e454d2c8c03c119301 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 16:20:05 +0200 Subject: [PATCH 18/63] allow api access only to logged in users --- .../class-wiaas-rest-delivery-process-api.php | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 6893d45..f99e7d9 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -32,22 +32,23 @@ class Wiass_REST_Delivery_Process_API { Used for some fast test and check - register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( - 'methods' => 'GET', - 'callback' => array(__CLASS__, 'get_form_entry'), - ) ); - register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)/field/(?P\d+(.\d+)?)', array( 'methods' => 'GET', 'callback' => array(__CLASS__, 'get_field_value_from_entry'), ) ); + */ + + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'get_form_entry'), + ) ); + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( 'methods' => 'PUT', 'callback' => array(__CLASS__, 'update_entry'), ) ); - */ register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'POST', @@ -108,7 +109,9 @@ class Wiass_REST_Delivery_Process_API { } public static function get_customer_acceptance($data){ - //TODO: check for permissions + if (!is_user_logged_in()){ + return self::generate_error("You don't have permission to read this entry", 401); + } $entry = GFAPI::get_entry($data['entry_id']); if (!$entry){ @@ -144,8 +147,14 @@ class Wiass_REST_Delivery_Process_API { } public static function update_customer_acceptance($data){ - //TODO : check for permissions + if (!is_user_logged_in()){ + return self::generate_error("You don't have permission to read this entry", 401); + } + $entry = GFAPI::get_entry($data['entry_id']); + if (!$entry){ + return self::generate_error('Customer acceptance entry not found', 404); + } $entry[self::$DECLINE_REASON_FIELD_ID] = $_POST['declineReason']; $entry[self::$ACCEPTANCE_STATUS_FIELD_ID] = $_POST['actionType']; @@ -155,7 +164,9 @@ class Wiass_REST_Delivery_Process_API { } public static function upload_file($data){ - //TODO : Check permissions + if (!is_user_logged_in()){ + return self::generate_error("You don't have permission to read this entry", 401); + } $input_name = "file"; if (!$_FILES[$input_name]){ @@ -227,10 +238,7 @@ class Wiass_REST_Delivery_Process_API { //Used for testing and checking /* - public static function get_form_entry($data) { - //TODO: check for permissions - return GFAPI::get_entry($data['entry_id']); - } + public static function get_field_value_from_entry($data){ //TODO : check for permissions @@ -239,8 +247,16 @@ class Wiass_REST_Delivery_Process_API { return new WP_REST_Response ($result); } + */ + + //TODO: Remove this function + public static function get_form_entry($data) { + return GFAPI::get_entry($data['entry_id']); + } + + + //TODO: Remove this function public static function update_entry($data){ - //TODO : check for permissions $entry = GFAPI::get_entry($data['entry_id']); $new_values = json_decode($data->get_body()); if ($new_values === NULL) { @@ -254,7 +270,7 @@ class Wiass_REST_Delivery_Process_API { return new WP_REST_Response ($result); } - */ + //Helper function From 0a5d69f6f2c22b76400619b64c77702535a966aa Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 22:05:04 +0200 Subject: [PATCH 19/63] use constants; send message objects instead of strings --- .../class-wiaas-rest-delivery-process-api.php | 112 ++++++++++++------ 1 file changed, 78 insertions(+), 34 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index f99e7d9..514d144 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -2,12 +2,17 @@ class Wiass_REST_Delivery_Process_API { - private static $BASE_NAME = WP_HOME . "/"; + const BASE_NAME = WP_HOME . '/'; - private static $ACCEPTANCE_STATUS_FIELD_ID = 8; - private static $EXPIRATION_DATE_FIELD_ID = 9; - private static $DECLINE_REASON_FIELD_ID = 10; - private static $UPLOADED_FILES_FIELD_ID = 12; + const ACCEPTANCE_STATUS_FIELD_ID = 8; + const EXPIRATION_DATE_FIELD_ID = 9; + const DECLINE_REASON_FIELD_ID = 10; + const UPLOADED_FILES_FIELD_ID = 12; + + const ACCEPT_STATUS_LABEL = 'accept'; + const DECLINE_STATUS_LABEL = 'decline'; + + const ACCEPTABLE_STATUS = [self::ACCEPT_STATUS_LABEL, self::DECLINE_STATUS_LABEL]; /** * Endpoint namespace. @@ -110,7 +115,7 @@ class Wiass_REST_Delivery_Process_API { public static function get_customer_acceptance($data){ if (!is_user_logged_in()){ - return self::generate_error("You don't have permission to read this entry", 401); + return self::generate_error('You don\'t have permission to read this entry', 401); } $entry = GFAPI::get_entry($data['entry_id']); @@ -119,7 +124,7 @@ class Wiass_REST_Delivery_Process_API { } $acceptance_documents = array(); - $uploaded_files = json_decode($entry[self::$UPLOADED_FILES_FIELD_ID]); + $uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]); foreach($uploaded_files as $file_url){ $info = pathinfo($file_url); @@ -132,15 +137,15 @@ class Wiass_REST_Delivery_Process_API { } $acceptance_status = 0; - if ($entry[self::$ACCEPTANCE_STATUS_FIELD_ID]){ - $acceptance_status = ($entry[self::$ACCEPTANCE_STATUS_FIELD_ID] === 'accept') ? 1 : -1; + if ($entry[self::ACCEPTANCE_STATUS_FIELD_ID]){ + $acceptance_status = ($entry[self::ACCEPTANCE_STATUS_FIELD_ID] === 'accept') ? 1 : -1; } $result = array( 'documents' => $acceptance_documents, - 'expiration' => $entry[self::$EXPIRATION_DATE_FIELD_ID], + 'expiration' => $entry[self::EXPIRATION_DATE_FIELD_ID], 'status' => $acceptance_status, - 'decline_reason' => $entry[self::$DECLINE_REASON_FIELD_ID] + 'decline_reason' => $entry[self::DECLINE_REASON_FIELD_ID] ); return new WP_REST_Response($result); @@ -148,54 +153,79 @@ class Wiass_REST_Delivery_Process_API { public static function update_customer_acceptance($data){ if (!is_user_logged_in()){ - return self::generate_error("You don't have permission to read this entry", 401); + return self::generate_error('You don\'t have permission to read this entry', 401); } $entry = GFAPI::get_entry($data['entry_id']); if (!$entry){ - return self::generate_error('Customer acceptance entry not found', 404); + return self::generate_wiaas_response('INTERNAL_SERVER_ERROR', 'error'); } - $entry[self::$DECLINE_REASON_FIELD_ID] = $_POST['declineReason']; - $entry[self::$ACCEPTANCE_STATUS_FIELD_ID] = $_POST['actionType']; + $status = $_POST['actionType']; + $reason = $_POST['declineReason']; + $installation_declined = ($status === self::DECLINE_STATUS_LABEL); + + if (!in_array($status, self::ACCEPTABLE_STATUS)){ + return self::generate_wiaas_response('ACCEPTANCE_STATUS_MISSING', 'error'); + } + + if ($installation_declined && $reason === ''){ + return self::generate_wiaas_response('DECLINE_REASON_EMPTY', 'error'); + } + + $entry[self::DECLINE_REASON_FIELD_ID] = $reason; + $entry[self::ACCEPTANCE_STATUS_FIELD_ID] = $status; + + //submit step + $entry['workflow_step'] = 2; + $entry['workflow_step_status_1'] = 'complete'; + $entry['workflow_step_status_2'] = 'pending'; + $entry['workflow_timestamp'] = time(); - $result = GFAPI::update_entry( $entry ); - return new WP_REST_Response ($result); + if (GFAPI::update_entry( $entry )){ + if ($installation_declined){ + return self::generate_wiaas_response('INSTALLATION_DECLINED', 'success'); + }else{ + return self::generate_wiaas_response('INSTALLATION_ACCEPTED', 'success'); + } + }else{ + return self::generate_wiaas_response('INTERNAL_SERVER_ERROR', 'error'); + } } public static function upload_file($data){ if (!is_user_logged_in()){ - return self::generate_error("You don't have permission to read this entry", 401); + return self::generate_error('You don\'t have permission to read this entry', 401); } - $input_name = "file"; + $input_name = 'file'; if (!$_FILES[$input_name]){ - return self::generate_error("No file", 400); + return self::generate_wiaas_response('NO_FILES_UPLOADED', 'error'); } $entry = GFAPI::get_entry($data['entry_id']); if (!$entry['form_id']){ - return self::generate_error("Entry not found", 404); + return self::generate_wiaas_response('NOT_UPLOADED', 'error'); } $form = GFAPI::get_form($entry['form_id']); $form_upload_path = GFFormsModel::get_upload_path( $form['id'] ); - $target_path = $form_upload_path . '/' . date("Y") . '/' . date("m") . '/'; + $target_path = $form_upload_path . '/' . date('Y') . '/' . date('m') . '/'; wp_mkdir_p( $target_path ); GFCommon::recursive_add_index_file( $target_path ); - $upload_file_field = GFAPI::get_field($form['id'], self::$UPLOADED_FILES_FIELD_ID); + $upload_file_field = GFAPI::get_field($form['id'], self::UPLOADED_FILES_FIELD_ID); $file_name = $_FILES[$input_name]['name']; $file_path_details = pathinfo($file_name); if ( GFCommon::file_name_has_disallowed_extension( $file_name ) ) { - return self::generate_error("File extension is not allowed", 400); + return self::generate_wiaas_response('INVALID_FILE_ACCEPTANCE', 'error'); } $allowed_extensions = ! empty( $upload_file_field->allowedExtensions ) ? GFCommon::clean_extensions( explode( ',', strtolower( $upload_file_field->allowedExtensions ) ) ) : array(); if ( ! empty( $allowed_extensions ) ) { if ( ! GFCommon::match_file_extension( $file_name, $allowed_extensions ) ) { - return self::generate_error("File extension is not allowed", 400); + return self::generate_wiaas_response('INVALID_FILE_ACCEPTANCE', 'error'); } } @@ -204,36 +234,36 @@ class Wiass_REST_Delivery_Process_API { if ( move_uploaded_file( $_FILES[$input_name]['tmp_name'], $target_path . $new_file_name ) ) { GFFormsModel::set_permissions( $target_path . $new_file_name ); } else { - return self::generate_error("Internal server error"); + return self::generate_wiaas_response('INTERNAL_SERVER_ERROR', 'error'); } //Extract path relative to the root //Last 6 strings (excluding last empty) are path relative to the root - $path_parts = explode("/", $target_path); + $path_parts = explode('/', $target_path); - $relative_path = ""; + $relative_path = ''; $i = count($path_parts) - 7; while($i < count($path_parts)-1){ - $relative_path = $relative_path . $path_parts[$i] . "/"; + $relative_path = $relative_path . $path_parts[$i] . '/'; $i++; } - $file_url = self::$BASE_NAME . $relative_path . $new_file_name; + $file_url = self::BASE_NAME . $relative_path . $new_file_name; - $uploaded_files = json_decode($entry[self::$UPLOADED_FILES_FIELD_ID]); + $uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]); if ($uploaded_files === NULL){ $uploaded_files = []; } array_push($uploaded_files, $file_url); - $entry[self::$UPLOADED_FILES_FIELD_ID] = json_encode($uploaded_files); + $entry[self::UPLOADED_FILES_FIELD_ID] = json_encode($uploaded_files); if (GFAPI::update_entry( $entry )) { - return new WP_REST_Response($uploaded_files); + return self::generate_wiaas_response('FILE_UPLOADED','success'); } - return self::generate_error('Error updating entry'); + return self::generate_wiaas_response('NOT_UPLOADED', 'error'); } //Used for testing and checking @@ -285,5 +315,19 @@ class Wiass_REST_Delivery_Process_API { return $result; } + private static function generate_wiaas_response($message, $code, $data = NULL){ + $response = array( + 'messages' => [ + array( + 'code' => $code, + 'message' => $message + ) + ], + 'data' => $data + ); + + return new WP_REST_Response($response); + } + } \ No newline at end of file From 936193ba0ccdab16ddc166bd7d035427b2dc99f4 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 22:05:31 +0200 Subject: [PATCH 20/63] display returned message --- frontend/src/actions/orders/customerAcceptanceActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/actions/orders/customerAcceptanceActions.js b/frontend/src/actions/orders/customerAcceptanceActions.js index 9f1365f..642a22d 100644 --- a/frontend/src/actions/orders/customerAcceptanceActions.js +++ b/frontend/src/actions/orders/customerAcceptanceActions.js @@ -52,7 +52,7 @@ export const uploadAcceptance = (idEntry, file) => { url: `${API_SERVER}/wp-json/wiaas/customer-acceptance/${idEntry}/upload-file` }).then(response => { if (typeof response.data !== 'undefined') { - //dispatch(updateMessages(response.data.messages, orderMessages)); + dispatch(updateMessages(response.data.messages, orderMessages)); dispatch(fetchCustomerAcceptance(idEntry)); } }).catch(error => { From c459382d749e4fded034b4773625555e6d315959 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 22:05:43 +0200 Subject: [PATCH 21/63] add new constants --- frontend/src/constants/ordersConstants.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/src/constants/ordersConstants.js b/frontend/src/constants/ordersConstants.js index fb282fc..76c8c2c 100644 --- a/frontend/src/constants/ordersConstants.js +++ b/frontend/src/constants/ordersConstants.js @@ -50,13 +50,13 @@ export const orderMessages = { SYSTEM_ALLOWED_LANGUAGES_EMPTY: 'There are no languages added in the system.', ALLOWED_LANGUAGE: 'Allowed languages are:', ALLOWED_LANGUAGE_ERROR: 'There was an error while trying to detect the language:', - SERVER_ERROR: 'There seems to be a problem and the comment was not added!', + ERROR_ADDING_COMMENT: 'There seems to be a problem and the comment was not added!', ORDER_COMMENT_ADDED: 'Order comment updated!', FILE_UPLOADED : 'File has been uploaded and needs to be validated!', NOT_UPLOADED : 'There seems to be a problem and the file was not uploaded!', RE_UPLOAD_MAIL : 'Notify mail has been sent!', ACCEPTANCE_NOT_UPDATED : 'Acceptance status not updated!', - ACCEPTANCE_NOT_UPLOADED: 'You need to uploade the acceptance document before you can agree with the installation!', + ACCEPTANCE_NOT_UPLOADED: 'You need to upload the acceptance document before you can agree with the installation!', DECLINE_REASON_EMPTY : 'Please describe what is not to your satisfaction.', INSTALLATION_DECLINED : 'The implementation is not satisfactory.', ERROR_MAIL_SENT : 'Notify mail was not sent!', @@ -81,7 +81,12 @@ export const orderMessages = { EMPTY_VALUE: 'Field required: ', INSTALLATION_ACCEPTED: 'The implementation has been accepted!', ID_ORDER_NOT_SET: 'The id of the order is not set', - SUPPORT_MAIL_SENT: 'Support mail sent!' + SUPPORT_MAIL_SENT: 'Support mail sent!', + + NO_FILES_UPLOADED: 'You need to upload the acceptance document', + INTERNAL_SERVER_ERROR: 'Error occured. Please try again', + ACCEPTANCE_STATUS_MISSING: 'Acceptance action not selected' + }; export const orderTexts = { From 62c14fe1dc95721615c3649a80aa52864887db8f Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 22:05:57 +0200 Subject: [PATCH 22/63] remove unused constant --- .../containers/orders/components/process/CustomerAcceptance.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx index 567ca40..2104725 100644 --- a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx +++ b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx @@ -5,7 +5,6 @@ import {Row, Col, Button} from 'reactstrap'; import {fetchCustomerAcceptance, uploadAcceptance, acceptDeclineInstallation, badFile} from '../../../../actions/orders/customerAcceptanceActions'; import {setDialogContent, setDialogOpenFlag} from '../../../../actions/dialog/dialogActions'; import AcceptanceDeclineReason from './AcceptanceDeclineReason.jsx'; -import {API_SERVER} from '../../../../config'; import FileDownloader from '../../../../helpers/FileDownloader'; import {orderTexts} from '../../../../constants/ordersConstants'; import '../../style/CustomerAcceptance.css'; From b54512b1876e472f5b422942a33df052d50ae3cb Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 22:06:18 +0200 Subject: [PATCH 23/63] comment unused code for now --- frontend/src/helpers/HtmlClient.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/helpers/HtmlClient.js b/frontend/src/helpers/HtmlClient.js index 33a6a18..0f92822 100644 --- a/frontend/src/helpers/HtmlClient.js +++ b/frontend/src/helpers/HtmlClient.js @@ -45,13 +45,14 @@ class HtmlClient { uploadFile(file, configParams = null) { let formData = new FormData(); formData.append('file', file, file.name); + /* if(configParams) { - /* + Object.keys(configParams.data).forEach((paramKey) => { formData.append(paramKey, configParams.data[paramKey]); }); - */ - } + + }*/ configParams.data = formData; const params = Object.assign({}, uploadParams(), configParams); From 75416137565fff1e12dc13546ad9edddfc91d0bc Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 22:11:23 +0200 Subject: [PATCH 24/63] rename function --- .../includes/api/class-wiaas-rest-delivery-process-api.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 514d144..f33dd17 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -57,7 +57,7 @@ class Wiass_REST_Delivery_Process_API { register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'POST', - 'callback' => array(__CLASS__, 'update_customer_acceptance'), + 'callback' => array(__CLASS__, 'submit_customer_acceptance'), ) ); register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)/upload-file' , array( @@ -151,7 +151,7 @@ class Wiass_REST_Delivery_Process_API { return new WP_REST_Response($result); } - public static function update_customer_acceptance($data){ + public static function submit_customer_acceptance($data){ if (!is_user_logged_in()){ return self::generate_error('You don\'t have permission to read this entry', 401); } @@ -300,9 +300,6 @@ class Wiass_REST_Delivery_Process_API { return new WP_REST_Response ($result); } - - - //Helper function private static function generate_error($message, $code = 500){ $error = array( From af482104a05c559f491b58a933646195fe08a261 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 20 Aug 2018 01:29:51 +0200 Subject: [PATCH 25/63] fix bug with non existing entry --- .../api/class-wiaas-rest-delivery-process-api.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index f33dd17..9cd5c42 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -119,7 +119,7 @@ class Wiass_REST_Delivery_Process_API { } $entry = GFAPI::get_entry($data['entry_id']); - if (!$entry){ + if (is_wp_error($entry)){ return self::generate_error('Customer acceptance entry not found', 404); } @@ -153,12 +153,12 @@ class Wiass_REST_Delivery_Process_API { public static function submit_customer_acceptance($data){ if (!is_user_logged_in()){ - return self::generate_error('You don\'t have permission to read this entry', 401); + return self::generate_error('You don\'t have permission to update this entry', 401); } $entry = GFAPI::get_entry($data['entry_id']); - if (!$entry){ - return self::generate_wiaas_response('INTERNAL_SERVER_ERROR', 'error'); + if (is_wp_error($entry)){ + return self::generate_error('Customer acceptance entry not found', 404); } $status = $_POST['actionType']; From 902df8760b016f27bcd0ee3e869d64e088804c27 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 20 Aug 2018 12:52:49 +0200 Subject: [PATCH 26/63] install guzzle --- backend/composer.json | 3 +- backend/composer.lock | 233 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 234 insertions(+), 2 deletions(-) diff --git a/backend/composer.json b/backend/composer.json index 1fe0274..e3820f0 100644 --- a/backend/composer.json +++ b/backend/composer.json @@ -67,7 +67,8 @@ "3rdparty/woocommerce-product-bundles": "*" }, "require-dev": { - "vlucas/phpdotenv": "2.5.0" + "vlucas/phpdotenv": "2.5.0", + "guzzlehttp/guzzle": "6.3.3" }, "extra": { "installer-paths": { diff --git a/backend/composer.lock b/backend/composer.lock index b59d0b9..f58dd1a 100644 --- a/backend/composer.lock +++ b/backend/composer.lock @@ -1,7 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "content-hash": "302f569929ecdaf4d349b0bf764de74c", @@ -630,6 +630,237 @@ } ], "packages-dev": [ + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20T17:10:46+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, { "name": "vlucas/phpdotenv", "version": "v2.5.0", From b49c1cb82d0ce5e146ed7efd2b36db707ce29e96 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 20 Aug 2018 12:53:09 +0200 Subject: [PATCH 27/63] remove unused function --- .../class-wiaas-rest-delivery-process-api.php | 29 ++----------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 9cd5c42..76cb9d9 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -33,22 +33,12 @@ class Wiass_REST_Delivery_Process_API { 'callback' => array(__CLASS__, 'get_customer_acceptance'), ) ); - /* - - Used for some fast test and check - - register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)/field/(?P\d+(.\d+)?)', array( - 'methods' => 'GET', - 'callback' => array(__CLASS__, 'get_field_value_from_entry'), - ) ); - - */ - register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( 'methods' => 'GET', 'callback' => array(__CLASS__, 'get_form_entry'), ) ); + //Used for testing register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( 'methods' => 'PUT', 'callback' => array(__CLASS__, 'update_entry'), @@ -266,26 +256,13 @@ class Wiass_REST_Delivery_Process_API { return self::generate_wiaas_response('NOT_UPLOADED', 'error'); } - //Used for testing and checking - /* - - - public static function get_field_value_from_entry($data){ - //TODO : check for permissions - $entry = GFAPI::get_entry($data['entry_id']); - $result = $entry[$data['field_id']] ?: ''; - return new WP_REST_Response ($result); - } - - */ - - //TODO: Remove this function + //Used for testing public static function get_form_entry($data) { return GFAPI::get_entry($data['entry_id']); } - //TODO: Remove this function + //Used for testing public static function update_entry($data){ $entry = GFAPI::get_entry($data['entry_id']); $new_values = json_decode($data->get_body()); From 864134e67a72ee6f12bdf857b02e20899a6c66e3 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 20 Aug 2018 12:54:15 +0200 Subject: [PATCH 28/63] add tests for getting cust acceptance, submit cust acceptance --- .../test-wiaas-rest-delivery-process-api.php | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php index 726e865..f29f243 100644 --- a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php @@ -49,4 +49,190 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { $this->assertEquals($pending_step['status'], 'pending'); $this->assertNotEmpty($pending_step['step_action']); } + + /** + * @covers Wiass_REST_Delivery_Process_API::get_customer_acceptance + */ + function test_get_customer_acceptance_as_guest() { + wp_set_current_user(0); + $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance(NULL); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + + $this->assertTrue($response->is_error()); + $this->assertEquals($response->get_status(), 401); + + $error_data = $response->as_error(); + + $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to read this entry'); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::get_customer_acceptance + */ + function test_get_nonexisting_customer_acceptance() { + wp_set_current_user(1); + + $data['entry_id'] = 101; + + $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance($data); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + + $this->assertTrue($response->is_error()); + $this->assertEquals($response->get_status(), 404); + + $error_data = $response->as_error(); + + $this->assertEquals($error_data->get_error_message(), 'Customer acceptance entry not found'); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::get_customer_acceptance + */ + function test_get_valid_customer_acceptance() { + wp_set_current_user(1); + + // create customer acceptance entry + $customer_acceptance_form_id = 1; + + $customer_id_field_id = 2; + $actual_date_field_id = 6; + $acceptance_status_field_id = 8; + $expiration_date_field_id = 9; + $decline_reason_field_id = 10; + $files_uploaded_field_id = 12; + + $input_values['input_' . $acceptance_status_field_id] = 'accept'; + $input_values['input_' . $expiration_date_field_id] = "2020-01-01"; + //$input_values['input_' . $files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); + + GFAPI::submit_form($customer_acceptance_form_id, $input_values); + + //this part is needed since form submit does not store files for some reason, probably files should be sent some other way + $entry = GFAPI::get_entries($customer_acceptance_form_id)[0]; + $data['entry_id'] = $entry['id']; + $entry[$files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); + $update = GFAPI::update_entry($entry); + $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance($data); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + + $response_data = $response->get_data(); + + $this->assertTrue(is_array($response_data)); + $this->assertArrayHasKey('documents', $response_data); + $this->assertArrayHasKey('expiration', $response_data); + $this->assertArrayHasKey('status', $response_data); + $this->assertArrayHasKey('decline_reason', $response_data); + + $this->assertTrue(is_array($response_data['documents'])); + + $uploaded_file = $response_data['documents'][0]; + + $this->assertTrue(is_array($uploaded_file)); + $this->assertArrayHasKey('name', $uploaded_file); + $this->assertArrayHasKey('extension', $uploaded_file); + $this->assertArrayHasKey('url', $uploaded_file); + $this->assertEquals($uploaded_file['name'], 'file1'); + $this->assertEquals($uploaded_file['extension'], 'docx'); + $this->assertEquals($uploaded_file['url'], 'http://path/to/file1.docx'); + + $this->assertEquals($response_data['status'], 1); //1 means accept + + $this->assertEquals($response_data['expiration'], "2020-01-01"); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::submit_customer_acceptance + */ + function test_submit_customer_acceptance_as_guest() { + wp_set_current_user(0); + + $response = Wiass_REST_Delivery_Process_API::submit_customer_acceptance(NULL); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + + $this->assertTrue($response->is_error()); + $this->assertEquals($response->get_status(), 401); + + $error_data = $response->as_error(); + + $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to update this entry'); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::submit_customer_acceptance + */ + function test_submit_nonexisting_customer_acceptance() { + wp_set_current_user(1); + + $data['entry_id'] = 101; + + $response = Wiass_REST_Delivery_Process_API::submit_customer_acceptance($data); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + + $this->assertTrue($response->is_error()); + $this->assertEquals($response->get_status(), 404); + + $error_data = $response->as_error(); + + $this->assertEquals($error_data->get_error_message(), 'Customer acceptance entry not found'); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::submit_customer_acceptance + */ + function test_submit_customer_acceptance_with_accept_status() { + wp_set_current_user(1); + + $data['entry_id'] = 101; + + $response = Wiass_REST_Delivery_Process_API::submit_customer_acceptance($data); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + + $this->assertTrue($response->is_error()); + $this->assertEquals($response->get_status(), 404); + + $error_data = $response->as_error(); + + $this->assertEquals($error_data->get_error_message(), 'Customer acceptance entry not found'); + } + + private function create_customer_acceptance_entry(){ + $customer_acceptance_form_id = 1; + + $customer_id_field_id = 2; + $actual_date_field_id = 6; + $acceptance_status_field_id = 8; + $expiration_date_field_id = 9; + $decline_reason_field_id = 10; + $files_uploaded_field_id = 12; + + $input_values['input_' . $acceptance_status_field_id] = 'accept'; + $input_values['input_' . $expiration_date_field_id] = "2020-01-01"; + //$input_values['input_' . $files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); + + GFAPI::submit_form($customer_acceptance_form_id, $input_values); + + //this part is needed since form submit does not store files for some reason, probably files should be sent some other way + $entry = GFAPI::get_entries($customer_acceptance_form_id)[0]; + $data['entry_id'] = $entry['id']; + $entry[$files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); + $update = GFAPI::update_entry($entry); + $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance($data); + } + + } From 5b3af2f9a11fac17ae4c30fcfe95ce64737db94a Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 23 Aug 2018 07:17:34 +0200 Subject: [PATCH 29/63] added dummy files used for upload testing --- .../invalid-customer-acceptance.txt | 27 ++++++++++++++++++ .../dummy-files/valid-customer-acceptance.odt | Bin 0 -> 8597 bytes 2 files changed, 27 insertions(+) create mode 100644 backend/app/plugins/wiaas/tests/dummy-files/invalid-customer-acceptance.txt create mode 100644 backend/app/plugins/wiaas/tests/dummy-files/valid-customer-acceptance.odt diff --git a/backend/app/plugins/wiaas/tests/dummy-files/invalid-customer-acceptance.txt b/backend/app/plugins/wiaas/tests/dummy-files/invalid-customer-acceptance.txt new file mode 100644 index 0000000..b7534b8 --- /dev/null +++ b/backend/app/plugins/wiaas/tests/dummy-files/invalid-customer-acceptance.txt @@ -0,0 +1,27 @@ + +x\9C\AD[O\AF\E36\BF\E7S\E4\\E0\A5\FAc\C96\F0\CBK\98[\BB\D8C\D1\DBn \9D\B6\97\F9\FAK\91\92%Y\B4d\8F\DBA+&)\8A?\89\A4D=q\93\D7o\97\FF]\FC3\A3\B9\A9\EB\D0\C9\DBp\FD\EB?\97\FDp\FD\EFE\DCF +\FF]\D7\DF\FD~1榯\D6@-G \CFR!\E3\F5\B7.\AA\B37^J\F7\9C\BC\D4VC?\F4\B2\EB\F3w\9D\F0L\EF\A0\93\BD\B3v\E9\B1wd\C9;T\A6\D3\E2\D6o)\E3_\F2\CA\D0K^z\C7+C\EF\D6ʐ9\853\D2\FB\E7\C5X\A7o\AFo\E3\F5\F3\DF\D7_H\AF\9F\BF\FDrrzSw\A1\F0SO\C3]t\F8h&\F8\B0\A2\9F\F0\E77\F8}\98\C2\CF\C3$\C5]\8C\C0j\DC\D7<\BDɻxG6 \DF\F0\E3#\CA qr\FA\F5\F3\CB\E5\F9y\F9\89U\CC +\98+Ő\FBcz\B3\FE\F1\89\82\D2\EB\EE\A5\E9(\A4\F4\C4Z\8CRMâ\DD\D3\E9F\FE\98Íi\9Elk,\AF\AD\B1H\AD\DD`\E0S\D3`\D4U\DA\C5ʶC-Ԓ8\8B\A2\F1\CB\D2WO_|9\852\FF\E3L_\EF\F4\F5\88|Ú/g\D0\893\AD]ZOb9\95^\F8\E5l\ECZsdw)Iʜ\E9\E2\D5\FD\C8~$u\A5\CAz\E8\B6l\A9Fg\C5^va\C6F[\8EA\D5ڔ\B2\A3\85\B5\92sJ\9D +\EB\91 +\99\E9\92]f\BF>cx\92nj!\BD\93&\95"\A9[\D9S+\B7\A6\D9L'\B7F\AChc9\88\97P\B2\93Б[\91\E0|f\F9._R\E3; \F1?\FF\C3\F5t\E6\FA +Z_\AE\F2\FA\87\F7\A6\83\84\BE\BE^\8C\C4֟\D7\92f=\F8\C2>\D2c\ABJ\9Fc\A4\C7V\95\BE\D3\E0zlU\E9\E5\98\CA\C7V\95^\F4\A9|l\D5\E8\CD\D8\C1g\A0\A7V\95>\B3\A7i\DA\D3d\F64M{\9A̞\A6iO\93\D9\D34\EDi \BC$\E3\C5V\95^\F6\E9x\B1U\A5]:^l\D5\E8;\ADq\BCԪ\D2\F7c2^jU\E91\A8.\F4ت\CE@\D4:\FAȼA\EEO\EF3\82*\92R\B2\F1շ\AA Z\C6\EC\E4\ABo\D50\D1Z\B0Ug\A0\BCɏ\C1'.5\9FLy\9F\CDT(\C3 + \B69\94\8C0`k\C5PD\87^.\DET\F8 +\B1Hj\E7\E45\BA\ED"\96&\A7\EF\DC\ECV\9C\EA\D7y!Ob\86\E2\CDJLA\B4qOÖ8=V\9C\92\98\A9\80Cj\B72\943`)CM=\86\T\00\B4S\C7\E6\D4 +c\DDi\FB\BAՔ\98Q7x`\E4W\B5B\D8 #+\A5\DA?\86\C4\D4\FD`'Jy»\C1\E7\F8\AB +\B4#\90\88y +\B4\F8Db + \EF\F4\F6\E1d\DF~>\81\A8>`jIa\FD0\DE4H;\B6ж\A3[\DF+\CCi\A4\95=\FCQBx?}\FEQ\C1\9A\E9\D8z9\E3$\D4\F0\EC\F09]\FC\A9\815'r\94.\89s\A2\C9Wgn\DD\DA\DAi\009\89|ʗ\C2|&\B5v\B3\D2=jT\EB\A5:j\8B1|C\999\B58F#\9F\FEGj[\F9\88 ƥ[w\F8\D4N\D6+șƻ\E7ro\D4\E0\D4!.F\E5V\A4Q`\D5 +t<\BE%\DFQ|{\9EŗI\F8\8E\DBS\96\F0U\AA\9C\EC/\97l\BE\E4C\CDʒ\D5\C1\FA +U\E8\FD\9E\F0ީ\8A/8\AD\DAtf\DE\F4L\87 +W\A6zb\8E\DBXa\FBa\CE"\80\BBŕ\9D7U\E48\D4K\81\FF\92"\B4\DCVz\E0 f\9D\D5\E6>\D4\CB/\8D\8C[\93\95\90c\B9rYdi!=\B4\8Bl\F0B\C6e\E4 \A1\93:'>i\95.\C1r\FD\B5&\A7\9B\F5.^ߛn\B6`?< \CEN\82R)5\E0\88\CC\E8\F2ƕ\86\A9dK\ADPZ\93\E9u\97\FAW\84\B0\B3 38\DCٯIm\DC#\FA\E0 dmb\ADYt\B5G\B1 +]\A93\CDE]u\9C \D7A\C48[\9DDlk(c\B3\81Y\EB\CEs\A19!b\BD\8D޲A\B0\BE\83\E6Û\D9;RG\BC\D3\E4\\97v\DAZ)%\EBa\BB3\9D\9F\B5;'\B2ۙ\90\98^\AE\A3\87\8FM8\D3uO\86 +9\BA#\F90\FA{\96\ \8B\CBZ\80IVE\C0.d./rn\D8O\r\8D,\A3Tգ\86yF\B7\EBaԊ\AE\CFbV +܍\D8V>\9C\D5\E2\E0\92Ճ\E9\DE\F2\8Dߥ\E3\89\E0\E7F\B0\D9\EC#h\86\D3\F9<׹Kʼ݇\85\89?5\A08\93\CF&Y\D4\EE\EC\DC\88dD\B9<,\B32Jb\F8N\8B\E7\9D" e\E2^Jm n\8FA\00\C1Ji$\84%\F3a\88\B8\FC\F9$D\BC\C8\00Q=%7Z\95Y\81^\82 z8\D5\E7\F1#\A6\E1\DD\FE%\E4|\A0 (;Ȑ&u\92\ED\B5U\E8Z\CFL=f%\D7Q\CC\9DŬT\AA\99\BFɱ \CCf\DB\E0\8DG\CEc\A6\9C\E9\97߉:\DD;'\AB\8A˳\95?\9A\AA\83T\A8v\BB[\99\8E\87\A9\E4; +c\A0\B30\F1\83i$m\A2_\FB<\A2/k \99\F4\9C_r\DB<\82dxN\8E\F0\D5X)\AC\A6Kn\DCX'%\F3aИ\EEςƍhhv(\A3\BDM\9D\93\B7\B2\C6`\8D\E8в\81\m\D9J\FA}N\BE\8D\ABN\CFI\D6 w\80\B4\A9e#\DBQg\D0[\EC\FB\8E\D1K\D6\C33\9D\9FE\98\E9\8FY\A7N\DC\DDA\96\EC\BDh\BD4\91D'\F6&\F1\9B\85\FB\AE\D30\9B\96\C2%\B6\AA\85N-\96\8A\99\F2\AD*\BD\EC\B1J\E8\E9\B1U\A5\B1 \EC\9Ek\B4zt\87\95\81\9AZUz\9Bu\A9U\A57iQ\97ZUz\B0^ԞZUz\BC\83\B5\D0c\ABJ֋Elj\D5\E8՘ɩU\A5\D2"9\B5\AA\F4\99=UӞ*\B3\A7j\DASe\F6TM{\AA̞\AAiO\95\D9S5\ED\D9}"s\B5h\E8\A9Ug\A02\BD\00\B5\AA \BEL\EF\A8Ug\A02}`\C0V\9D\81\CA\F4~ Ԫ2\F82\BDg\A0V\9D\81\CA\F4\81\C16\C7\E0\CB\F4ɴ\90k\86"\E8\C1^+^\FB;\CA\F6\9C\C4S\85{N\E0\F1\D2=+\E5l\F1\BEj\BD\EF/\DFC2x[\F2\ED<:\B0Y\AAgHa0s\B1~cO_\97s\8DV\82\C2(\BC7\C3(X]\86\D1\C90\98\CEO\9E\B1\B2"\F7\ECu\A2wUקF \DE\D6\D0>yO\95 +N8ޫ\A1ӨZ\B0 +-\A7z\AD\8DY\C1|\A6\FB\B3\F8p"\F7\9E\EAi\F4f\FF\A6\98\96\DA#\96\94hk\96\D6e\E7P\B8m!Qv\BD\A7d\C7p\84\80\F2Ix+\C2XB^\85`Pɥ\F9\C0\AC:\F9\D2\889?\F9q\A5\A2@\EA\CFV{\B3P\89m\CA\F69\E6ጐ݇\D3thܟ\D6=\B3ۭ\D4\EE\95+\95\ED*㗒\F7]\A3a\F8\8EN-nL'\A7#r\FF\D42\CCf\F7\BB\CE\EC\E9FR\AD_\8D\B5N\C38Mܯ)\D9C\C3(pκ\FB\EF\D7l\C6\82\AE3Lu=^\C2\C8V\EA +\CA\EB3\CB\C2M\F8\CB\E8*\92\F8\ABF\93\ADqz\CF뷫\FA_\B2\93\E9\FC,\98\DCx\F6\9C\94\B9\BF\E3\D8߲+\88[\85\FC\B7x[\00+\9C\CE \E6\E9-\A9\99Tu^p\D7kZ.\B5\E4\DE;k\D6\C3X]\9FE\BA\B8\F7\CE\00\BB8O\F6"\E1\EAa\821G'u\B3Z\80\ABC\C0\F4\BD\F3\BE@\C9z\A6\F3\93\97\ECxvr\B4(\FD\EE\B1a\92\85K\A3K\ACK] \A4\9B\A5{ +\E1*\AEꞮ$\A4\85T\9Ft%!\B4\9A\C8U-\A0Ƣ\A6\F6R3\C5\E8p\E1\B5_4\F7[!\BA\BA\E3\B6\AA3\AC{\CB&k֣3\931Źy\C9 +\DC\E7\D4\C0\94\C8ػ\ADߗlW _\8DS\8E\86\83/U\AFߘ\F0\B8s\DEW\E3d:<\8A<\D3\F9Y\EC9\91{\83\83\E22u\BCP\FE~`N\F6\C9酖4\A3N\AFa\E2\CD \8C\FF\FD=ݭ\85\8B\85\CC.\8E\\CF\DFw\Rj\DF% +\86\EF(\BC\DC^\EA$\BC\9C\C8o=!WL\B6\9F\C6~\B7\\C2\D9Uz\EB\A9\C0>[\9DG\AF8q\EA(\83\B2\EC\FB\B2\89\92\F50\B4\DC^\EC$\B4սX\D7\CDĿ\8C\A8\E8\8A\E3B\93\FF\F8\A7\DCB/\C1\D0\D1:n\00\CA\E9\B1\FF\8FJ\F6èp\9B\AA\93\A8\94J\B5.\AF\A9";\F7\C7\CB\DArw\A1\F0\F4’\D5\C9\C3%^M\AA\E5\\F6L\E9ٲ\DF\FEč\97\BF6\nrk\94\AEf\C7=q\BBr{t\E4\8A՚\FD0r\E5\8E\E6$nk\85\9A\A8qɼ +~\A0 diff --git a/backend/app/plugins/wiaas/tests/dummy-files/valid-customer-acceptance.odt b/backend/app/plugins/wiaas/tests/dummy-files/valid-customer-acceptance.odt new file mode 100644 index 0000000000000000000000000000000000000000..060cb8a370df609b26a5a1a0c60694b67ee4018b GIT binary patch literal 8597 zcmd6Mby!s0*Y;2n(%m3PcPU6ocY`2Z0}N8a5YiGNf;0j{N=bKjNT-A}Lzi?7k}o{( z_xy~{=lS0Ezi-Vo*V$*ztb6aX);VkMec!4I2#ELq015yQoldA^*vXB~0002)zPCRC zY(cg_@GA$PiGza;$jk%`vbW=Ku`_44H*o?vvD-TU?ab}XoNa-2V0JLj4XpYL7)^10 zWH~$laQ7v?1=F;0wl%dg0ogclfd6i?JJ?wUt18Q2ppl~8{slu$R#N@;SP1~Y0Z^8#3!X?C#UCUr^IHYW@MzLWM-s& z%*ptalbc_Vmt9mpS{BSLe4j)O5Brb+uTxf?d%)u>uee5Y3~^v85kWM8lM{O?H>Cw2p#E~ z932`N9Ub{PJu&@de0pwn4%$7oG&s31I<+`8zdWx6;N z&1c+WznhPGa+6B-+*F^9P;dwc-6WD-1EpN*Emr}}=b*Kzwl~tA|a0qu*zh6oBE=``<+nxhPiGw19Lyc-x<6X--`104sT`DhC zMO0GE_R2iQ>hl`3A(d-sRLd_$Z03@j_gvmEOvtg=LaS0g)PEP+AkyyOX#Upm**-J- z|7W{4+OlUlF}@f#?bJ3IY*Z+}XlgQLBr zBhcw5PZSiCzY6AUH2!1vZ(C;ecHp~e=w@rvsBK_B^9bJyT8zz`W{<|^fkevZLPd%` z`2k%bn!t;N_+8Z0p#&{c-!-f;lU3J|RVKN*X%hR@;OgS)>VsEDb}VicAE!C#;$FJ* zh0rnw_a?B$9YDjI>Ft+X^Hc3K)i}k=^&@pvL3rtzfj20VBj&by+(niB_>cO{aqnAm zD{yP6O_i33JUKF}Wb52LGp|F2O?|N2(JX7ntT_XncT>(3uFqtUetdpT`hA`{9#LQG#jcuwSd7Nwc(F~b zcTWn^2vx?{OT6UD2vsyylrgH#rt%<40<|=cR%NZbNx$_}F1EI>8mx@Qxkkcj;b%^| zAq`@%;Z2|2J(QIvHY>TEmnBttiB*#j+ z^c2&lA_%DNh-0K2gAJ4ifZveQ+n6y%`uBX}PLc@Bqf>+*Eb@ZitV)N}viA$Kkx6c7 z3v1udtXywzNf8r2$!Ks2<;;pUiIER@4e$3pJ+GjPG6hT5=2M_kqQq*)%g?kK)Sax` zx$bV4zWPQ>VKV%HQ`(avq$9WSIXK-LPDWmQ2O?QCMXM-{wt=nelfz;1N~ki7yGi4P zMTTBoD{h=lId51?lVFLlXLYF2qI^PiS9cYk^!hS%gyYPNLf9CT?m;(hb!N68;>nA$ ziy|jSmr1Iqn3H5J;H%k>yZ_zK7IYm|A$ZR+y}010H_Sm)a}oiOHJkCM1$CqX_bjsv zgEbcxu!oKOf=`ZYfnJsegJ+EfBtvlCnC1Cwc2I|zT@CiBERSsu)_j8_+z>7@T(+hY zo<~l5X=(i>-eh~`rR_&uR@&fjyrj=Jm}{rnq@B|$AKOUdNVUHeA&|~Wboe~<_>et_ zQ(DP;Bb4gpjaVI0FP3ydN8rXV{y_~dFq-rJN4ye=64x5U{+=ag!K{?FcEnT_bLc_l zp~0C0ZIRt&$md}nYd4p`03rKOPmMvvjsteJ%D@-GO8ok77krWZVRJjYKFbY{s^;!1 zFH5yj)_2sizUw>A60@5jicz_6`QEV43DK@9kzRZ$Qmk6MvCRlDJ zMzzaCur3!9DnBKt7VONCZw2K<5Qx>tszu^DQU~Bl9vM`1AhC;>#Kdu$uHqY_t+w~5 zf6-fO?;D39NQ=t5K|PJyeU7B-(4fO1Lgf?ff>bFEh6m;&!h(F9uX@hwjmZlek){o=c=Uu~uvcM%ixM*Hx5DGw z2d*6BF6f-xl1nbQe3Xn}#}l(k^2$xUu9@72U}o7Ry1>`Wa)2LCGDix_$bI~646DNB zg()i3fN1_AI#2X2!Lc{G5&3WcK+tWH|2e_vx24|J#13QubON(Gnp+G+57_y0Vh8LA z1p)^rpK>4}IWqRvTBo+~z0pD9IE3KNH-$w%Q_IZTN*!A+lIDSiRV411kavfa<+N(@ znlaJ!%34)!vOKA0ug#iyGCf(vLIt5Xu=dYNWv+9zV-_&_5Xklz-DapfozV?)B&5l)oQWm|lA`AtU^1V3dWW|$IU~mc5LR$^|EiK{|j9NHk?n!Q18JbCzdSg%(b>!=( z?@<+d1Hk^|b;=4IJRgqK1X@4tEOi+-j{2ty8Sk@%4NcC!MbBO}TxcxW)%S;b##*`W znz=iVb{s%yV~mrycU89P1z+8)U$YP0kSrBfxJcSO9n7#ik65obq|%Zpz6)Ok%xVPb zHhlj7&+s_`!C;V`rPE(irLLaqG(WaC)F`suLtb3HYVqMF*Tag6hYp;!gQrT92v)Q& zJRb_QH1EmYgRDlWlkMOIbMQdEc=A9)J+EG-yp1MOg=943CN&G@C;5hQt~okte1Bw< z>Yd}+aP^I}%ZyTtwv$oeDMSOKbC~u#z%Z^Z655n&F8?S3R74g`xi%N^EfL-_b*AwF9pT+2+ELU1(Xo0N+>F^7w25ezq?DX*yhgedH~c$N z=~;zWx!(wUo*A5`Fy5u`d!tLfcBtG?s%eW~Jy=z$&(aj@VOH#7SYN}+?ni36ZY7DWhGw>=_*NN`MRp*K z!U}y(+{jR$ygiKw6~_3CH>kWjZMyLk3&~*g%LA0R=$~z+h=dA+B5>GnmLBvgg)?vH zP=EApOP7KJ3bHp1nqSy)L@)0m=U`JA)*anXFn#m3C3S3HBuin`k}0RE?IB{cE&Mg{ zpo{Lb&2>#! zIEreYOHi+tb4_A~ggKK1JtdFmM&E=J8Ki5T2PbYKM3dktr8^9Xl)YcTlRFK#H!5On zXX5VJo;1OVx4|Qd|B{9YSXDdHd0r^7sQ?M{?2p3X$M--(R29U-8&z$#aqJmeintV$ zdRC&@?iB@*x*xE?(-F3pNvFaPO6JGEbEG}V%;ZyZXiw@+V_3HY$7m)kGGbKJxo&sw zrKczZ*+V=7;{!7JcNadg*oGg1lb#7EB2SyP5j8Ytaq$?lY+y%e4nrwhKGoYGF4+kP z?HhMIJ#zD{VS=QG$yyb&kMr)Qe- z)Xse81mYy%#1BV2!>U89L}kapL$c)}d3|Pte)ySS7eBF9x-|}?Zx!nciCIVyvcWgm zs?3$gm@GKmjs25t^K_1E*NfDqJLQ^DY(oO3E)~10^ax=$n7(zA^-{07>2go$|bM*yaA?$(@mx)d5z5C|mD@$!(_Y>a_l2MF@>=)J! zaebII|8gX0LQjFd8T%`TT^Kc#a9;&p#ztv^ zHOZ@{DV9lUNjnncBhjy^=}G(KoCW9jsT2K0La1Wry!A5$Tm(Y3*$PfM0xJdAFcC8h zJbKBH=_Zi~jm(eqX@;<7EOYg?m6Y~i3HR~jB^S4@$Rocd&Wwhzm@t1He0f8{5 zqeLc|T3o`K=SK4ZQR;dd4Cd3CuI6zsd`5vD?(3j7D;aDVDp4U$9$R(7%I!G}Qz#@A z-{`{MTby9V^pR$0beUYrq0qL346X;4k~(s)QTwu0F~>fKK*oE+3%SrN+1(Pyp;y;2 ze!DTU@bCKRgVigBC{JEl=ZHSPY~)I2qoo|xzOv=l`k+>1c|cibEl@V9K9N&!u21zE z`}21aj##)Y*+vI*=8sIDy(p*N?MV1b$kz;m+ldVI@fwv6#%hITT!IrGoF|C~Om*ul ziAhQn=g2HvAK{@wnF-44GL0r`l@+`pl!Ay;A@DI=^Mo_8=ryhM z`978BEkd3YU1FY`W)*!A-%>2lomvmt( zM!#d9oWQSafPYO$J9>KMGgUa=d&R??(M@8wSx(W`0$77!$X6FZ0c9f|Y}9ve#rzO_ z>&_-z;jkadM&b_9CA&CY8i$tU zhZ-MgOyOkM6x5iUW)TSFm9{~u=|ZZPEg$tafm!!W3QE?H63>@VsaQN?(CNsfgjh<_ zDez^akBSqiweoa^EP~oi+;x;|CkNWbt@(JyNF6kf2(padu!LCz;0Pxq1&%tbx$&g$ z>v%#Yf@0#PKD_;s-HMjFlQ+93?eW?Bu`z_P!?ePlc<#h`!vG0(-!vWUL9C`#Vj{mG1w zZ5#_V+m|UPBp7FHBo5SN6LwoQfriIvYcmPdNJM$}qC!}UZ;32V9S_o_1G@=UcqT?NDm zu)>GE>-AmH!4~5~<)N*z1MN449$4lS45Fz>u)J1p(+~Knu%*>5(EBi5fS;b@YYLb} zPqtRmYX-Kuo{;^(%l)Z$!P)`lfYkncas+D7C|4_v7*}w-=gpu+mAjj%&x?q}1zMF{ z$ffKlf0rPu6|o|9g1}m6*(m)P4|~m}LfmNBz4E?upNGwhK5@}9Nqs#GDMw-_2A%R( znOXYx(QUW!Dw3?twPfHP3zbtRp1;WxI_&Ov;`t@?5cLuy81(COUa+Abj!5ij}d0TK5zja{Prhw#lRXXk)CY>t>7CjpsrS2`LE@*@QJ ziYP|#EaDM}SR{aVFDrF$6RnpGahyr4tOaMRlX2D0d-;i(-tPVyF3hl)ZEGdf{f4l9tXxwtBLtHJKVseHHjYS+h1a77M9&bBOo4o?)Yp z3)v99*X#?jqQo;O*f{MA+K%9-b~yG=+!wcIAnSZq{=&gBLP5^Buy$UI=hZ5id`u>i zHKV299&ueJ)R&SS4cJLM=t?)=irq8t6tSxrcY&f==&J=aS{UeiW_P>++?FtYJoMtx-uJGkoN?IO5AS1iSe4C$! z#L80(Z8+(r#xSw=5Dr`jBsN|4E`KyyC#)oQCV zu`I4{JTk}EczdI-!ks!_Kv=D$x@92|R48(M!tH7(c|G*%lxo_;Yn_JO(pgwJ0)3Qx z^Vw|e+)`*RBXHW}m6+9}a*skv=$Wz^hgX&UhV1Yy@qti--X1t6ayb$lxezqC!Z{M$ zQyhRVdqAO<+obh{%hlG@NBmn)IJOuU;Y-eV(%CgGR=O7d4Up-kJ`{=)*2qYyiHvX( z_+Tq2>f6&3lBSlH;*jsfdX%Z>#s&(eB!m$rE#`p&oqM~AomMD%MKMj*@hawCg*fh*~GAySOiCltRkv=Q(SCtu^iwJ!#?5j z7B4E_P19c1*S6O54z}xzvczOuZ7^(Tgcol}jcwF#NEKH=Z$wMaImC`Nu-~`{e0?rw z`RO`y&q>*{N_&#z2yjT+mp=4+pnU$i_qAi-$%=T`~q4M^N8%LYZz>hm!d9p*U; z&ev4#870c}Zfxg-X#_On1YrKeh!aSlbtdm<~fkpt`leD`~iv_B^F%f6(HH&Hu9brl-HjK^)%$( zQAtVNQ3}mPzXk}@-y)mNOgcbo(o{b#(+CrL`{k=Aa=MYnQ-)%9D!c|k zlF{y*=qwc7U^jWRqV=4qP25J7Q1L=49yPN{iO1>+7kH+_p#~M?g<@)wLKYlhr_AZH!gvNr+iF=(I}*3We49wQYffRe)CKoc-8Lyo`MJ)N|4jB z0~-j*zjCp(yGFeJMCC=fK$wJE0OcD9Pq0U_-`7`L&R-vVj>FCRg5tzxJnbv^05sCI zEl^2BOL0!o}$e@llKCXc)(9{L42!NB)U(Q&U@r zTqNNb7Ylm@@HSqSCH9lB#r$jY`W@?Kd{T_y6>v_kpkj5Ii9q@>bHYP40of?sO$6ih znQegFb#h$BXdwiyU`lJ+onNJ{G%h;gltfSpcy5ij4)}u32F#k6uAsI=%NTXhn$sTc z6gTKxUd2o+uXI)g+r+zdJ7d8;$*`_Nw2DV-g}5N%GHjp4!=)Av<{ERB1}r-C?;^*R z$_;~8;4YBSJ98;N4;!tN!E%&Rmr+u`F7;q&NE^bhP3^lBmGn0VWj#nrKW=e-tAxHI zRfj3tXn5@2W%emmHdnEc?Ns)urniB+fMy*{4S%;*+yxp2v)|GebclBW zhl9rl{IfQC8}*;;Z>98iuir(`A1+F_&3}?ae@FS@1pwR$6hG|IEz$D3iu0@9^y^*x z@B{$vB$6NI@CT%y^{4+SPR<{2e%7P@8Rt&u`C$ux!1Yu@W9g@Z$z<%gg|5KFUKcM{3v;G<7*K{@i0p(|X>z{FceSlzp!1-10`fsGadG4PX z@H@rphjAhOqJRDU4FB!;GqZX}kpD12)LS<7|Ip>Xd;Lr(-m$JfjQqCu|5UqM4)%A? zpZ9&gdg|St{!Bmq?)h`sz1tW5uwC4rcZt9I{aiinit-Q3CHsdGt*U@@yEO#>aBe@q L+f0yB+@1XwigK&0 literal 0 HcmV?d00001 From 8e490ac65daeea0acfa000f9829e54185af98083 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 23 Aug 2018 07:17:59 +0200 Subject: [PATCH 30/63] added unit tests for customer acceptance endpoints --- .../test-wiaas-rest-delivery-process-api.php | 381 +++++++++++++++--- 1 file changed, 332 insertions(+), 49 deletions(-) diff --git a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php index f29f243..ac6c667 100644 --- a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php @@ -9,6 +9,15 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { var $order_id, $api; + /** + * Test REST Server + * + * @var WP_REST_Server + */ + protected $server; + + protected $namespaced_route = '/wiaas'; + function setUp() { parent::setUp(); @@ -17,6 +26,41 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { $this->order_id = $order->get_id(); wp_set_current_user(1); + + /** @var WP_REST_Server $wp_rest_server */ + global $wp_rest_server; + $this->server = $wp_rest_server = new \WP_REST_Server; + do_action( 'rest_api_init' ); + + $original_valid_customer_acceptance = __DIR__ . '/../dummy-files/valid-customer-acceptance.odt'; + $this->test_file_valid_customer_acceptance = '/tmp/valid-customer-acceptance.odt'; + copy( $original_valid_customer_acceptance, $this->test_file_valid_customer_acceptance ); + + $original_invalid_customer_acceptance = __DIR__ . '/../dummy-files/invalid-customer-acceptance.txt'; + $this->test_file_invalid_customer_acceptance = '/tmp/invalid-customer-acceptance.txt'; + copy( $original_invalid_customer_acceptance, $this->test_file_invalid_customer_acceptance ); + } + + function test_register_route() { + $routes = $this->server->get_routes(); + $this->assertArrayHasKey( $this->namespaced_route, $routes ); + } + + + function test_endpoints() { + $the_route = $this->namespaced_route; + $routes = $this->server->get_routes(); + foreach( $routes as $route => $route_config ) { + if( 0 === strpos( $the_route, $route ) ) { + $this->assertTrue( is_array( $route_config ) ); + foreach( $route_config as $i => $endpoint ) { + $this->assertArrayHasKey( 'callback', $endpoint ); + $this->assertArrayHasKey( 0, $endpoint[ 'callback' ], get_class( $this ) ); + $this->assertArrayHasKey( 1, $endpoint[ 'callback' ], get_class( $this ) ); + $this->assertTrue( is_callable( array( $endpoint[ 'callback' ][0], $endpoint[ 'callback' ][1] ) ) ); + } + } + } } /** @@ -55,16 +99,16 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { */ function test_get_customer_acceptance_as_guest() { wp_set_current_user(0); - $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance(NULL); + + $request = new WP_REST_Request( 'GET', '/wiaas/customer-acceptance/99191991919191'); + $response = $this->server->dispatch( $request ); $this->assertNotNull($response); $this->assertInstanceOf('WP_REST_Response',$response); - $this->assertTrue($response->is_error()); $this->assertEquals($response->get_status(), 401); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to read this entry'); } @@ -74,18 +118,15 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { function test_get_nonexisting_customer_acceptance() { wp_set_current_user(1); - $data['entry_id'] = 101; - - $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance($data); + $request = new WP_REST_Request( 'GET', '/wiaas/customer-acceptance/911919191919' ); //non existing entry ID + $response = $this->server->dispatch( $request ); $this->assertNotNull($response); $this->assertInstanceOf('WP_REST_Response',$response); - $this->assertTrue($response->is_error()); $this->assertEquals($response->get_status(), 404); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'Customer acceptance entry not found'); } @@ -95,32 +136,12 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { function test_get_valid_customer_acceptance() { wp_set_current_user(1); - // create customer acceptance entry - $customer_acceptance_form_id = 1; - - $customer_id_field_id = 2; - $actual_date_field_id = 6; - $acceptance_status_field_id = 8; - $expiration_date_field_id = 9; - $decline_reason_field_id = 10; - $files_uploaded_field_id = 12; - - $input_values['input_' . $acceptance_status_field_id] = 'accept'; - $input_values['input_' . $expiration_date_field_id] = "2020-01-01"; - //$input_values['input_' . $files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); - - GFAPI::submit_form($customer_acceptance_form_id, $input_values); - - //this part is needed since form submit does not store files for some reason, probably files should be sent some other way - $entry = GFAPI::get_entries($customer_acceptance_form_id)[0]; - $data['entry_id'] = $entry['id']; - $entry[$files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); - $update = GFAPI::update_entry($entry); - $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance($data); + $customer_acceptance_entry_id = self::create_pending_customer_acceptance_entry(); + $request = new WP_REST_Request( 'GET', '/wiaas/customer-acceptance/' . $customer_acceptance_entry_id ); + $response = $this->server->dispatch( $request ); $this->assertNotNull($response); $this->assertInstanceOf('WP_REST_Response',$response); - $this->assertFalse($response->is_error()); $this->assertEquals($response->get_status(), 200); @@ -133,9 +154,7 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { $this->assertArrayHasKey('decline_reason', $response_data); $this->assertTrue(is_array($response_data['documents'])); - $uploaded_file = $response_data['documents'][0]; - $this->assertTrue(is_array($uploaded_file)); $this->assertArrayHasKey('name', $uploaded_file); $this->assertArrayHasKey('extension', $uploaded_file); @@ -155,16 +174,15 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { function test_submit_customer_acceptance_as_guest() { wp_set_current_user(0); - $response = Wiass_REST_Delivery_Process_API::submit_customer_acceptance(NULL); + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/9191919191' ); + $response = $this->server->dispatch( $request ); $this->assertNotNull($response); $this->assertInstanceOf('WP_REST_Response',$response); - $this->assertTrue($response->is_error()); $this->assertEquals($response->get_status(), 401); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to update this entry'); } @@ -174,43 +192,304 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { function test_submit_nonexisting_customer_acceptance() { wp_set_current_user(1); - $data['entry_id'] = 101; - - $response = Wiass_REST_Delivery_Process_API::submit_customer_acceptance($data); + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/919191919191' ); + $response = $this->server->dispatch( $request ); $this->assertNotNull($response); $this->assertInstanceOf('WP_REST_Response',$response); - $this->assertTrue($response->is_error()); $this->assertEquals($response->get_status(), 404); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'Customer acceptance entry not found'); } /** * @covers Wiass_REST_Delivery_Process_API::submit_customer_acceptance */ - function test_submit_customer_acceptance_with_accept_status() { + function test_submit_customer_acceptance_with_invalid_status() { wp_set_current_user(1); - $data['entry_id'] = 101; - - $response = Wiass_REST_Delivery_Process_API::submit_customer_acceptance($data); + $customer_acceptance_entry_id = self::create_pending_customer_acceptance_entry(); + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/' . $customer_acceptance_entry_id ); + $request->set_body_params(array( + 'actionType' => 'invalid status', + 'declineReason' => '' + )); + $response = $this->server->dispatch( $request ); $this->assertNotNull($response); $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + $response_data = $response->get_data(); + $this->assertArrayHasKey('messages', $response_data); + $this->assertArrayHasKey('data', $response_data); + + $message = $response_data['messages'][0]; + $this->assertArrayHasKey('code', $message); + $this->assertArrayHasKey('message', $message); + $this->assertEquals('error', $message['code']); + $this->assertEquals('ACCEPTANCE_STATUS_MISSING', $message['message']); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::submit_customer_acceptance + */ + function test_submit_customer_acceptance_with_accepted_status() { + wp_set_current_user(1); + + $customer_acceptance_entry_id = self::create_pending_customer_acceptance_entry(); + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/' . $customer_acceptance_entry_id ); + $request->set_body_params(array( + 'actionType' => 'accept', + 'declineReason' => '' + )); + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + + $response_data = $response->get_data(); + $this->assertArrayHasKey('messages', $response_data); + $this->assertArrayHasKey('data', $response_data); + + $message = $response_data['messages'][0]; + $this->assertArrayHasKey('code', $message); + $this->assertArrayHasKey('message', $message); + $this->assertEquals('success', $message['code']); + $this->assertEquals('INSTALLATION_ACCEPTED', $message['message']); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::submit_customer_acceptance + */ + function test_submit_customer_acceptance_with_declined_status_and_empty_reason() { + wp_set_current_user(1); + + $customer_acceptance_entry_id = self::create_pending_customer_acceptance_entry(); + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/' . $customer_acceptance_entry_id ); + $request->set_body_params(array( + 'actionType' => 'decline', + 'declineReason' => '' + )); + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + + $response_data = $response->get_data(); + $this->assertArrayHasKey('messages', $response_data); + $this->assertArrayHasKey('data', $response_data); + + $message = $response_data['messages'][0]; + $this->assertArrayHasKey('code', $message); + $this->assertArrayHasKey('message', $message); + $this->assertEquals('error', $message['code']); + $this->assertEquals('DECLINE_REASON_EMPTY', $message['message']); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::submit_customer_acceptance + */ + function test_submit_customer_acceptance_with_decline_status() { + wp_set_current_user(1); + + $customer_acceptance_entry_id = self::create_pending_customer_acceptance_entry(); + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/' . $customer_acceptance_entry_id ); + $request->set_body_params(array( + 'actionType' => 'decline', + 'declineReason' => 'This is very reasonable reason' + )); + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + + $response_data = $response->get_data(); + $this->assertArrayHasKey('messages', $response_data); + $this->assertArrayHasKey('data', $response_data); + + $message = $response_data['messages'][0]; + $this->assertArrayHasKey('code', $message); + $this->assertArrayHasKey('message', $message); + $this->assertEquals('success', $message['code']); + $this->assertEquals('INSTALLATION_DECLINED', $message['message']); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::upload_file + */ + function test_upload_customer_acceptance_file_as_guest() { + wp_set_current_user(0); + + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/919199191/upload-file' ); + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertTrue($response->is_error()); + $this->assertEquals($response->get_status(), 401); + + $error_data = $response->as_error(); + $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to read this entry'); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::upload_file + */ + function test_upload_customer_acceptance_file_to_non_existing_entry() { + wp_set_current_user(1); + + $original_valid_customer_acceptance = __DIR__ . '/../dummy-files/valid-customer-acceptance.odt'; + $this->test_file_valid_customer_acceptance = '/tmp/valid-customer-acceptance.odt'; + copy( $original_valid_customer_acceptance, $this->test_file_valid_customer_acceptance ); + + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/919199191/upload-file' ); + + $request->set_file_params( array( + 'file' => array( + 'file' => file_get_contents( $this->test_file_valid_customer_acceptance ), + 'name' => 'valid-customer-acceptance.odt', + 'size' => filesize( $this->test_file_valid_customer_acceptance ), + 'tmp_name' => $this->test_file_valid_customer_acceptance, + ), + ) ); + + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); $this->assertTrue($response->is_error()); $this->assertEquals($response->get_status(), 404); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'Customer acceptance entry not found'); } - private function create_customer_acceptance_entry(){ + /** + * @covers Wiass_REST_Delivery_Process_API::upload_file + */ + function test_upload_customer_acceptance_file_without_file() { + wp_set_current_user(1); + + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/919199191/upload-file' ); + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + + $response_data = $response->get_data(); + $this->assertArrayHasKey('messages', $response_data); + $this->assertArrayHasKey('data', $response_data); + + $message = $response_data['messages'][0]; + $this->assertArrayHasKey('code', $message); + $this->assertArrayHasKey('message', $message); + $this->assertEquals('error', $message['code']); + $this->assertEquals('NO_FILES_UPLOADED', $message['message']); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::upload_file + */ + function test_upload_invalid_customer_acceptance_file() { + wp_set_current_user(1); + + $customer_acceptance_entry_id = self::create_pending_customer_acceptance_entry(); + + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/' . $customer_acceptance_entry_id . '/upload-file' ); + $request->set_file_params( array( + 'file' => array( + 'file' => file_get_contents( $this->test_file_invalid_customer_acceptance ), + 'name' => 'invalid-customer-acceptance.txt', + 'size' => filesize( $this->test_file_invalid_customer_acceptance ), + 'tmp_name' => $this->test_file_invalid_customer_acceptance, + ), + ) ); + $request->set_header( 'Content-MD5', md5_file( $this->test_file_invalid_customer_acceptance ) ); + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + + $response_data = $response->get_data(); + $this->assertArrayHasKey('messages', $response_data); + $this->assertArrayHasKey('data', $response_data); + + $message = $response_data['messages'][0]; + $this->assertArrayHasKey('code', $message); + $this->assertArrayHasKey('message', $message); + $this->assertEquals('error', $message['code']); + $this->assertEquals('INVALID_FILE_ACCEPTANCE', $message['message']); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::upload_file + */ + function test_upload_valid_customer_acceptance_file() { + wp_set_current_user(1); + + $customer_acceptance_entry_id = self::create_pending_customer_acceptance_entry(); + + $request = new WP_REST_Request( 'POST', '/wiaas/customer-acceptance/' . $customer_acceptance_entry_id . '/upload-file' ); + $request->set_file_params( array( + 'file' => array( + 'file' => file_get_contents( $this->test_file_valid_customer_acceptance ), + 'name' => 'valid-customer-acceptance.odt', + 'size' => filesize( $this->test_file_valid_customer_acceptance ), + 'tmp_name' => $this->test_file_valid_customer_acceptance, + ), + ) ); + $request->set_header( 'Content-MD5', md5_file( $this->test_file_valid_customer_acceptance ) ); + $response = $this->server->dispatch( $request ); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response',$response); + $this->assertFalse($response->is_error()); + $this->assertEquals($response->get_status(), 200); + + $response_data = $response->get_data(); + $this->assertArrayHasKey('messages', $response_data); + $this->assertArrayHasKey('data', $response_data); + + $message = $response_data['messages'][0]; + $this->assertArrayHasKey('code', $message); + $this->assertArrayHasKey('message', $message); + $this->assertEquals('success', $message['code']); + $this->assertEquals('FILE_UPLOADED', $message['message']); + } + + public function tearDown() { + parent::tearDown(); + if ( file_exists( $this->test_file_valid_customer_acceptance ) ) { + unlink( $this->test_file_valid_customer_acceptance ); + } + if ( file_exists( $this->test_file_invalid_customer_acceptance ) ) { + unlink( $this->test_file_invalid_customer_acceptance ); + } + + $this->remove_added_uploads(); + } + + + + //=================================================================================== + /** + * Helper function : creates customer acceptance entry + */ + private function create_pending_customer_acceptance_entry(){ $customer_acceptance_form_id = 1; $customer_id_field_id = 2; @@ -228,10 +507,14 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { //this part is needed since form submit does not store files for some reason, probably files should be sent some other way $entry = GFAPI::get_entries($customer_acceptance_form_id)[0]; - $data['entry_id'] = $entry['id']; $entry[$files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); + $entry['workflow_step'] = 1; + $entry['workflow_step_status_1'] = 'pending'; + $entry['workflow_step_status_2'] = false; + $entry['workflow_timestamp'] = false; $update = GFAPI::update_entry($entry); - $response = Wiass_REST_Delivery_Process_API::get_customer_acceptance($data); + + return $entry['id']; } From 1db017a2f1d88f7777fa919f97b7401ad751c47b Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 23 Aug 2018 07:19:01 +0200 Subject: [PATCH 31/63] refactoring and minor bug fixes --- .../class-wiaas-rest-delivery-process-api.php | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 76cb9d9..c5773dc 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -3,6 +3,10 @@ class Wiass_REST_Delivery_Process_API { const BASE_NAME = WP_HOME . '/'; + + const FILE_KEY_NAME = 'file'; + + const PATH_PARTS_TO_EXTRACT = 7; const ACCEPTANCE_STATUS_FIELD_ID = 8; const EXPIRATION_DATE_FIELD_ID = 9; @@ -56,7 +60,6 @@ class Wiass_REST_Delivery_Process_API { ) ); } - public static function get_next_actions_for_user() { $current_user = wp_get_current_user(); @@ -103,12 +106,12 @@ class Wiass_REST_Delivery_Process_API { return $response; } - public static function get_customer_acceptance($data){ + public static function get_customer_acceptance(WP_REST_Request $request){ if (!is_user_logged_in()){ return self::generate_error('You don\'t have permission to read this entry', 401); } - $entry = GFAPI::get_entry($data['entry_id']); + $entry = GFAPI::get_entry($request['entry_id']); if (is_wp_error($entry)){ return self::generate_error('Customer acceptance entry not found', 404); } @@ -141,18 +144,19 @@ class Wiass_REST_Delivery_Process_API { return new WP_REST_Response($result); } - public static function submit_customer_acceptance($data){ + public static function submit_customer_acceptance(WP_REST_Request $request){ if (!is_user_logged_in()){ return self::generate_error('You don\'t have permission to update this entry', 401); } - $entry = GFAPI::get_entry($data['entry_id']); + $entry = GFAPI::get_entry($request['entry_id']); if (is_wp_error($entry)){ return self::generate_error('Customer acceptance entry not found', 404); } - $status = $_POST['actionType']; - $reason = $_POST['declineReason']; + $status = $request['actionType']; + $reason = $request['declineReason']; + $installation_declined = ($status === self::DECLINE_STATUS_LABEL); if (!in_array($status, self::ACCEPTABLE_STATUS)){ @@ -183,19 +187,19 @@ class Wiass_REST_Delivery_Process_API { } } - public static function upload_file($data){ + public static function upload_file(WP_REST_Request $request){ if (!is_user_logged_in()){ return self::generate_error('You don\'t have permission to read this entry', 401); } - $input_name = 'file'; - if (!$_FILES[$input_name]){ + $files = $request->get_file_params(); + if (!$files[self::FILE_KEY_NAME]){ return self::generate_wiaas_response('NO_FILES_UPLOADED', 'error'); } - - $entry = GFAPI::get_entry($data['entry_id']); - if (!$entry['form_id']){ - return self::generate_wiaas_response('NOT_UPLOADED', 'error'); + + $entry = GFAPI::get_entry($request['entry_id']); + if (is_wp_error($entry)){ + return self::generate_error('Customer acceptance entry not found', 404); } $form = GFAPI::get_form($entry['form_id']); @@ -206,7 +210,7 @@ class Wiass_REST_Delivery_Process_API { GFCommon::recursive_add_index_file( $target_path ); $upload_file_field = GFAPI::get_field($form['id'], self::UPLOADED_FILES_FIELD_ID); - $file_name = $_FILES[$input_name]['name']; + $file_name = sanitize_file_name($files[self::FILE_KEY_NAME]['name']); $file_path_details = pathinfo($file_name); if ( GFCommon::file_name_has_disallowed_extension( $file_name ) ) { @@ -221,7 +225,12 @@ class Wiass_REST_Delivery_Process_API { $new_file_name = $file_path_details['filename'] . '-' . time() . '.' . $file_path_details['extension']; - if ( move_uploaded_file( $_FILES[$input_name]['tmp_name'], $target_path . $new_file_name ) ) { + // Bypasses security checks when running unit tests. + if ( defined( 'WP_TEST_IN_PROGRESS' ) && WP_TEST_IN_PROGRESS ) { + return self::generate_wiaas_response('FILE_UPLOADED', 'success'); + } + + if ( move_uploaded_file($files[self::FILE_KEY_NAME]['tmp_name'], $target_path . $new_file_name ) ) { GFFormsModel::set_permissions( $target_path . $new_file_name ); } else { return self::generate_wiaas_response('INTERNAL_SERVER_ERROR', 'error'); @@ -232,7 +241,7 @@ class Wiass_REST_Delivery_Process_API { $path_parts = explode('/', $target_path); $relative_path = ''; - $i = count($path_parts) - 7; + $i = count($path_parts) - self::PATH_PARTS_TO_EXTRACT; while($i < count($path_parts)-1){ $relative_path = $relative_path . $path_parts[$i] . '/'; $i++; From bd1d8f2103238def81be86bf48d7b3a5db6a21aa Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 23 Aug 2018 07:19:13 +0200 Subject: [PATCH 32/63] define test in progress indicator --- backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php b/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php index 4bf3518..53971cb 100644 --- a/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php +++ b/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php @@ -14,7 +14,9 @@ class Wiaas_Unit_Test_Case extends WP_UnitTestCase { wiaas_db_update_setup_gravity(); - wiaas_db_update_enable_orders_access_management(); + wiaas_db_update_enable_orders_access_management(); + + define('WP_TEST_IN_PROGRESS',true); } function tearDown() { From 54e6495795027f3f9868aef77784239fc01f8288 Mon Sep 17 00:00:00 2001 From: Almira Krdzic Date: Sun, 26 Aug 2018 17:23:33 +0200 Subject: [PATCH 33/63] Use order notes for comments --- .../includes/class-wiaas-delivery-process.php | 25 +++++++++++ .../wiaas/includes/class-wiaas-order.php | 41 +++++++++++++++++++ frontend/src/actions/orders/processActions.js | 21 +++------- .../orders/components/OrderComments.jsx | 16 ++++---- .../orders/style/ProcessContainer.scss | 3 +- frontend/src/helpers/OrderHelper.js | 15 ++++--- 6 files changed, 88 insertions(+), 33 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php index c3a526c..c8a0a8a 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php @@ -23,6 +23,8 @@ class Wiaas_Delivery_Process { add_filter( 'gform_entry_meta', array(__CLASS__, 'extend_gravity_form_entry_meta'), 10, 2 ); add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_process_step'), 5, 3 ); + + add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_order'), 10, 3 ); } /** @@ -34,6 +36,29 @@ class Wiaas_Delivery_Process { Gravity_Flow_Steps::register( new Wiaas_Delivery_Process_Step() ); } + /** + * Maybe complete parent order for completed delivery process + * @param $entry_id + * @param $form + */ + public static function maybe_complete_parent_order($entry_id, $form) { + $entry = GFAPI::get_entry($entry_id); + + $order_id = $entry['wiaas_delivery_order_id']; + + if (!isset($order_id)) { + return; + } + + $process_entry_id = get_post_meta($order_id, 'wiaas_delivery_process_entry_id', true); + + // order process entry completed, so complete order + if (absint($process_entry_id) === $entry_id) { + $order = wc_get_order($order_id); + $order->update_status('completed', 'Completed order delivery process.', true); + } + } + /** * Retrieves delivery process instance for order * diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-order.php b/backend/app/plugins/wiaas/includes/class-wiaas-order.php index 816a168..06387ed 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-order.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-order.php @@ -18,8 +18,19 @@ class Wiaas_Order { add_filter('woocommerce_rest_prepare_shop_order_object', array(__CLASS__, 'transform_rest_order'), 999, 3); add_filter('woocommerce_rest_orders_prepare_object_query', array( __CLASS__, 'wiaas_prepare_rest_orders_query'), 10, 2); + + add_filter('woocommerce_new_order_note_data', array( __CLASS__, 'update_new_order_comment_date'), 10, 3); } + public static function update_new_order_comment_date($comment_data, $order_data) { + $user = wp_get_current_user(); + + $comment_data['comment_author'] = $user->display_name; + $comment_data['comment_author_email'] = $user->user_email; + + return $comment_data; + } + /** * Assignees order to corresponding user organization when order is created. * @@ -94,6 +105,8 @@ class Wiaas_Order { $data = self::_append_commercial_lead_info($data, $order, $request); $data = self::_append_wiaas_order_details($data, $order, $request); + + $data = self::_append_order_comments($data, $order, $request); $response->set_data($data); @@ -229,6 +242,34 @@ class Wiaas_Order { return $data; } + + /** Append order comments if single order is requested + * @param $data + * @param $order + * @param $request + */ + private static function _append_order_comments($data, $order, $request) { + + if (isset($request['id'])) { + $current_user = wp_get_current_user(); + + $comments = $order->get_customer_order_notes(); + + $data['comments'] = array(); + + foreach ($comments as $comment) { + $data['comments'][] = array( + 'id' => $comment->comment_ID, + 'content' => $comment->comment_content, + 'username' => $comment->comment_author, + 'date' => $comment->comment_date, + 'is_owner' => $comment->comment_author === $current_user->display_name, + ); + } + } + + return $data; + } } Wiaas_Order::init(); diff --git a/frontend/src/actions/orders/processActions.js b/frontend/src/actions/orders/processActions.js index e45d409..87bef48 100644 --- a/frontend/src/actions/orders/processActions.js +++ b/frontend/src/actions/orders/processActions.js @@ -62,27 +62,16 @@ const sendComment = () => ({ type: SEND_ORDER_COMMENT }) -export const addComment = (idOrder, newComment, existingComments) => { +export const addComment = (idOrder, newComment) => { return dispatch => { dispatch(sendComment()); - //TODO: get real user name and store in comment object - const newCommentObject = { - comment : newComment, - date : moment().format("Do MMM, YY"), - username: localStorage.getItem('username') || '-', - } - const concatenatedComments = (existingComments) ? existingComments.concat(newCommentObject) : [newCommentObject]; return htmlClient.fetch({ - url: `${API_SERVER}/wp-json/wc/v2/orders/${idOrder}`, - method: 'put', + url: `${API_SERVER}/wp-json/wc/v2/orders/${idOrder}/notes`, + method: 'post', data: { - meta_data: [ - { - key:'comments', - value: JSON.stringify(concatenatedComments), - } - ] + note : newComment || 'Test comment', + customer_note: true, } }) .then(response => { diff --git a/frontend/src/containers/orders/components/OrderComments.jsx b/frontend/src/containers/orders/components/OrderComments.jsx index 9717e42..51a7588 100644 --- a/frontend/src/containers/orders/components/OrderComments.jsx +++ b/frontend/src/containers/orders/components/OrderComments.jsx @@ -18,19 +18,19 @@ class OrderComments extends Component { } addNewComment(){ - this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment, this.props.orderComments)); + this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment)); } onEditorChange(newComment){ this.setState({newComment}); } - getOffset(username){ - return (username === localStorage.getItem('username')) ? 6 : 0; + getOffset(isOwner){ + return isOwner ? 6 : 0; } - getClassByOwner(username){ - return (username === localStorage.getItem('username')) ? 'mine' : ''; + getClassByOwner(isOwner){ + return isOwner ? 'mine' : ''; } render() { @@ -46,9 +46,9 @@ class OrderComments extends Component { orderComments && orderComments.map((orderComment, index) => - -
-
{orderComment.username} - {orderComment.date}
+ +
+
{orderComment.username} - {orderComment.dateCreated}
diff --git a/frontend/src/containers/orders/style/ProcessContainer.scss b/frontend/src/containers/orders/style/ProcessContainer.scss index 225f339..3e4d82e 100644 --- a/frontend/src/containers/orders/style/ProcessContainer.scss +++ b/frontend/src/containers/orders/style/ProcessContainer.scss @@ -26,6 +26,7 @@ $link-line-height: 1.5rem; .completed { border-left: $border-width $production-status-color solid; + background: $production-status-color; } .end-of-life { @@ -131,7 +132,7 @@ $link-line-height: 1.5rem; background: $canceled-status-color; } -.production { +.completed { background: $production-status-color; } diff --git a/frontend/src/helpers/OrderHelper.js b/frontend/src/helpers/OrderHelper.js index 202f4a6..e9f50ff 100644 --- a/frontend/src/helpers/OrderHelper.js +++ b/frontend/src/helpers/OrderHelper.js @@ -9,13 +9,6 @@ function formatAddress(addressObject) { return `${addressObject.address_1}, ${addressObject.city}, ${addressObject.country}, ${addressObject.postcode}`; } -function extractComments(metaDataArray){ - const commentsObject = metaDataArray.find(metaDataElement => { - return metaDataElement.key === "comments"; - }); - return commentsObject ? JSON.parse(commentsObject.value) : []; -} - export const fromWCOrder = (WCOrder) => { let processInfo = Object.assign({},WCOrder['delivery-process']); if (WCOrder['delivery-process']){ @@ -59,7 +52,13 @@ export const fromWCOrder = (WCOrder) => { }; }), process: processInfo, - comments: extractComments(WCOrder.meta_data), + comments: WCOrder.comments ? WCOrder.comments.map(comment => ({ + id: comment.id, + comment: comment.content, + username: comment.username, + dateCreated: formatDate(comment.date), + isOwner: comment['is_owner'] + })) : [], deliveryAddress: formatAddress(WCOrder.shipping), customer: WCOrder.customer, commercialLead: WCOrder['commercial_lead'] From 906725f5c516635ced7d5d9df1813052bd1be2e0 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:19:05 +0200 Subject: [PATCH 34/63] comment function used for testing --- .../includes/api/class-wiaas-rest-delivery-process-api.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index c5773dc..17f75d3 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -37,6 +37,10 @@ class Wiass_REST_Delivery_Process_API { 'callback' => array(__CLASS__, 'get_customer_acceptance'), ) ); + /* + + Used for some fast test and check + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( 'methods' => 'GET', 'callback' => array(__CLASS__, 'get_form_entry'), @@ -48,6 +52,8 @@ class Wiass_REST_Delivery_Process_API { 'callback' => array(__CLASS__, 'update_entry'), ) ); + */ + register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'POST', From 1e2373090cd0d826c082c0b11d91da8de5c892cc Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:19:24 +0200 Subject: [PATCH 35/63] change comments handling --- frontend/src/containers/orders/components/OrderComments.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/containers/orders/components/OrderComments.jsx b/frontend/src/containers/orders/components/OrderComments.jsx index 51a7588..7c781c4 100644 --- a/frontend/src/containers/orders/components/OrderComments.jsx +++ b/frontend/src/containers/orders/components/OrderComments.jsx @@ -18,7 +18,7 @@ class OrderComments extends Component { } addNewComment(){ - this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment)); + this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment, this.props.orderComments)); } onEditorChange(newComment){ From fed5ecafc4b19a920cefa16da915ab2095198d3c Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 15 Aug 2018 22:20:02 +0200 Subject: [PATCH 36/63] remove hardcoded values and change comment handling --- frontend/src/helpers/OrderHelper.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontend/src/helpers/OrderHelper.js b/frontend/src/helpers/OrderHelper.js index e9f50ff..f69b832 100644 --- a/frontend/src/helpers/OrderHelper.js +++ b/frontend/src/helpers/OrderHelper.js @@ -9,6 +9,13 @@ function formatAddress(addressObject) { return `${addressObject.address_1}, ${addressObject.city}, ${addressObject.country}, ${addressObject.postcode}`; } +function extractComments(metaDataArray){ + const commentsObject = metaDataArray.find(metaDataElement => { + return metaDataElement.key === "comments"; + }); + return commentsObject ? JSON.parse(commentsObject.value) : []; +} + export const fromWCOrder = (WCOrder) => { let processInfo = Object.assign({},WCOrder['delivery-process']); if (WCOrder['delivery-process']){ From b18a87790a87f049a8eb9a0a78191723c21d933e Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 16 Aug 2018 10:35:55 +0200 Subject: [PATCH 37/63] check comment owner by username --- .../src/containers/orders/components/OrderComments.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/containers/orders/components/OrderComments.jsx b/frontend/src/containers/orders/components/OrderComments.jsx index 7c781c4..8ad885a 100644 --- a/frontend/src/containers/orders/components/OrderComments.jsx +++ b/frontend/src/containers/orders/components/OrderComments.jsx @@ -25,12 +25,12 @@ class OrderComments extends Component { this.setState({newComment}); } - getOffset(isOwner){ - return isOwner ? 6 : 0; + getOffset(username){ + return (username === localStorage.getItem('username')) ? 6 : 0; } - getClassByOwner(isOwner){ - return isOwner ? 'mine' : ''; + getClassByOwner(username){ + return (username === localStorage.getItem('username')) ? 'mine' : ''; } render() { From ba99d85c857d70bbdd1cf903f6eefdef1253fe1a Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sat, 18 Aug 2018 16:20:05 +0200 Subject: [PATCH 38/63] allow api access only to logged in users --- .../includes/api/class-wiaas-rest-delivery-process-api.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 17f75d3..1b6601a 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -41,9 +41,9 @@ class Wiass_REST_Delivery_Process_API { Used for some fast test and check - register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( + register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)/field/(?P\d+(.\d+)?)', array( 'methods' => 'GET', - 'callback' => array(__CLASS__, 'get_form_entry'), + 'callback' => array(__CLASS__, 'get_field_value_from_entry'), ) ); //Used for testing @@ -54,7 +54,6 @@ class Wiass_REST_Delivery_Process_API { */ - register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'POST', 'callback' => array(__CLASS__, 'submit_customer_acceptance'), From ed23a872e9ac3ce7a60eb0eb4a092f3643f66d2f Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 20 Aug 2018 12:52:49 +0200 Subject: [PATCH 39/63] install guzzle --- backend/composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/composer.lock b/backend/composer.lock index f58dd1a..8436e1f 100644 --- a/backend/composer.lock +++ b/backend/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "302f569929ecdaf4d349b0bf764de74c", + "content-hash": "5436495873974fe1e5c0c8fd71cc83d3", "packages": [ { "name": "3rdparty/gravityflow", From f33da62d75f743da696f0369d22d1f082c9ec1d7 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sun, 26 Aug 2018 19:41:51 +0200 Subject: [PATCH 40/63] fix merge --- frontend/src/helpers/OrderHelper.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/frontend/src/helpers/OrderHelper.js b/frontend/src/helpers/OrderHelper.js index f69b832..e9f50ff 100644 --- a/frontend/src/helpers/OrderHelper.js +++ b/frontend/src/helpers/OrderHelper.js @@ -9,13 +9,6 @@ function formatAddress(addressObject) { return `${addressObject.address_1}, ${addressObject.city}, ${addressObject.country}, ${addressObject.postcode}`; } -function extractComments(metaDataArray){ - const commentsObject = metaDataArray.find(metaDataElement => { - return metaDataElement.key === "comments"; - }); - return commentsObject ? JSON.parse(commentsObject.value) : []; -} - export const fromWCOrder = (WCOrder) => { let processInfo = Object.assign({},WCOrder['delivery-process']); if (WCOrder['delivery-process']){ From 3419f2bddc952e32aef1d5af0f8e2a88033cfcef Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sun, 26 Aug 2018 20:26:30 +0200 Subject: [PATCH 41/63] use Orchestration API to complete GF step --- .../api/class-wiaas-rest-delivery-process-api.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 1b6601a..d49c407 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -175,11 +175,11 @@ class Wiass_REST_Delivery_Process_API { $entry[self::DECLINE_REASON_FIELD_ID] = $reason; $entry[self::ACCEPTANCE_STATUS_FIELD_ID] = $status; - //submit step - $entry['workflow_step'] = 2; - $entry['workflow_step_status_1'] = 'complete'; - $entry['workflow_step_status_2'] = 'pending'; - $entry['workflow_timestamp'] = time(); + + $gf_api = new Gravity_Flow_API($entry['form_id']); + $current_step = $gf_api->get_current_step($entry); + $current_step->update_step_status('complete'); + $gf_api->send_to_step($entry, $current_step->get_id() + 1); if (GFAPI::update_entry( $entry )){ if ($installation_declined){ From 1368f1b6aeeaaa973db68c47ef6cf8b9f2722a8b Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 27 Aug 2018 17:54:05 +0200 Subject: [PATCH 42/63] improve code quality --- .../class-wiaas-rest-delivery-process-api.php | 93 ++++++++++--------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index d49c407..36230dc 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -35,6 +35,7 @@ class Wiass_REST_Delivery_Process_API { register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'GET', 'callback' => array(__CLASS__, 'get_customer_acceptance'), + 'permission_callback' => 'is_user_logged_in' ) ); /* @@ -57,11 +58,13 @@ class Wiass_REST_Delivery_Process_API { register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'POST', 'callback' => array(__CLASS__, 'submit_customer_acceptance'), + 'permission_callback' => 'is_user_logged_in' ) ); register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)/upload-file' , array( 'methods' => 'POST', 'callback' => array(__CLASS__, 'upload_file'), + 'permission_callback' => 'is_user_logged_in' ) ); } @@ -112,10 +115,6 @@ class Wiass_REST_Delivery_Process_API { } public static function get_customer_acceptance(WP_REST_Request $request){ - if (!is_user_logged_in()){ - return self::generate_error('You don\'t have permission to read this entry', 401); - } - $entry = GFAPI::get_entry($request['entry_id']); if (is_wp_error($entry)){ return self::generate_error('Customer acceptance entry not found', 404); @@ -125,10 +124,18 @@ class Wiass_REST_Delivery_Process_API { $uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]); foreach($uploaded_files as $file_url){ - $info = pathinfo($file_url); + //example of decoded url : + //http://localhost/wp/index.php?gf-download=2018/08/rokovi-1535378841.docx&form-id=1&field-id=12&hash=1be6c30f0eeff93563b352d15fe459d5ded12ee06c2c8f36fed66b42dedf2534 + + $decoded_url = urldecode($file_url); + $url_parts = explode('?', $decoded_url); + $file_name_base_parts = explode('&', $url_parts[1]); + $file_name_parts = explode('/', $file_name_base_parts[0]); + $file_name_with_extension_parts = explode('.', $file_name_parts[2]); + $acceptance_documents_entry = array( - 'name' => $info['filename'], - 'extension' => $info['extension'], + 'name' => $file_name_with_extension_parts[0], + 'extension' => $file_name_with_extension_parts[1], 'url' => $file_url ); array_push($acceptance_documents, $acceptance_documents_entry); @@ -162,34 +169,50 @@ class Wiass_REST_Delivery_Process_API { $status = $request['actionType']; $reason = $request['declineReason']; - $installation_declined = ($status === self::DECLINE_STATUS_LABEL); - if (!in_array($status, self::ACCEPTABLE_STATUS)){ return self::generate_wiaas_response('ACCEPTANCE_STATUS_MISSING', 'error'); } + $installation_declined = ($status === self::DECLINE_STATUS_LABEL); + + $uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]); + if ($installation_declined && $reason === ''){ return self::generate_wiaas_response('DECLINE_REASON_EMPTY', 'error'); } + if (!$installation_declined && (count($uploaded_files)===0)){ + return self::generate_wiaas_response('ACCEPTANCE_NOT_UPLOADED', 'error'); + } + $entry[self::DECLINE_REASON_FIELD_ID] = $reason; $entry[self::ACCEPTANCE_STATUS_FIELD_ID] = $status; - - $gf_api = new Gravity_Flow_API($entry['form_id']); - $current_step = $gf_api->get_current_step($entry); - $current_step->update_step_status('complete'); - $gf_api->send_to_step($entry, $current_step->get_id() + 1); - - if (GFAPI::update_entry( $entry )){ - if ($installation_declined){ - return self::generate_wiaas_response('INSTALLATION_DECLINED', 'success'); - }else{ - return self::generate_wiaas_response('INSTALLATION_ACCEPTED', 'success'); - } - }else{ + if (!GFAPI::update_entry( $entry )){ return self::generate_wiaas_response('INTERNAL_SERVER_ERROR', 'error'); } + + $gf_api = new Gravity_Flow_API($entry['form_id']); + $current_step = $gf_api->get_current_step($entry); + if ( $current_step ) { + $current_step->purge_assignees(); + $current_step->update_step_status( 'complete' ); + } + $entry_id = $entry['id']; + $new_step_id = $current_step->get_id() + 1; + $new_step = $gf_api->get_step( $new_step_id, $entry ); + $feedback = sprintf( esc_html__( 'Sent to step: %s', 'gravityflow' ), $new_step->get_name() ); + $gf_api->add_timeline_note( $entry_id, $feedback ); + $gf_api->log_activity( 'workflow', 'sent_to_step', $gf_api->form_id, $entry_id, $step_id ); + gform_update_meta( $entry_id, 'workflow_final_status', 'pending' ); + $new_step->start(); + $gf_api->process_workflow( $entry_id ); + + + if ($installation_declined){ + return self::generate_wiaas_response('INSTALLATION_DECLINED', 'success'); + } + return self::generate_wiaas_response('INSTALLATION_ACCEPTED', 'success'); } public static function upload_file(WP_REST_Request $request){ @@ -253,13 +276,14 @@ class Wiass_REST_Delivery_Process_API { } $file_url = self::BASE_NAME . $relative_path . $new_file_name; - + $url_for_download = $upload_file_field->get_download_url($file_url); + $uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]); if ($uploaded_files === NULL){ $uploaded_files = []; } - array_push($uploaded_files, $file_url); + array_push($uploaded_files, $url_for_download); $entry[self::UPLOADED_FILES_FIELD_ID] = json_encode($uploaded_files); @@ -270,27 +294,6 @@ class Wiass_REST_Delivery_Process_API { return self::generate_wiaas_response('NOT_UPLOADED', 'error'); } - //Used for testing - public static function get_form_entry($data) { - return GFAPI::get_entry($data['entry_id']); - } - - - //Used for testing - public static function update_entry($data){ - $entry = GFAPI::get_entry($data['entry_id']); - $new_values = json_decode($data->get_body()); - if ($new_values === NULL) { - return new WP_REST_Response (); - } - $keys = get_object_vars($new_values); - foreach($keys as $key => $value){ - $entry[$key] = $value; - } - $result = GFAPI::update_entry( $entry ); - return new WP_REST_Response ($result); - } - //Helper function private static function generate_error($message, $code = 500){ $error = array( From 769c8c01e8e26a99395ec363bf46eff884fa30dc Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 27 Aug 2018 18:08:22 +0200 Subject: [PATCH 43/63] change tests accoring to changes in delivery process api --- .../test-wiaas-rest-delivery-process-api.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php index ac6c667..7f48145 100644 --- a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php @@ -109,7 +109,7 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { $this->assertEquals($response->get_status(), 401); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to read this entry'); + $this->assertEquals($error_data->get_error_message(), 'Sorry, you are not allowed to do that.'); } /** @@ -161,7 +161,7 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { $this->assertArrayHasKey('url', $uploaded_file); $this->assertEquals($uploaded_file['name'], 'file1'); $this->assertEquals($uploaded_file['extension'], 'docx'); - $this->assertEquals($uploaded_file['url'], 'http://path/to/file1.docx'); + $this->assertEquals($uploaded_file['url'], 'http://localhost/wp/index.php?gf-download=2018%2F08%2Ffile1.docx&form-id=1&field-id=12&hash=1be6c30f0eeff93563b352d15fe459d5ded12ee06c2c8f36fed66b42dedf2534'); $this->assertEquals($response_data['status'], 1); //1 means accept @@ -183,7 +183,7 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { $this->assertEquals($response->get_status(), 401); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to update this entry'); + $this->assertEquals($error_data->get_error_message(), 'Sorry, you are not allowed to do that.'); } /** @@ -339,7 +339,7 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { $this->assertEquals($response->get_status(), 401); $error_data = $response->as_error(); - $this->assertEquals($error_data->get_error_message(), 'You don\'t have permission to read this entry'); + $this->assertEquals($error_data->get_error_message(), 'Sorry, you are not allowed to do that.'); } /** @@ -507,7 +507,7 @@ class Wiass_REST_Delivery_Process_Api_Test extends Wiaas_Unit_Test_Case { //this part is needed since form submit does not store files for some reason, probably files should be sent some other way $entry = GFAPI::get_entries($customer_acceptance_form_id)[0]; - $entry[$files_uploaded_field_id] = json_encode(['http://path/to/file1.docx']); + $entry[$files_uploaded_field_id] = json_encode(['http://localhost/wp/index.php?gf-download=2018%2F08%2Ffile1.docx&form-id=1&field-id=12&hash=1be6c30f0eeff93563b352d15fe459d5ded12ee06c2c8f36fed66b42dedf2534']); $entry['workflow_step'] = 1; $entry['workflow_step_status_1'] = 'pending'; $entry['workflow_step_status_2'] = false; From 9958d4118d3e79bb6adb4b2271c2730157b1449a Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 27 Aug 2018 18:42:41 +0200 Subject: [PATCH 44/63] Create link to customer acceptance documents --- .../orders/components/process/CustomerAcceptance.jsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx index 2104725..592e7af 100644 --- a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx +++ b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx @@ -147,9 +147,8 @@ class CustomerAcceptance extends Component {
{ customerAcceptance.documents.map((document, index) =>
- {this.downloadDocument(document)}}> - {document.name} ({document.extension}) + + {document.name} ({document.extension}) {document.validation}
From 9f653bb92034c4edbb773d9a74a766b25adad52a Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 27 Aug 2018 19:05:59 +0200 Subject: [PATCH 45/63] improve code quality --- .../class-wiaas-rest-delivery-process-api.php | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 36230dc..2bb499b 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -38,23 +38,6 @@ class Wiass_REST_Delivery_Process_API { 'permission_callback' => 'is_user_logged_in' ) ); - /* - - Used for some fast test and check - - register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)/field/(?P\d+(.\d+)?)', array( - 'methods' => 'GET', - 'callback' => array(__CLASS__, 'get_field_value_from_entry'), - ) ); - - //Used for testing - register_rest_route( self::$namespace, 'gravity-form-entry/(?P\d+)', array( - 'methods' => 'PUT', - 'callback' => array(__CLASS__, 'update_entry'), - ) ); - - */ - register_rest_route( self::$namespace, 'customer-acceptance/(?P\d+)', array( 'methods' => 'POST', 'callback' => array(__CLASS__, 'submit_customer_acceptance'), @@ -157,10 +140,6 @@ class Wiass_REST_Delivery_Process_API { } public static function submit_customer_acceptance(WP_REST_Request $request){ - if (!is_user_logged_in()){ - return self::generate_error('You don\'t have permission to update this entry', 401); - } - $entry = GFAPI::get_entry($request['entry_id']); if (is_wp_error($entry)){ return self::generate_error('Customer acceptance entry not found', 404); @@ -216,10 +195,6 @@ class Wiass_REST_Delivery_Process_API { } public static function upload_file(WP_REST_Request $request){ - if (!is_user_logged_in()){ - return self::generate_error('You don\'t have permission to read this entry', 401); - } - $files = $request->get_file_params(); if (!$files[self::FILE_KEY_NAME]){ return self::generate_wiaas_response('NO_FILES_UPLOADED', 'error'); @@ -319,6 +294,4 @@ class Wiass_REST_Delivery_Process_API { return new WP_REST_Response($response); } - - } \ No newline at end of file From 2d24f826988defdbad8ef00eca591ac0d7c53910 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 27 Aug 2018 23:30:25 +0200 Subject: [PATCH 46/63] do not submit custommer acceptance if already submitted --- .../includes/api/class-wiaas-rest-delivery-process-api.php | 6 ++++++ frontend/src/constants/ordersConstants.js | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php index 2bb499b..e575199 100644 --- a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -13,6 +13,7 @@ class Wiass_REST_Delivery_Process_API { const DECLINE_REASON_FIELD_ID = 10; const UPLOADED_FILES_FIELD_ID = 12; + const USER_INPUT_STEP_NAME = 'Upload acceptance file'; const ACCEPT_STATUS_LABEL = 'accept'; const DECLINE_STATUS_LABEL = 'decline'; @@ -171,8 +172,13 @@ class Wiass_REST_Delivery_Process_API { return self::generate_wiaas_response('INTERNAL_SERVER_ERROR', 'error'); } + //Check if step is already completed, to not submit again $gf_api = new Gravity_Flow_API($entry['form_id']); $current_step = $gf_api->get_current_step($entry); + if ($current_step->get_name() !== self::USER_INPUT_STEP_NAME){ + return self::generate_wiaas_response('ACCEPTANCE_STATUS_UPDATED', 'success'); + } + if ( $current_step ) { $current_step->purge_assignees(); $current_step->update_step_status( 'complete' ); diff --git a/frontend/src/constants/ordersConstants.js b/frontend/src/constants/ordersConstants.js index 76c8c2c..b2d9b2e 100644 --- a/frontend/src/constants/ordersConstants.js +++ b/frontend/src/constants/ordersConstants.js @@ -85,7 +85,8 @@ export const orderMessages = { NO_FILES_UPLOADED: 'You need to upload the acceptance document', INTERNAL_SERVER_ERROR: 'Error occured. Please try again', - ACCEPTANCE_STATUS_MISSING: 'Acceptance action not selected' + ACCEPTANCE_STATUS_MISSING: 'Acceptance action not selected', + ACCEPTANCE_STATUS_UPDATED: 'Acceptance status updated' }; From 684c06df557782636f6071752594dc6f1d75c3b7 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 27 Aug 2018 23:36:24 +0200 Subject: [PATCH 47/63] remove guzzle, it's not used --- backend/composer.json | 3 +- backend/composer.lock | 233 +----------------------------------------- 2 files changed, 2 insertions(+), 234 deletions(-) diff --git a/backend/composer.json b/backend/composer.json index e3820f0..1fe0274 100644 --- a/backend/composer.json +++ b/backend/composer.json @@ -67,8 +67,7 @@ "3rdparty/woocommerce-product-bundles": "*" }, "require-dev": { - "vlucas/phpdotenv": "2.5.0", - "guzzlehttp/guzzle": "6.3.3" + "vlucas/phpdotenv": "2.5.0" }, "extra": { "installer-paths": { diff --git a/backend/composer.lock b/backend/composer.lock index 8436e1f..527c55b 100644 --- a/backend/composer.lock +++ b/backend/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "5436495873974fe1e5c0c8fd71cc83d3", + "content-hash": "302f569929ecdaf4d349b0bf764de74c", "packages": [ { "name": "3rdparty/gravityflow", @@ -630,237 +630,6 @@ } ], "packages-dev": [ - { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2018-04-22T15:46:56+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2017-03-20T17:10:46+00:00" - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" - }, { "name": "vlucas/phpdotenv", "version": "v2.5.0", From b99a0cb8564cafc61addb10ee29018df538b675f Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 29 Aug 2018 09:59:55 +0200 Subject: [PATCH 48/63] fix comment style --- .../src/containers/orders/components/OrderComments.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/containers/orders/components/OrderComments.jsx b/frontend/src/containers/orders/components/OrderComments.jsx index 8ad885a..0c43852 100644 --- a/frontend/src/containers/orders/components/OrderComments.jsx +++ b/frontend/src/containers/orders/components/OrderComments.jsx @@ -25,12 +25,12 @@ class OrderComments extends Component { this.setState({newComment}); } - getOffset(username){ - return (username === localStorage.getItem('username')) ? 6 : 0; + getOffset(isOwner){ + return (isOwner) ? 6 : 0; } - getClassByOwner(username){ - return (username === localStorage.getItem('username')) ? 'mine' : ''; + getClassByOwner(isOwner){ + return (isOwner) ? 'mine' : ''; } render() { From a8e3522ec5d0fb1918fb9c27f574bee0ae7494c0 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 29 Aug 2018 10:44:19 +0200 Subject: [PATCH 49/63] open document in new tab --- .../containers/orders/components/process/CustomerAcceptance.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx index 592e7af..4d12479 100644 --- a/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx +++ b/frontend/src/containers/orders/components/process/CustomerAcceptance.jsx @@ -148,7 +148,7 @@ class CustomerAcceptance extends Component { { customerAcceptance.documents.map((document, index) =>
- {document.name} ({document.extension}) + {document.name} ({document.extension}) {document.validation}
From 2cb32dca31c1159cff9655ea3eefdf6b8226a2b0 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Wed, 29 Aug 2018 10:52:13 +0200 Subject: [PATCH 50/63] temporarily disable fetching documents and validation comments --- .../orders/components/process/ValidateQuestionnaire.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/containers/orders/components/process/ValidateQuestionnaire.jsx b/frontend/src/containers/orders/components/process/ValidateQuestionnaire.jsx index 9e27ab5..08cb7b5 100644 --- a/frontend/src/containers/orders/components/process/ValidateQuestionnaire.jsx +++ b/frontend/src/containers/orders/components/process/ValidateQuestionnaire.jsx @@ -8,8 +8,8 @@ class ValidateQuestionnaire extends Component { componentDidMount(){ const {idOrder, idProcessStep} = this.props.step; - this.props.dispatch(fetchCustomerDocuments(idOrder, 'orderQuestionaire')); - this.props.dispatch(fetchValidationComments(idOrder, idProcessStep, 'invalidQuestionnaireComment')); + //this.props.dispatch(fetchCustomerDocuments(idOrder, 'orderQuestionaire')); + //this.props.dispatch(fetchValidationComments(idOrder, idProcessStep, 'invalidQuestionnaireComment')); } findById(orderPackage, idOrderPackagePair){ From 057a99b8f5ffbc09e97dc361143f1469285b12d6 Mon Sep 17 00:00:00 2001 From: Almira Krdzic Date: Wed, 29 Aug 2018 11:37:24 +0200 Subject: [PATCH 51/63] Show additional info on workflow inbox page --- .../includes/class-wiaas-delivery-process.php | 16 ++++++++++++++++ .../class-wiaas-delivery-process-step.php | 1 + 2 files changed, 17 insertions(+) diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php index c8a0a8a..2492afc 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php @@ -25,8 +25,14 @@ class Wiaas_Delivery_Process { add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_process_step'), 5, 3 ); add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_order'), 10, 3 ); + + add_filter('gravityflow_inbox_submitter_name',array(__CLASS__, 'display_step_name_in_inbox'), 10, 3); } + public static function display_step_name_in_inbox($name, $entry, $form) { + return $entry['wiaas_delivery_step_name']; + } + /** * Registers our Delivery Process Step Type as available Gravity Flow Step Type */ @@ -159,6 +165,16 @@ class Wiaas_Delivery_Process { ), ); + $entry_meta[ 'wiaas_delivery_step_name' ] = array( + 'label' => 'Wiaas Delivery Step name', + 'is_numeric' => false, + 'update_entry_meta_callback' => null, + 'is_default_column' => false, // this column will be displayed by default on the entry list + 'filter' => array( + 'operators' => array( 'is' ), + ), + ); + return $entry_meta; } diff --git a/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php b/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php index e4497c7..8c5b478 100644 --- a/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php +++ b/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php @@ -100,6 +100,7 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { 'form_id' => $this->target_form_id, 'wiaas_delivery_process_id' => $this->get_entry_id(), 'wiaas_delivery_order_id' => $entry['wiaas_delivery_order_id'], + 'wiaas_delivery_step_name' => $this->get_name(), ); $customer_id_value = null; From 23794a8f1c7d6d36624ecb73dee1d977084c6e73 Mon Sep 17 00:00:00 2001 From: Almira Krdzic Date: Wed, 29 Aug 2018 13:02:09 +0200 Subject: [PATCH 52/63] Handle display for workflow inbox page --- .../includes/class-wiaas-delivery-process.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php index 2492afc..34b58c3 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php @@ -26,9 +26,26 @@ class Wiaas_Delivery_Process { add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_order'), 10, 3 ); - add_filter('gravityflow_inbox_submitter_name',array(__CLASS__, 'display_step_name_in_inbox'), 10, 3); + // Some temporary functions to make inbox page prettier + add_filter('gravityflow_inbox_submitter_name', array(__CLASS__, 'display_step_name_in_inbox'), 10, 3); + add_filter('gravityflow_approve_label_workflow_detail', array(__CLASS__, 'approval_step_approval_label'), 10, 2); + add_filter('gravityflow_reject_label_workflow_detail', array(__CLASS__, 'approval_step_reject_label'), 10, 2); } + public static function approval_step_approval_label($label, $step) { + if ($step->get_name() === 'Complete step') { + return esc_html__( 'Complete step', 'wiaas' ); + } + return $label; + } + + public static function approval_step_reject_label($label, $step) { + if ($step->get_name() === 'Complete step') { + return esc_html__( 'Cancel', 'wiaas' ); + } + return $label; + } + public static function display_step_name_in_inbox($name, $entry, $form) { return $entry['wiaas_delivery_step_name']; } From 4ee23fba3fc773de3d5cd8a23ed14ca6ac5af7d3 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 30 Aug 2018 23:08:59 +0200 Subject: [PATCH 53/63] add volume mapping to preserve database changes --- database/.gitignore | 1 + docker-compose.yml | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 database/.gitignore diff --git a/database/.gitignore b/database/.gitignore new file mode 100644 index 0000000..7d04233 --- /dev/null +++ b/database/.gitignore @@ -0,0 +1 @@ +volume/* \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 0d16029..38b809c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -54,3 +54,5 @@ services: - MYSQL_PASSWORD ports: - '23306:3306' + volumes: + - ./database/volume/:/var/lib/mysql \ No newline at end of file From 3f1e63cb44219f022aa04bb97341da78212880f0 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 30 Aug 2018 23:33:31 +0200 Subject: [PATCH 54/63] set permissions to allow upload --- backend.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend.dockerfile b/backend.dockerfile index 285710c..4987db7 100644 --- a/backend.dockerfile +++ b/backend.dockerfile @@ -63,6 +63,6 @@ RUN ln -s ../html api COPY docker/php/.htaccess /var/www/html/ -RUN chown -R www-data:www-data /var/www/html +RUN chown -R www-data:www-data /var/www/html && chmod 750 -R /var/www/html/app/uploads CMD /init-scripts/setup.sh From df816f0dd76953bd2bb3b236d1ca8b80df2c6c85 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Fri, 31 Aug 2018 00:23:18 +0200 Subject: [PATCH 55/63] add missing plugin activation --- docker/php/setup.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docker/php/setup.sh b/docker/php/setup.sh index d4d3cdf..eb6f82e 100644 --- a/docker/php/setup.sh +++ b/docker/php/setup.sh @@ -13,14 +13,16 @@ wp core update-db --allow-root # Activate plugins in desired order # (if plugin is already activated command will do nothing) +wp plugin activate woocommerce --allow-root +wp plugin activate woocommerce-product-bundles --allow-root wp plugin activate woocommerce-jetpack --allow-root -wp plugin activate groups --allow-root wp plugin activate jwt-authentication-for-wp-rest-api --allow-root -wp plugin activate wiaas --allow-root wp plugin activate gravityforms --allow-root wp plugin activate gravityflow --allow-root wp plugin activate capability-manager-enhanced --allow-root +wp plugin activate groups --allow-root wp plugin activate wp-user-groups --allow-root +wp plugin activate wiaas --allow-root # Execute database update for updated plugins # (if no changes detected command will do nothing) From bc15706f07be4da3d8f50327c3ff12aa9d62ad48 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Fri, 31 Aug 2018 17:35:36 +0200 Subject: [PATCH 56/63] allow customer to add comments --- .../wiaas/includes/db-updates/wiaas-db-update-functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php index 3ce2174..341ffe2 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php +++ b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php @@ -82,7 +82,8 @@ function wiaas_db_update_setup_customer_capabilities() { $customer_role = get_role('customer'); $customer_role->add_cap('read_private_shop_orders'); - $customer_role->add_cap('read_shop_order'); + $customer_role->add_cap('read_shop_order'); + $customer_role->add_cap('publish_shop_order'); } function wiaas_db_update_add_customer_read_permission() { From 513401c9db5d03dabbd0f39452a8c6041d3f1131 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Fri, 31 Aug 2018 18:35:48 +0200 Subject: [PATCH 57/63] refactor code --- .../app/plugins/wiaas/includes/class-wiaas-db-update.php | 1 - .../includes/db-updates/wiaas-db-update-functions.php | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php b/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php index 9121bb4..97e8023 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php @@ -9,7 +9,6 @@ class Wiaas_DB_Update { '20180801222206' => 'wiaas_db_update_setup_gravity', '20180802222206' => 'wiaas_db_update_add_delivery_process_forms', '20180807222206' => 'wiaas_db_update_setup_customer_capabilities', - '20180809134511' => 'wiaas_db_update_add_customer_read_permission', '20180811134511' => 'wiaas_db_update_enable_orders_access_management', '20180813134511' => 'wiaas_db_update_enable_order_numbers', '20180826153509' => 'wiaas_create_broker_access_group' diff --git a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php index 341ffe2..03b70b1 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php +++ b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php @@ -82,13 +82,10 @@ function wiaas_db_update_setup_customer_capabilities() { $customer_role = get_role('customer'); $customer_role->add_cap('read_private_shop_orders'); + $customer_role->add_cap('read_private_products'); $customer_role->add_cap('read_shop_order'); $customer_role->add_cap('publish_shop_order'); -} - -function wiaas_db_update_add_customer_read_permission() { - $role = get_role( 'customer' ); - $role->add_cap( 'read_private_products' ); + } function wiaas_db_update_enable_orders_access_management() { From d90c12406b30c0eb19dc247bb37f7ceb737200c8 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Fri, 31 Aug 2018 20:39:04 +0200 Subject: [PATCH 58/63] fix typo --- .../wiaas/includes/db-updates/wiaas-db-update-functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php index 03b70b1..86c9f30 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php +++ b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php @@ -84,7 +84,7 @@ function wiaas_db_update_setup_customer_capabilities() { $customer_role->add_cap('read_private_shop_orders'); $customer_role->add_cap('read_private_products'); $customer_role->add_cap('read_shop_order'); - $customer_role->add_cap('publish_shop_order'); + $customer_role->add_cap('publish_shop_orders'); } From 06fc46fbc5e8f9d7c029aefe7003ed42ea8996f2 Mon Sep 17 00:00:00 2001 From: Almira Krdzic Date: Mon, 3 Sep 2018 23:22:10 +0200 Subject: [PATCH 59/63] Run database migration as www-data user --- backend.dockerfile | 4 ++-- docker/php/setup.sh | 42 +++++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/backend.dockerfile b/backend.dockerfile index 4987db7..b638aa8 100644 --- a/backend.dockerfile +++ b/backend.dockerfile @@ -35,7 +35,7 @@ ENV WP_LOGGED_IN_SALT ${WP_LOGGED_IN_SALT} ENV WP_NONCE_SALT ${WP_NONCE_SALT} ENV WP_JWT_AUTH_SECRET_KEY ${WP_JWT_AUTH_SECRET_KEY} -RUN apt-get update && apt-get install -y git unzip gnupg mysql-client +RUN apt-get update && apt-get install -y git unzip gnupg mysql-client sudo COPY docker/php/composer.phar /usr/local/bin/composer RUN chmod 755 /usr/local/bin/composer @@ -63,6 +63,6 @@ RUN ln -s ../html api COPY docker/php/.htaccess /var/www/html/ -RUN chown -R www-data:www-data /var/www/html && chmod 750 -R /var/www/html/app/uploads +RUN chown -R www-data:www-data /var/www/html CMD /init-scripts/setup.sh diff --git a/docker/php/setup.sh b/docker/php/setup.sh index eb6f82e..cd47b5b 100644 --- a/docker/php/setup.sh +++ b/docker/php/setup.sh @@ -8,29 +8,29 @@ while ! mysqladmin ping -h"db" --silent; do done echo "Ready...." -# Apply core database updates if needed -wp core update-db --allow-root +sudo -u www-data -s -- < Date: Thu, 6 Sep 2018 13:07:14 +0200 Subject: [PATCH 60/63] Readme spelling fixes --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ac21102..ea212fb 100644 --- a/README.md +++ b/README.md @@ -178,11 +178,11 @@ After any of these actions run: ##### Removing existing plugin -1) remove it from composer.json with: +1) Remove it from composer.json with: composer remove wpackagist-plugin/{plugin_name} -2) remove it from `"activate-plugins"` and `"update-db"` scripts. +2) Remove it from `"activate-plugins"` and `"update-db"` scripts. 3) Then run: @@ -218,7 +218,7 @@ Wiaas exposes WP CLI command which will execute pending db updates for wiaas: wp wiaas update-db -If your feature requires some database updates that can be easiliy executed from wordpress code, then: +If your feature requires some database updates that can be easily executed from wordpress code, then: 1) Place this update to `wiaas/includes/db-updates/wiaas-db-update-functions.php` as a function named `wiaas_db_update_{name}` From 51434c3128c0f27da5ab37f4597948b53ce1d621 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 6 Sep 2018 17:57:43 +0200 Subject: [PATCH 61/63] preserve css files from public dir --- frontend/.gitignore | 2 + .../fonts/fonts.css | 88 ++++++++++ .../fonts/fonts.min.css | 1 + .../tinymce/plugins/codesample/css/prism.css | 138 ++++++++++++++++ .../plugins/visualblocks/css/visualblocks.css | 154 ++++++++++++++++++ .../skins/lightgray/content.inline.min.css | 1 + .../tinymce/skins/lightgray/content.min.css | 1 + .../skins/lightgray/content.mobile.min.css | 1 + .../js/tinymce/skins/lightgray/skin.min.css | 1 + .../skins/lightgray/skin.mobile.min.css | 2 + 10 files changed, 389 insertions(+) create mode 100644 frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.css create mode 100644 frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.min.css create mode 100644 frontend/public/static/js/tinymce/js/tinymce/plugins/codesample/css/prism.css create mode 100644 frontend/public/static/js/tinymce/js/tinymce/plugins/visualblocks/css/visualblocks.css create mode 100644 frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.inline.min.css create mode 100644 frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.min.css create mode 100644 frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.mobile.min.css create mode 100644 frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.min.css create mode 100644 frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.mobile.min.css diff --git a/frontend/.gitignore b/frontend/.gitignore index f7373cf..a1d972b 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -11,6 +11,8 @@ # devBuild *.css +#except css files in public/ dir +!public/**/*.css # misc .DS_Store diff --git a/frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.css b/frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.css new file mode 100644 index 0000000..ff8438b --- /dev/null +++ b/frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.css @@ -0,0 +1,88 @@ +/** Proxima Nova **/ + + + +@font-face { + font-family: 'proxima_nova_altblack'; + src: url('Mark Simonson - Proxima Nova Alt Black-webfont.eot'); + src: url('Mark Simonson - Proxima Nova Alt Black-webfont.eot?#iefix') format('embedded-opentype'), + url('Mark Simonson - Proxima Nova Alt Black-webfont.woff2') format('woff2'), + url('Mark Simonson - Proxima Nova Alt Black-webfont.woff') format('woff'), + url('Mark Simonson - Proxima Nova Alt Black-webfont.ttf') format('truetype'), + url('Mark Simonson - Proxima Nova Alt Black-webfont.svg#proxima_nova_altblack') format('svg'); + font-weight: normal; + font-style: normal; + +} + +@font-face { + font-family: 'proxima_nova_altbold'; + src: url('Mark Simonson - Proxima Nova Alt Bold-webfont.eot'); + src: url('Mark Simonson - Proxima Nova Alt Bold-webfont.eot?#iefix') format('embedded-opentype'), + url('Mark Simonson - Proxima Nova Alt Bold-webfont.woff2') format('woff2'), + url('Mark Simonson - Proxima Nova Alt Bold-webfont.woff') format('woff'), + url('Mark Simonson - Proxima Nova Alt Bold-webfont.ttf') format('truetype'), + url('Mark Simonson - Proxima Nova Alt Bold-webfont.svg#proxima_nova_altbold') format('svg'); + font-weight: normal; + font-style: normal; + +} + +@font-face { + font-family: 'Proxima Nova'; + src: url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot'); + src: url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix') format('embedded-opentype'), + url('Mark Simonson - Proxima Nova Alt Regular-webfont.woff2') format('woff2'), + url('Mark Simonson - Proxima Nova Alt Regular-webfont.woff') format('woff'), + url('Mark Simonson - Proxima Nova Alt Regular-webfont.ttf') format('truetype'), + url('Mark Simonson - Proxima Nova Alt Regular-webfont.svg#proxima_nova_altregular') format('svg'); + font-weight: normal; + font-style: normal; + +} + +/* Generated by Font Squirrel (http://www.fontsquirrel.com) on April 4, 2015 */ + + + +@font-face { + font-family: 'proxima_nova_scosfthin'; + src: url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.eot'); + src: url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.eot?#iefix') format('embedded-opentype'), + url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.woff2') format('woff2'), + url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.woff') format('woff'), + url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.ttf') format('truetype'), + url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.svg#proxima_nova_scosfthin') format('svg'); + font-weight: normal; + font-style: normal; + +} + + + + +@font-face { + font-family: 'proxima_nova_ltsemibold'; + src: url('Mark Simonson - Proxima Nova Semibold-webfont.eot'); + src: url('Mark Simonson - Proxima Nova Semibold-webfont.eot?#iefix') format('embedded-opentype'), + url('Mark Simonson - Proxima Nova Semibold-webfont.woff2') format('woff2'), + url('Mark Simonson - Proxima Nova Semibold-webfont.woff') format('woff'), + url('Mark Simonson - Proxima Nova Semibold-webfont.ttf') format('truetype'), + url('Mark Simonson - Proxima Nova Semibold-webfont.svg#proxima_nova_ltsemibold') format('svg'); + font-weight: normal; + font-style: normal; + +} + +@font-face { + font-family: 'proxima_nova_ltthin'; + src: url('Mark Simonson - Proxima Nova Thin-webfont.eot'); + src: url('Mark Simonson - Proxima Nova Thin-webfont.eot?#iefix') format('embedded-opentype'), + url('Mark Simonson - Proxima Nova Thin-webfont.woff2') format('woff2'), + url('Mark Simonson - Proxima Nova Thin-webfont.woff') format('woff'), + url('Mark Simonson - Proxima Nova Thin-webfont.ttf') format('truetype'), + url('Mark Simonson - Proxima Nova Thin-webfont.svg#proxima_nova_ltthin') format('svg'); + font-weight: normal; + font-style: normal; + +} diff --git a/frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.min.css b/frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.min.css new file mode 100644 index 0000000..a1a23ef --- /dev/null +++ b/frontend/public/static/fonts/proxima-nova-web-fonts-master/fonts/fonts.min.css @@ -0,0 +1 @@ +@font-face{font-family:proxima_nova_altblack;src:url('Mark Simonson - Proxima Nova Alt Black-webfont.eot');src:url('Mark Simonson - Proxima Nova Alt Black-webfont.eot?#iefix') format('embedded-opentype'),url('Mark Simonson - Proxima Nova Alt Black-webfont.woff2') format('woff2'),url('Mark Simonson - Proxima Nova Alt Black-webfont.woff') format('woff'),url('Mark Simonson - Proxima Nova Alt Black-webfont.ttf') format('truetype'),url('Mark Simonson - Proxima Nova Alt Black-webfont.svg#proxima_nova_altblack') format('svg');font-weight:400;font-style:normal}@font-face{font-family:proxima_nova_altbold;src:url('Mark Simonson - Proxima Nova Alt Bold-webfont.eot');src:url('Mark Simonson - Proxima Nova Alt Bold-webfont.eot?#iefix') format('embedded-opentype'),url('Mark Simonson - Proxima Nova Alt Bold-webfont.woff2') format('woff2'),url('Mark Simonson - Proxima Nova Alt Bold-webfont.woff') format('woff'),url('Mark Simonson - Proxima Nova Alt Bold-webfont.ttf') format('truetype'),url('Mark Simonson - Proxima Nova Alt Bold-webfont.svg#proxima_nova_altbold') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Proxima Nova';src:url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot');src:url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix') format('embedded-opentype'),url('Mark Simonson - Proxima Nova Alt Regular-webfont.woff2') format('woff2'),url('Mark Simonson - Proxima Nova Alt Regular-webfont.woff') format('woff'),url('Mark Simonson - Proxima Nova Alt Regular-webfont.ttf') format('truetype'),url('Mark Simonson - Proxima Nova Alt Regular-webfont.svg#proxima_nova_altregular') format('svg');font-weight:400;font-style:normal}@font-face{font-family:proxima_nova_scosfthin;src:url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.eot');src:url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.eot?#iefix') format('embedded-opentype'),url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.woff2') format('woff2'),url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.woff') format('woff'),url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.ttf') format('truetype'),url('Mark Simonson - Proxima Nova ScOsf Thin-webfont.svg#proxima_nova_scosfthin') format('svg');font-weight:400;font-style:normal}@font-face{font-family:proxima_nova_ltsemibold;src:url('Mark Simonson - Proxima Nova Semibold-webfont.eot');src:url('Mark Simonson - Proxima Nova Semibold-webfont.eot?#iefix') format('embedded-opentype'),url('Mark Simonson - Proxima Nova Semibold-webfont.woff2') format('woff2'),url('Mark Simonson - Proxima Nova Semibold-webfont.woff') format('woff'),url('Mark Simonson - Proxima Nova Semibold-webfont.ttf') format('truetype'),url('Mark Simonson - Proxima Nova Semibold-webfont.svg#proxima_nova_ltsemibold') format('svg');font-weight:400;font-style:normal}@font-face{font-family:proxima_nova_ltthin;src:url('Mark Simonson - Proxima Nova Thin-webfont.eot');src:url('Mark Simonson - Proxima Nova Thin-webfont.eot?#iefix') format('embedded-opentype'),url('Mark Simonson - Proxima Nova Thin-webfont.woff2') format('woff2'),url('Mark Simonson - Proxima Nova Thin-webfont.woff') format('woff'),url('Mark Simonson - Proxima Nova Thin-webfont.ttf') format('truetype'),url('Mark Simonson - Proxima Nova Thin-webfont.svg#proxima_nova_ltthin') format('svg');font-weight:400;font-style:normal} diff --git a/frontend/public/static/js/tinymce/js/tinymce/plugins/codesample/css/prism.css b/frontend/public/static/js/tinymce/js/tinymce/plugins/codesample/css/prism.css new file mode 100644 index 0000000..128237f --- /dev/null +++ b/frontend/public/static/js/tinymce/js/tinymce/plugins/codesample/css/prism.css @@ -0,0 +1,138 @@ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + +code[class*="language-"], +pre[class*="language-"] { + color: black; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, pre[class*="language-"] ::selection, +code[class*="language-"]::selection, code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + diff --git a/frontend/public/static/js/tinymce/js/tinymce/plugins/visualblocks/css/visualblocks.css b/frontend/public/static/js/tinymce/js/tinymce/plugins/visualblocks/css/visualblocks.css new file mode 100644 index 0000000..96e4d7c --- /dev/null +++ b/frontend/public/static/js/tinymce/js/tinymce/plugins/visualblocks/css/visualblocks.css @@ -0,0 +1,154 @@ +.mce-visualblocks p { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7); + background-repeat: no-repeat; +} + +.mce-visualblocks h1 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks h2 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks h3 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7); + background-repeat: no-repeat; +} + +.mce-visualblocks h4 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks h5 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks h6 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks div:not([data-mce-bogus]) { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7); + background-repeat: no-repeat; +} + +.mce-visualblocks section { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=); + background-repeat: no-repeat; +} + +.mce-visualblocks article { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7); + background-repeat: no-repeat; +} + +.mce-visualblocks blockquote { + padding-top: 10px; + border: 1px dashed #BBB; + background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7); + background-repeat: no-repeat; +} + +.mce-visualblocks address { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=); + background-repeat: no-repeat; +} + +.mce-visualblocks pre { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks figure { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7); + background-repeat: no-repeat; +} + +.mce-visualblocks hgroup { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7); + background-repeat: no-repeat; +} + +.mce-visualblocks aside { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=); + background-repeat: no-repeat; +} + +.mce-visualblocks figcaption { + border: 1px dashed #BBB; +} + +.mce-visualblocks ul { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks ol { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==); + background-repeat: no-repeat; +} + +.mce-visualblocks dl { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==); + background-repeat: no-repeat; +} diff --git a/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.inline.min.css b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.inline.min.css new file mode 100644 index 0000000..7b45d33 --- /dev/null +++ b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.inline.min.css @@ -0,0 +1 @@ +.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2}.mce-content-body{line-height:1.3} \ No newline at end of file diff --git a/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.min.css b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.min.css new file mode 100644 index 0000000..fe9bcde --- /dev/null +++ b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.min.css @@ -0,0 +1 @@ +body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:1.3;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2} \ No newline at end of file diff --git a/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.mobile.min.css b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.mobile.min.css new file mode 100644 index 0000000..fa69a9d --- /dev/null +++ b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/content.mobile.min.css @@ -0,0 +1 @@ +.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position:absolute;display:inline-block;background-color:green;opacity:.5}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%} \ No newline at end of file diff --git a/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.min.css b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.min.css new file mode 100644 index 0000000..e246cef --- /dev/null +++ b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *,.mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#595959;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:inherit !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);box-shadow:0 1px 2px rgba(0, 0, 0, 0.2)}.mce-statusbar>.mce-container-body{display:flex;padding-right:16px}.mce-statusbar>.mce-container-body .mce-path{flex:1}.mce-wordcount{font-size:inherit;text-transform:uppercase;padding:8px 0}div.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative;font-size:11px}.mce-fullscreen .mce-resizehandle{display:none}.mce-statusbar .mce-flow-layout-item{margin:0}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid #c5c5c5;width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:white}.mce-grid td.mce-grid-cell div{border:1px solid #c5c5c5;width:15px;height:15px;margin:0;cursor:pointer}.mce-grid td.mce-grid-cell div:focus{border-color:#91bbe9}.mce-grid td.mce-grid-cell div[disabled]{cursor:not-allowed}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover,.mce-grid a:focus{border-color:#91bbe9}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#c5c5c5;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#91bbe9;background:#bdd6f2}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%}.mce-colorbtn-trans div{text-align:center;vertical-align:middle;font-weight:bold;font-size:20px;line-height:16px;color:#8b8b8b}.mce-monospace{font-family:"Courier New",Courier,monospace}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-container b{font-weight:bold}.mce-container p{margin-bottom:5px}.mce-container a{cursor:pointer;color:#2276d2}.mce-container a:hover{text-decoration:underline}.mce-container ul{margin-left:15px}.mce-container .mce-table-striped{border-collapse:collapse;margin:10px}.mce-container .mce-table-striped thead>tr{background-color:#fafafa}.mce-container .mce-table-striped thead>tr th{font-weight:bold}.mce-container .mce-table-striped td,.mce-container .mce-table-striped th{padding:5px}.mce-container .mce-table-striped tr:nth-child(even){background-color:#fafafa}.mce-container .mce-table-striped tbody>tr:hover{background-color:#e1e1e1}.mce-branding{font-size:inherit;text-transform:uppercase;white-space:pre;padding:8px 0}.mce-branding a{font-size:inherit;color:inherit}.mce-top-part{position:relative}.mce-top-part::before{content:'';position:absolute;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);top:0;right:0;bottom:0;left:0;pointer-events:none}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-rtl .mce-statusbar>.mce-container-body>*:last-child{padding-right:0;padding-left:10px}.mce-rtl .mce-path{text-align:right;padding-right:16px}.mce-croprect-container{position:absolute;top:0;left:0}.mce-croprect-handle{position:absolute;top:0;left:0;width:20px;height:20px;border:2px solid white}.mce-croprect-handle-nw{border-width:2px 0 0 2px;margin:-2px 0 0 -2px;cursor:nw-resize;top:100px;left:100px}.mce-croprect-handle-ne{border-width:2px 2px 0 0;margin:-2px 0 0 -20px;cursor:ne-resize;top:100px;left:200px}.mce-croprect-handle-sw{border-width:0 0 2px 2px;margin:-20px 2px 0 -2px;cursor:sw-resize;top:200px;left:100px}.mce-croprect-handle-se{border-width:0 2px 2px 0;margin:-20px 0 0 -20px;cursor:se-resize;top:200px;left:200px}.mce-croprect-handle-move{position:absolute;cursor:move;border:0}.mce-croprect-block{opacity:.5;filter:alpha(opacity=50);zoom:1;position:absolute;background:black}.mce-croprect-handle:focus{border-color:#2276d2}.mce-croprect-handle-move:focus{outline:1px solid #2276d2}.mce-imagepanel{overflow:auto;background:black}.mce-imagepanel-bg{position:absolute;background:url('data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==')}.mce-imagepanel img{position:absolute}.mce-imagetool.mce-btn .mce-ico{display:block;width:20px;height:20px;text-align:center;line-height:20px;font-size:20px;padding:5px}.mce-arrow-up{margin-top:12px}.mce-arrow-down{margin-top:-12px}.mce-arrow:before,.mce-arrow:after{position:absolute;left:50%;display:block;width:0;height:0;border-style:solid;border-color:transparent;content:""}.mce-arrow.mce-arrow-up:before{top:-9px;border-bottom-color:#c5c5c5;border-width:0 9px 9px;margin-left:-9px}.mce-arrow.mce-arrow-down:before{bottom:-9px;border-top-color:#c5c5c5;border-width:9px 9px 0;margin-left:-9px}.mce-arrow.mce-arrow-up:after{top:-8px;border-bottom-color:#fff;border-width:0 8px 8px;margin-left:-8px}.mce-arrow.mce-arrow-down:after{bottom:-8px;border-top-color:#fff;border-width:8px 8px 0;margin-left:-8px}.mce-arrow.mce-arrow-left:before,.mce-arrow.mce-arrow-left:after{margin:0}.mce-arrow.mce-arrow-left:before{left:8px}.mce-arrow.mce-arrow-left:after{left:9px}.mce-arrow.mce-arrow-right:before,.mce-arrow.mce-arrow-right:after{left:auto;margin:0}.mce-arrow.mce-arrow-right:before{right:8px}.mce-arrow.mce-arrow-right:after{right:9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left:before{left:-9px;top:50%;border-right-color:#c5c5c5;border-width:9px 9px 9px 0;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left:after{left:-8px;top:50%;border-right-color:#fff;border-width:8px 8px 8px 0;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left{margin-left:12px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:before{right:-9px;top:50%;border-left-color:#c5c5c5;border-width:9px 0 9px 9px;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:after{right:-8px;top:50%;border-left-color:#fff;border-width:8px 0 8px 8px;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right{margin-left:-14px}.mce-edit-aria-container>.mce-container-body{display:flex}.mce-edit-aria-container>.mce-container-body .mce-edit-area{flex:1}.mce-edit-aria-container>.mce-container-body .mce-sidebar>.mce-container-body{display:flex;align-items:stretch;height:100%}.mce-edit-aria-container>.mce-container-body .mce-sidebar-panel{min-width:250px;max-width:250px;position:relative}.mce-edit-aria-container>.mce-container-body .mce-sidebar-panel>.mce-container-body{position:absolute;width:100%;height:100%;overflow:auto;top:0;left:0}.mce-sidebar-toolbar{border:0 solid #c5c5c5;border-left-width:1px}.mce-sidebar-toolbar .mce-btn{border-left:0;border-right:0}.mce-sidebar-toolbar .mce-btn.mce-active,.mce-sidebar-toolbar .mce-btn.mce-active:hover{background-color:#555c66}.mce-sidebar-toolbar .mce-btn.mce-active button,.mce-sidebar-toolbar .mce-btn.mce-active:hover button,.mce-sidebar-toolbar .mce-btn.mce-active button i,.mce-sidebar-toolbar .mce-btn.mce-active:hover button i{color:white;text-shadow:1px 1px none}.mce-sidebar-panel{border:0 solid #c5c5c5;border-left-width:1px}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1}.mce-scroll{position:relative}.mce-panel{border:0 solid #f3f3f3;border:0 solid #c5c5c5;background-color:#fff}.mce-floatpanel{position:absolute;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);box-shadow:0 1px 2px rgba(0, 0, 0, 0.2)}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);top:0;left:0;background:#FFF;border:1px solid #c5c5c5;border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#c5c5c5;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#FFF}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#FFF}#mce-modal-block.mce-in{opacity:.5;filter:alpha(opacity=50);zoom:1}.mce-window-move{cursor:move}.mce-window{-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#FFF;position:fixed;top:0;left:0;opacity:0;transform:scale(.1);transition:transform 100ms ease-in,opacity 150ms ease-in}.mce-window.mce-in{transform:scale(1);opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:0;top:0;height:38px;width:38px;text-align:center;cursor:pointer}.mce-window-head .mce-close i{color:#9b9b9b}.mce-close:hover i{color:#bdbdbd}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:20px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#FFF;border-top:1px solid #c5c5c5}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window-body .mce-listbox{border-color:#e2e4e7}.mce-window .mce-btn:hover{border-color:#c5c5c5}.mce-window .mce-btn:focus{border-color:#2276d2}.mce-window-body .mce-btn,.mce-foot .mce-btn{border-color:#c5c5c5}.mce-foot .mce-btn.mce-primary{border-color:transparent}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1;margin-top:1px}.mce-tooltip-inner{font-size:11px;background-color:#000;color:white;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-inner{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-ne,.mce-tooltip-se{margin-left:14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-progress{display:inline-block;position:relative;height:20px}.mce-progress .mce-bar-container{display:inline-block;width:100px;height:100%;margin-right:8px;border:1px solid #ccc;overflow:hidden}.mce-progress .mce-text{display:inline-block;margin-top:auto;margin-bottom:auto;font-size:14px;width:40px;color:#595959}.mce-bar{display:block;width:0;height:100%;background-color:#dfdfdf;-webkit-transition:width .2s ease;transition:width .2s ease}.mce-notification{position:absolute;background-color:#fff;padding:5px;margin-top:5px;border-width:1px;border-style:solid;border-color:#c5c5c5;transition:transform 100ms ease-in,opacity 150ms ease-in;opacity:0;box-sizing:border-box}.mce-notification.mce-in{opacity:1}.mce-notification-success{background-color:#dff0d8;border-color:#d6e9c6}.mce-notification-info{background-color:#d9edf7;border-color:#779ECB}.mce-notification-warning{background-color:#fcf8e3;border-color:#faebcc}.mce-notification-error{background-color:#f2dede;border-color:#ebccd1}.mce-notification.mce-has-close{padding-right:15px}.mce-notification .mce-ico{margin-top:5px}.mce-notification-inner{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;display:inline-block;font-size:14px;margin:5px 8px 4px 8px;text-align:center;white-space:normal;color:#31708f}.mce-notification-inner a{text-decoration:underline;cursor:pointer}.mce-notification .mce-progress{margin-right:8px}.mce-notification .mce-progress .mce-text{margin-top:5px}.mce-notification *,.mce-notification .mce-progress .mce-text{color:#595959}.mce-notification .mce-progress .mce-bar-container{border-color:#c5c5c5}.mce-notification .mce-progress .mce-bar-container .mce-bar{background-color:#595959}.mce-notification-success *,.mce-notification-success .mce-progress .mce-text{color:#3c763d}.mce-notification-success .mce-progress .mce-bar-container{border-color:#d6e9c6}.mce-notification-success .mce-progress .mce-bar-container .mce-bar{background-color:#3c763d}.mce-notification-info *,.mce-notification-info .mce-progress .mce-text{color:#31708f}.mce-notification-info .mce-progress .mce-bar-container{border-color:#779ECB}.mce-notification-info .mce-progress .mce-bar-container .mce-bar{background-color:#31708f}.mce-notification-warning *,.mce-notification-warning .mce-progress .mce-text{color:#8a6d3b}.mce-notification-warning .mce-progress .mce-bar-container{border-color:#faebcc}.mce-notification-warning .mce-progress .mce-bar-container .mce-bar{background-color:#8a6d3b}.mce-notification-error *,.mce-notification-error .mce-progress .mce-text{color:#a94442}.mce-notification-error .mce-progress .mce-bar-container{border-color:#ebccd1}.mce-notification-error .mce-progress .mce-bar-container .mce-bar{background-color:#a94442}.mce-notification .mce-close{position:absolute;top:6px;right:8px;font-size:20px;font-weight:bold;line-height:20px;color:#9b9b9b;cursor:pointer}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-btn{border:1px solid #b3b3b3;border-color:transparent transparent transparent transparent;position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);background:white;display:inline-block;*display:inline;*zoom:1;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-btn:hover,.mce-btn:active{background:white;color:#595959;border-color:#e2e4e7}.mce-btn:focus{background:white;color:#595959;border-color:#e2e4e7}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover,.mce-btn.mce-active:focus,.mce-btn.mce-active:active{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;background:#555c66;color:white;border-color:transparent}.mce-btn.mce-active button,.mce-btn.mce-active:hover button,.mce-btn.mce-active i,.mce-btn.mce-active:hover i{color:white}.mce-btn:hover .mce-caret{border-top-color:#b5bcc2}.mce-btn.mce-active .mce-caret,.mce-btn.mce-active:hover .mce-caret{border-top-color:white}.mce-btn button{padding:4px 6px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#595959;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px none}.mce-primary.mce-btn-has-text{min-width:50px}.mce-primary{color:white;border:1px solid transparent;border-color:transparent;background-color:#2276d2}.mce-primary:hover,.mce-primary:focus{background-color:#1e6abc;border-color:transparent}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#1e6abc;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-primary button,.mce-primary button i{color:white;text-shadow:1px 1px none}.mce-btn .mce-txt{font-size:inherit;line-height:inherit;color:inherit}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #b5bcc2;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #b5bcc2;border-top:0}.mce-btn-flat{border:0;background:transparent;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-btn-flat:hover,.mce-btn-flat.mce-active,.mce-btn-flat:focus,.mce-btn-flat:active{border:0;background:#e6e6e6;filter:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-btn-has-text .mce-ico{padding-right:5px}.mce-rtl .mce-btn button{direction:rtl}.mce-toolbar .mce-btn-group{margin:0;padding:2px 0}.mce-btn-group .mce-btn{border-width:1px;margin:0;margin-left:2px}.mce-btn-group:not(:first-child){border-left:1px solid #d9d9d9;padding-left:0;margin-left:2px}.mce-btn-group{margin-left:2px}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-rtl .mce-btn-group .mce-btn{margin-left:0;margin-right:2px}.mce-rtl .mce-btn-group .mce-first{margin-right:0}.mce-rtl .mce-btn-group:not(:first-child){border-left:none;border-right:1px solid #d9d9d9;padding-right:4px;margin-right:4px}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;background-color:white;text-indent:-10em;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#595959;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid #2276d2;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#bdbdbd}.mce-checkbox .mce-label{vertical-align:middle}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-combobox{position:relative;display:inline-block;*display:inline;*zoom:1;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#bdbdbd}.mce-combobox .mce-btn{border:1px solid #c5c5c5;border-left:0;margin:0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-combobox .mce-status{position:absolute;right:2px;top:50%;line-height:16px;margin-top:-8px;font-size:12px;width:15px;height:15px;text-align:center;cursor:pointer}.mce-combobox.mce-has-status input{padding-right:20px}.mce-combobox.mce-has-open .mce-status{right:37px}.mce-combobox .mce-status.mce-i-warning{color:#c09853}.mce-combobox .mce-status.mce-i-checkmark{color:#468847}.mce-menu.mce-combobox-menu{border-top:0;margin-top:0;max-height:200px}.mce-menu.mce-combobox-menu .mce-menu-item{padding:4px 6px 4px 4px;font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-sep{padding:0}.mce-menu.mce-combobox-menu .mce-text{font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-link,.mce-menu.mce-combobox-menu .mce-menu-item-link b{font-size:11px}.mce-menu.mce-combobox-menu .mce-text b{font-size:11px}.mce-colorbox i{border:1px solid #c5c5c5;width:14px;height:14px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-17px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:3px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;padding-left:2px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:0}.mce-colorpicker{position:relative;width:250px;height:220px}.mce-colorpicker-sv{position:absolute;top:0;left:0;width:90%;height:100%;border:1px solid #c5c5c5;cursor:crosshair;overflow:hidden}.mce-colorpicker-h-chunk{width:100%}.mce-colorpicker-overlay1,.mce-colorpicker-overlay2{width:100%;height:100%;position:absolute;top:0;left:0}.mce-colorpicker-overlay1{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr='#ffffff', endColorstr='#00ffffff');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')";background:linear-gradient(to right, #fff, rgba(255,255,255,0))}.mce-colorpicker-overlay2{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#00000000', endColorstr='#000000');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')";background:linear-gradient(to bottom, rgba(0,0,0,0), #000)}.mce-colorpicker-selector1{background:none;position:absolute;width:12px;height:12px;margin:-8px 0 0 -8px;border:1px solid black;border-radius:50%}.mce-colorpicker-selector2{position:absolute;width:10px;height:10px;border:1px solid white;border-radius:50%}.mce-colorpicker-h{position:absolute;top:0;right:0;width:6.5%;height:100%;border:1px solid #c5c5c5;cursor:crosshair}.mce-colorpicker-h-marker{margin-top:-4px;position:absolute;top:0;left:-1px;width:100%;border:1px solid black;background:white;height:4px;z-index:100}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal;font-size:inherit}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#595959;font-size:inherit;text-transform:uppercase}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#555c66;color:white}.mce-path .mce-divider{display:inline;font-size:inherit}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9E9E9E}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid #c5c5c5;width:100%;height:100%}.mce-infobox{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden;border:1px solid red}.mce-infobox div{display:block;margin:5px}.mce-infobox div button{position:absolute;top:50%;right:4px;cursor:pointer;margin-top:-8px;display:none}.mce-infobox div button:focus{outline:2px solid #e2e4e7}.mce-infobox.mce-has-help div{margin-right:25px}.mce-infobox.mce-has-help button{display:block}.mce-infobox.mce-success{background:#dff0d8;border-color:#d6e9c6}.mce-infobox.mce-success div{color:#3c763d}.mce-infobox.mce-warning{background:#fcf8e3;border-color:#faebcc}.mce-infobox.mce-warning div{color:#8a6d3b}.mce-infobox.mce-error{background:#f2dede;border-color:#ebccd1}.mce-infobox.mce-error div{color:#a94442}.mce-rtl .mce-infobox div{text-align:right;direction:rtl}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-label.mce-success{color:#468847}.mce-label.mce-warning{color:#c09853}.mce-label.mce-error{color:#b94a48}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar{border:1px solid #e2e4e7}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-menubar .mce-menubtn button span{color:#595959}.mce-menubar .mce-caret{border-top-color:#b5bcc2}.mce-menubar .mce-active .mce-caret,.mce-menubar .mce-menubtn:hover .mce-caret{border-top-color:#b5bcc2}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:#e2e4e7;background:white;filter:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-menubar .mce-menubtn.mce-active{border-bottom:none;z-index:65537}div.mce-menubtn.mce-opened{border-bottom-color:white;z-index:65537}.mce-menubtn button{color:#595959}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-menu-item{display:block;padding:6px 4px 6px 4px;clear:both;font-weight:normal;line-height:20px;color:#595959;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-caret{margin-top:4px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #595959}.mce-menu-item .mce-menu-shortcut{display:inline-block;padding:0 10px 0 20px;color:#aaa}.mce-menu-item .mce-ico{padding-right:4px}.mce-menu-item:hover,.mce-menu-item:focus{background:#ededee}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:#aaa}.mce-menu-item:hover .mce-text,.mce-menu-item:focus .mce-text,.mce-menu-item:hover .mce-ico,.mce-menu-item:focus .mce-ico{color:#595959}.mce-menu-item.mce-selected{background:#ededee}.mce-menu-item.mce-selected .mce-text,.mce-menu-item.mce-selected .mce-ico{color:#595959}.mce-menu-item.mce-active.mce-menu-item-normal{background:#555c66}.mce-menu-item.mce-active.mce-menu-item-normal .mce-text,.mce-menu-item.mce-active.mce-menu-item-normal .mce-ico{color:white}.mce-menu-item.mce-active.mce-menu-item-checkbox .mce-ico{visibility:visible}.mce-menu-item.mce-disabled,.mce-menu-item.mce-disabled:hover{background:white}.mce-menu-item.mce-disabled:focus,.mce-menu-item.mce-disabled:hover:focus{background:#ededee}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled:hover .mce-text,.mce-menu-item.mce-disabled .mce-ico,.mce-menu-item.mce-disabled:hover .mce-ico{color:#aaa}.mce-menu-item.mce-menu-item-preview.mce-active{border-left:5px solid #555c66;background:white}.mce-menu-item.mce-menu-item-preview.mce-active .mce-text,.mce-menu-item.mce-menu-item-preview.mce-active .mce-ico{color:#595959}.mce-menu-item.mce-menu-item-preview.mce-active:hover{background:#ededee}.mce-menu-item-link{color:#093;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mce-menu-item-link b{color:#093}.mce-menu-item-ellipsis{display:block;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.mce-menu-item:hover *,.mce-menu-item.mce-selected *,.mce-menu-item:focus *{color:#595959}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:transparent;border-bottom:1px solid rgba(0,0,0,0.1);cursor:default;filter:none}div.mce-menu .mce-menu-item b{font-weight:bold}.mce-menu-item-indent-1{padding-left:20px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-3{padding-left:40px}.mce-menu-item-indent-4{padding-left:45px}.mce-menu-item-indent-5{padding-left:50px}.mce-menu-item-indent-6{padding-left:55px}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #595959;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:#595959}.mce-rtl .mce-menu-item .mce-ico{padding-right:0;padding-left:4px}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}.mce-throbber-inline{position:static;height:50px}.mce-menu .mce-throbber-inline{height:25px;background-size:contain}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:-1px 0 0;min-width:180px;background:white;border:1px solid #c5c9cf;border:1px solid #e2e4e7;z-index:1002;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);max-height:500px;overflow:auto;overflow-x:hidden}.mce-menu.mce-animate{opacity:.01;transform:rotateY(10deg) rotateX(-10deg);transform-origin:left top}.mce-menu.mce-menu-align .mce-menu-shortcut,.mce-menu.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block}.mce-menu.mce-in.mce-animate{opacity:1;transform:rotateY(0) rotateX(0);transition:opacity .075s ease,transform .1s ease}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-rtl .mce-menu-item .mce-ico{padding-right:0;padding-left:4px}.mce-rtl.mce-menu-align .mce-caret,.mce-rtl .mce-menu-shortcut{right:auto;left:0}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#595959}.mce-selectbox{background:#fff;border:1px solid #c5c5c5}.mce-slider{border:1px solid #c5c5c5;background:#fff;width:100px;height:10px;position:relative;display:block}.mce-slider.mce-vertical{width:10px;height:100px}.mce-slider-handle{border:1px solid #c5c5c5;background:#e6e6e6;display:block;width:13px;height:13px;position:absolute;top:0;left:0;margin-left:-1px;margin-top:-2px}.mce-slider-handle:focus{border-color:#2276d2}.mce-spacer{visibility:hidden}.mce-splitbtn:hover .mce-open{border-left:1px solid #e2e4e7}.mce-splitbtn .mce-open{border-left:1px solid transparent;padding-right:4px;padding-left:4px}.mce-splitbtn .mce-open:focus{border-left:1px solid #e2e4e7}.mce-splitbtn .mce-open:hover,.mce-splitbtn .mce-open:active{border-left:1px solid #e2e4e7}.mce-splitbtn.mce-active:hover .mce-open{border-left:1px solid white}.mce-splitbtn.mce-opened{border-color:#e2e4e7}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:4px;padding-left:4px}.mce-rtl .mce-splitbtn .mce-open{border-left:0}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tabs,.mce-tabs+.mce-container-body{background:#fff}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#fff;padding:8px 15px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#FDFDFD}.mce-tab.mce-active{background:#FDFDFD;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-tab:focus{color:#2276d2}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#595959}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:#2276d2;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px;height:auto}.mce-textbox.mce-disabled{color:#bdbdbd}.mce-rtl .mce-textbox{text-align:right;direction:rtl}.mce-dropzone{border:3px dashed gray;text-align:center}.mce-dropzone span{text-transform:uppercase;display:inline-block;vertical-align:middle}.mce-dropzone:after{content:"";height:100%;display:inline-block;vertical-align:middle}.mce-dropzone.mce-disabled{opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-dropzone.mce-disabled.mce-dragenter{cursor:not-allowed}.mce-browsebutton{position:relative;overflow:hidden}.mce-browsebutton button{position:relative;z-index:1}.mce-browsebutton input{opacity:0;filter:alpha(opacity=0);zoom:1;position:absolute;top:0;left:0;width:100%;height:100%;z-index:0}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce',Arial;font-style:normal;font-weight:normal;font-variant:normal;font-size:16px;line-height:16px;speak:none;vertical-align:text-top;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;background:transparent center center;background-size:cover;width:16px;height:16px;color:#595959}.mce-btn-small .mce-ico{font-family:'tinymce-small',Arial}.mce-i-save:before{content:"\e000"}.mce-i-newdocument:before{content:"\e001"}.mce-i-fullpage:before{content:"\e002"}.mce-i-alignleft:before{content:"\e003"}.mce-i-aligncenter:before{content:"\e004"}.mce-i-alignright:before{content:"\e005"}.mce-i-alignjustify:before{content:"\e006"}.mce-i-alignnone:before{content:"\e003"}.mce-i-cut:before{content:"\e007"}.mce-i-paste:before{content:"\e008"}.mce-i-searchreplace:before{content:"\e009"}.mce-i-bullist:before{content:"\e00a"}.mce-i-numlist:before{content:"\e00b"}.mce-i-indent:before{content:"\e00c"}.mce-i-outdent:before{content:"\e00d"}.mce-i-blockquote:before{content:"\e00e"}.mce-i-undo:before{content:"\e00f"}.mce-i-redo:before{content:"\e010"}.mce-i-link:before{content:"\e011"}.mce-i-unlink:before{content:"\e012"}.mce-i-anchor:before{content:"\e013"}.mce-i-image:before{content:"\e014"}.mce-i-media:before{content:"\e015"}.mce-i-help:before{content:"\e016"}.mce-i-code:before{content:"\e017"}.mce-i-insertdatetime:before{content:"\e018"}.mce-i-preview:before{content:"\e019"}.mce-i-forecolor:before{content:"\e01a"}.mce-i-backcolor:before{content:"\e01a"}.mce-i-table:before{content:"\e01b"}.mce-i-hr:before{content:"\e01c"}.mce-i-removeformat:before{content:"\e01d"}.mce-i-subscript:before{content:"\e01e"}.mce-i-superscript:before{content:"\e01f"}.mce-i-charmap:before{content:"\e020"}.mce-i-emoticons:before{content:"\e021"}.mce-i-print:before{content:"\e022"}.mce-i-fullscreen:before{content:"\e023"}.mce-i-spellchecker:before{content:"\e024"}.mce-i-nonbreaking:before{content:"\e025"}.mce-i-template:before{content:"\e026"}.mce-i-pagebreak:before{content:"\e027"}.mce-i-restoredraft:before{content:"\e028"}.mce-i-bold:before{content:"\e02a"}.mce-i-italic:before{content:"\e02b"}.mce-i-underline:before{content:"\e02c"}.mce-i-strikethrough:before{content:"\e02d"}.mce-i-visualchars:before{content:"\e02e"}.mce-i-visualblocks:before{content:"\e02e"}.mce-i-ltr:before{content:"\e02f"}.mce-i-rtl:before{content:"\e030"}.mce-i-copy:before{content:"\e031"}.mce-i-resize:before{content:"\e032"}.mce-i-browse:before{content:"\e034"}.mce-i-pastetext:before{content:"\e035"}.mce-i-rotateleft:before{content:"\eaa8"}.mce-i-rotateright:before{content:"\eaa9"}.mce-i-crop:before{content:"\ee78"}.mce-i-editimage:before{content:"\e915"}.mce-i-options:before{content:"\ec6a"}.mce-i-flipv:before{content:"\eaaa"}.mce-i-fliph:before{content:"\eaac"}.mce-i-zoomin:before{content:"\eb35"}.mce-i-zoomout:before{content:"\eb36"}.mce-i-sun:before{content:"\eccc"}.mce-i-moon:before{content:"\eccd"}.mce-i-arrowleft:before{content:"\edc0"}.mce-i-arrowright:before{content:"\e93c"}.mce-i-drop:before{content:"\e935"}.mce-i-contrast:before{content:"\ecd4"}.mce-i-sharpen:before{content:"\eba7"}.mce-i-resize2:before{content:"\edf9"}.mce-i-orientation:before{content:"\e601"}.mce-i-invert:before{content:"\e602"}.mce-i-gamma:before{content:"\e600"}.mce-i-remove:before{content:"\ed6a"}.mce-i-tablerowprops:before{content:"\e604"}.mce-i-tablecellprops:before{content:"\e605"}.mce-i-table2:before{content:"\e606"}.mce-i-tablemergecells:before{content:"\e607"}.mce-i-tableinsertcolbefore:before{content:"\e608"}.mce-i-tableinsertcolafter:before{content:"\e609"}.mce-i-tableinsertrowbefore:before{content:"\e60a"}.mce-i-tableinsertrowafter:before{content:"\e60b"}.mce-i-tablesplitcells:before{content:"\e60d"}.mce-i-tabledelete:before{content:"\e60e"}.mce-i-tableleftheader:before{content:"\e62a"}.mce-i-tabletopheader:before{content:"\e62b"}.mce-i-tabledeleterow:before{content:"\e800"}.mce-i-tabledeletecol:before{content:"\e801"}.mce-i-codesample:before{content:"\e603"}.mce-i-fill:before{content:"\e902"}.mce-i-borderwidth:before{content:"\e903"}.mce-i-line:before{content:"\e904"}.mce-i-count:before{content:"\e905"}.mce-i-translate:before{content:"\e907"}.mce-i-drag:before{content:"\e908"}.mce-i-home:before{content:"\e90b"}.mce-i-upload:before{content:"\e914"}.mce-i-bubble:before{content:"\e91c"}.mce-i-user:before{content:"\e91d"}.mce-i-lock:before{content:"\e926"}.mce-i-unlock:before{content:"\e927"}.mce-i-settings:before{content:"\e928"}.mce-i-remove2:before{content:"\e92a"}.mce-i-menu:before{content:"\e92d"}.mce-i-warning:before{content:"\e930"}.mce-i-question:before{content:"\e931"}.mce-i-pluscircle:before{content:"\e932"}.mce-i-info:before{content:"\e933"}.mce-i-notice:before{content:"\e934"}.mce-i-arrowup:before{content:"\e93b"}.mce-i-arrowdown:before{content:"\e93d"}.mce-i-arrowup2:before{content:"\e93f"}.mce-i-arrowdown2:before{content:"\e940"}.mce-i-menu2:before{content:"\e941"}.mce-i-newtab:before{content:"\e961"}.mce-i-a11y:before{content:"\e900"}.mce-i-plus:before{content:"\e93a"}.mce-i-insert:before{content:"\e93a"}.mce-i-minus:before{content:"\e939"}.mce-i-books:before{content:"\e911"}.mce-i-reload:before{content:"\e906"}.mce-i-toc:before{content:"\e901"}.mce-i-checkmark:before{content:"\e033"}.mce-i-checkbox:before,.mce-i-selected:before{content:"\e033"}.mce-i-insert{font-size:14px}.mce-i-selected{visibility:hidden}i.mce-i-backcolor{text-shadow:none;background:#BBB}/*# sourceMappingURL=skin.min.css.map */ \ No newline at end of file diff --git a/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.mobile.min.css b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.mobile.min.css new file mode 100644 index 0000000..ac322a0 --- /dev/null +++ b/frontend/public/static/js/tinymce/js/tinymce/skins/lightgray/skin.mobile.min.css @@ -0,0 +1,2 @@ +.tinymce-mobile-outer-container{all:initial;display:block}.tinymce-mobile-outer-container *{-webkit-box-sizing:initial;box-sizing:initial;line-height:1;margin:0;padding:0;border:0;outline:0;text-shadow:none;float:none;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent}.tinymce-mobile-icon-arrow-back:before{content:"\e5cd"}.tinymce-mobile-icon-image:before{content:"\e412"}.tinymce-mobile-icon-cancel-circle:before{content:"\e5c9"}.tinymce-mobile-icon-full-dot:before{content:"\e061"}.tinymce-mobile-icon-align-center:before{content:"\e234"}.tinymce-mobile-icon-align-left:before{content:"\e236"}.tinymce-mobile-icon-align-right:before{content:"\e237"}.tinymce-mobile-icon-bold:before{content:"\e238"}.tinymce-mobile-icon-italic:before{content:"\e23f"}.tinymce-mobile-icon-unordered-list:before{content:"\e241"}.tinymce-mobile-icon-ordered-list:before{content:"\e242"}.tinymce-mobile-icon-font-size:before{content:"\e245"}.tinymce-mobile-icon-underline:before{content:"\e249"}.tinymce-mobile-icon-link:before{content:"\e157"}.tinymce-mobile-icon-unlink:before{content:"\eca2"}.tinymce-mobile-icon-color:before{content:"\e891"}.tinymce-mobile-icon-previous:before{content:"\e314"}.tinymce-mobile-icon-next:before{content:"\e315"}.tinymce-mobile-icon-large-font:before,.tinymce-mobile-icon-style-formats:before{content:"\e264"}.tinymce-mobile-icon-undo:before{content:"\e166"}.tinymce-mobile-icon-redo:before{content:"\e15a"}.tinymce-mobile-icon-removeformat:before{content:"\e239"}.tinymce-mobile-icon-small-font:before{content:"\e906"}.tinymce-mobile-icon-readonly-back:before,.tinymce-mobile-format-matches:after{content:"\e5ca"}.tinymce-mobile-icon-small-heading:before{content:"small"}.tinymce-mobile-icon-large-heading:before{content:"large"}.tinymce-mobile-icon-small-heading:before,.tinymce-mobile-icon-large-heading:before{font-family:sans-serif;font-size:80%}.tinymce-mobile-mask-edit-icon:before{content:"\e254"}.tinymce-mobile-icon-back:before{content:"\e5c4"}.tinymce-mobile-icon-heading:before{content:"Headings";font-family:sans-serif;font-weight:bold;font-size:80%}.tinymce-mobile-icon-h1:before{content:"H1";font-weight:bold}.tinymce-mobile-icon-h2:before{content:"H2";font-weight:bold}.tinymce-mobile-icon-h3:before{content:"H3";font-weight:bold}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;position:absolute;width:100%;height:100%;top:0;background:rgba(51,51,51,0.5)}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-border-radius:50%;border-radius:50%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;font-family:sans-serif;font-size:1em}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{-webkit-border-radius:50%;border-radius:50%;width:2.1em;height:2.1em;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size:1em;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}@media only screen and (min-device-width:700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size:1.2em}}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{-webkit-border-radius:50%;border-radius:50%;width:2.1em;height:2.1em;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;color:#4682B4;background-color:white}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon:before{font-family:'tinymce-mobile';content:"\e900"}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index:2}.tinymce-mobile-android-container.tinymce-mobile-android-maximized{position:fixed;top:0;bottom:0;left:0;right:0;border:none;background:#fff;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position:relative}.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display:-webkit-box !important;display:-webkit-flex !important;display:-ms-flexbox !important;display:flex !important;height:auto !important;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.tinymce-mobile-android-scroll-reload{overflow:hidden}:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top:23px}.tinymce-mobile-toolstrip{background:#eceff1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;z-index:1;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:100%;height:2.5em;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;color:#455a64}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{background:#4682B4;color:#eceff1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background:#f44336}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-left:.5em;padding-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-left:2px;margin-right:2px;height:80%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{background:#455a64;color:#b1bec6}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding-top:.4em;padding-bottom:.4em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;overflow:hidden;position:relative;width:100%;min-height:1.5em;padding-left:0;padding-right:0}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{-webkit-transition:left cubic-bezier(.4, 0, 1, 1) .15s;transition:left cubic-bezier(.4, 0, 1, 1) .15s;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family:Sans-serif}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;position:relative}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{position:absolute;right:0;color:#888;font-size:.6em;font-weight:bold;background:inherit;-webkit-border-radius:50%;border-radius:50%;border:none;-webkit-align-self:center;-ms-flex-item-align:center;-ms-grid-row-align:center;align-self:center;height:100%;padding-right:2px}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display:none}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous:before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next:before{padding-left:.5em;padding-right:.5em;height:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;font-weight:bold}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled:before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled:before{visibility:hidden}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{margin:0 2px;font-size:10px;line-height:10px;padding-top:3px;color:#b1bec6}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color:#455a64}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;position:relative;padding:.28em 0;margin-left:10%;margin-right:10%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font:before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading:before{margin-right:.9em;margin-left:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font:before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading:before{margin-left:.9em;margin-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{margin-left:0;margin-right:0}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;height:100%;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;margin-top:.3em;margin-bottom:.3em;background:#b1bec6;height:.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-left:2em;padding-right:2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;height:100%;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;margin-top:.3em;margin-bottom:.3em;background:-webkit-gradient(linear, left top, right top, color-stop(0, #f00), color-stop(17%, #ff0), color-stop(33%, #0f0), color-stop(50%, #0ff), color-stop(67%, #00f), color-stop(83%, #f0f), to(#f00));background:-webkit-linear-gradient(left, #f00 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);background:linear-gradient(to right, #f00 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);height:.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{background:black;width:1.2em;height:.2em;margin-top:.3em;margin-bottom:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{background:white;width:1.2em;height:.2em;margin-top:.3em;margin-bottom:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{position:absolute;height:.5em;width:.5em;left:-10px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin:auto;top:0;bottom:0;-webkit-transition:border 120ms cubic-bezier(.39, .58, .57, 1);transition:border 120ms cubic-bezier(.39, .58, .57, 1);background-color:#455a64;background-clip:padding-box;color:#eceff1;border:.5em solid rgba(136,136,136,0);-webkit-border-radius:3em;border-radius:3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border:.5em solid rgba(136,136,136,0.39)}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{padding-top:.1em;padding-bottom:.1em;padding-left:5px;font-size:.85em;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;background:#fff;border:none;-webkit-border-radius:0;border-radius:0;color:#455a64}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color:#888}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input:-ms-input-placeholder{color:#888}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color:#888}.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}@media only screen and (orientation: landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}}@media only screen and (min-device-width : 320px) and (max-device-width : 568px) and (orientation : landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:150px}}.tinymce-mobile-dropup{background:white;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;overflow:hidden}.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{-webkit-transition:height .3s ease-out;transition:height .3s ease-out}.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{-webkit-transition:height .3s ease-in;transition:height .3s ease-in}.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0}.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.tinymce-mobile-styles-menu{overflow:hidden;outline:4px solid black;position:relative;width:100%;font-family:sans-serif}.tinymce-mobile-styles-menu [role="menu"]{height:100%;position:absolute;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%}.tinymce-mobile-styles-menu [role="menu"].transitioning{-webkit-transition:-webkit-transform .5s ease-in-out;transition:-webkit-transform .5s ease-in-out;transition:transform .5s ease-in-out;transition:transform .5s ease-in-out, -webkit-transform .5s ease-in-out}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{cursor:pointer;padding:1em 1em;position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border-bottom:1px solid #ddd;color:#455a64}.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon:before{font-family:'tinymce-mobile';content:"\e314";color:#455a64}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu:after{font-family:'tinymce-mobile';content:"\e315";position:absolute;padding-left:1em;padding-right:1em;right:0;color:#455a64}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches:after{font-family:'tinymce-mobile';position:absolute;padding-left:1em;padding-right:1em;right:0}.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator,.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser{border-top:#455a64;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:2.5em;padding-left:1em;padding-right:1em;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;background:#eceff1;color:#455a64}.tinymce-mobile-styles-menu [data-transitioning-destination="before"][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state="before"]{-webkit-transform:translate(-100%);transform:translate(-100%)}.tinymce-mobile-styles-menu [data-transitioning-destination="current"][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state="current"]{-webkit-transform:translate(0);transform:translate(0)}.tinymce-mobile-styles-menu [data-transitioning-destination="after"][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state="after"]{-webkit-transform:translate(100%);transform:translate(100%)}@font-face{font-family:'tinymce-mobile';src:url('fonts/tinymce-mobile.woff?8x92w3') format('woff');font-weight:normal;font-style:normal}@media (min-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:25px}}@media (max-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:18px}}.tinymce-mobile-icon{font-family:'tinymce-mobile'}.mixin-flex-and-centre{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.mixin-flex-bar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:100%}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{overflow:hidden;height:300px}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display:none}.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{position:fixed;right:2em;bottom:1em;color:white;background-color:#4682B4;-webkit-border-radius:50%;border-radius:50%;width:2.1em;height:2.1em;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;font-size:1em}@media only screen and (min-device-width:700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size:1.2em}}input[type="file"]::-webkit-file-upload-button{display:none}@media only screen and (min-device-width : 320px) and (max-device-width : 568px) and (orientation : landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom:50%}} +/*# sourceMappingURL=skin.mobile.min.css.map */ \ No newline at end of file From 297f967708b5ca4849fd93a4b4f8d0157e89e352 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 6 Sep 2018 18:12:16 +0200 Subject: [PATCH 62/63] refactor gitignore --- frontend/.gitignore | 5 ----- frontend/src/.gitignore | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) create mode 100644 frontend/src/.gitignore diff --git a/frontend/.gitignore b/frontend/.gitignore index a1d972b..d30f40e 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -9,11 +9,6 @@ # production /build -# devBuild -*.css -#except css files in public/ dir -!public/**/*.css - # misc .DS_Store .env.local diff --git a/frontend/src/.gitignore b/frontend/src/.gitignore new file mode 100644 index 0000000..2318862 --- /dev/null +++ b/frontend/src/.gitignore @@ -0,0 +1 @@ +*.css \ No newline at end of file From 9cda7fdaeb0c9b34868456a8ef61c891237bb786 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 6 Sep 2018 18:14:37 +0200 Subject: [PATCH 63/63] add comment --- frontend/src/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/.gitignore b/frontend/src/.gitignore index 2318862..8787fca 100644 --- a/frontend/src/.gitignore +++ b/frontend/src/.gitignore @@ -1 +1,2 @@ +# devBuild *.css \ No newline at end of file