BNA8/.resources/e535664bb2c9fdb9049b78679f4f4c5db19a09f9c0a71c6d3af13ca0046afb1c

2092 lines
98 KiB
Plaintext

{
"custom": {
"api_region_name": "eu",
"default_file_config": {
"ETag": "?",
"LastModified": "?",
"Size": 0,
"StorageClass": "?"
},
"dummy": [],
"file_not_found": true,
"file_options": [],
"loading": false,
"selected_file": "",
"selected_file_config": {
"ETag": "?",
"Filename": ".svg",
"Key": ".svg",
"LastModified": "?",
"Size": 0,
"StorageClass": "?"
},
"stage_config": {
"account_id": "006306898152",
"api_call_role": "arn:aws:iam::609617486056:role/RMESDScadaS3ManagementAPIcallRole-prod-eu-west-1",
"endpoint": "https://eu-west-1.scada-s3-management.scada.eurme.amazon.dev/",
"lambda_name": "RMESDScadaS3ManagementFlaskLambda-prod",
"region": "eu-west-1",
"repo_bucket": "ignition-image-repo",
"s3_region": "eu-west-1",
"source_bucket": "ignition-image-source"
}
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tself.custom.selected_file \u003d self.params.selected_file"
},
"scope": "G",
"type": "script"
}
}
},
"params": {
"bucket": "",
"enables": {
"delete": true,
"download": true,
"file": true,
"object_key": false,
"upload": true
},
"files": [],
"prefix": "",
"selected_file": "",
"suffix": ".svg",
"upload_file_types": [
"svg"
],
"whid": ""
},
"propConfig": {
"custom.api_region_name": {
"binding": {
"config": {
"path": "session.custom.aws.prefix"
},
"type": "property"
},
"persistent": true
},
"custom.default_file_config": {
"persistent": true
},
"custom.default_file_config.Filename": {
"binding": {
"config": {
"expression": "{view.params.selected_file}+{view.params.suffix}"
},
"type": "expr"
}
},
"custom.default_file_config.Key": {
"binding": {
"config": {
"expression": "{view.params.prefix}+{view.params.selected_file}+{view.params.suffix}"
},
"type": "expr"
}
},
"custom.dummy": {
"persistent": true
},
"custom.file_not_found": {
"binding": {
"config": {
"expression": "{view.custom.selected_file_config.Size}\u003d0"
},
"type": "expr"
},
"persistent": true
},
"custom.file_options": {
"binding": {
"config": {
"path": "view.params.files"
},
"transforms": [
{
"code": "\tprefix \u003d self.params.prefix\n\tsuffix \u003d self.params.suffix\n\treturn [{\u0027value\u0027: x.Filename, \n\t\t\u0027label\u0027: x.Filename} \n\t\tfor x in value]",
"type": "script"
}
],
"type": "property"
},
"persistent": true
},
"custom.loading": {
"persistent": true
},
"custom.selected_file": {
"persistent": true
},
"custom.selected_file_config": {
"binding": {
"config": {
"expression": "{view.custom.selected_file}+toStr({view.custom.file_options})"
},
"transforms": [
{
"code": "\tdef_file_config \u003d self.custom.default_file_config\n\treturn next((x for x in self.params.files if x.Filename \u003d\u003d self.custom.selected_file), def_file_config)",
"type": "script"
}
],
"type": "expr"
},
"persistent": true
},
"custom.stage_config": {
"binding": {
"config": {
"expression": "{view.custom.api_region_name}"
},
"transforms": [
{
"code": "\treturn AWS.s3.STAGE_CONFIG[\u0027prod\u0027][value]",
"type": "script"
}
],
"type": "expr"
},
"persistent": true
},
"params.bucket": {
"paramDirection": "input",
"persistent": true
},
"params.enables": {
"paramDirection": "input",
"persistent": true
},
"params.files": {
"paramDirection": "input",
"persistent": true
},
"params.prefix": {
"paramDirection": "input",
"persistent": true
},
"params.selected_file": {
"onChange": {
"enabled": null,
"script": "\tif not missedEvents:\n\t\tselection \u003d self.getChild(\"root\").getChild(\"FlexContainer\").getChild(\"Table\").props.selection\n\t\tif currentValue.value:\n\t\t\tif not currentValue.value.endswith(self.params.suffix):\n\t\t\t\tself.custom.selected_file \u003d currentValue.value + self.params.suffix\n\t\t\telse:\n\t\t\t\tself.custom.selected_file \u003d currentValue.value\n\t\t\t# now select the correct row in table that matches selection\n\t\t\tfilename \u003d self.custom.selected_file\n\t\t\tselected_row, selected_data \u003d None, []\n\t\t\tfor index, row in enumerate(self.params.files):\n\t\t\t\tif row.Filename \u003d\u003d filename:\n\t\t\t\t\tselected_row \u003d index\n\t\t\t\t\tselected_data.append(row)\n\t\t\t\t\tbreak\n\t\t\tselection.data \u003d selected_data\n\t\t\tselection.selectedRow \u003d selected_row\n\t\telse:\n\t\t\t# file is none, clear out file selection\n\t\t\t# I know, why are we setting to -1, then None? it\u0027s an ignition persp table bug\n\t\t\t# as of 8.1.20. It works...\n\t\t\tselection.selectedRow \u003d -1\n\t\t\tselection.selectedColumn \u003d -1\n\t\t\tselection.selectedRow \u003d None\n\t\t\tselection.selectedColumn \u003d None\n\t"
},
"paramDirection": "input",
"persistent": true
},
"params.suffix": {
"paramDirection": "input",
"persistent": true
},
"params.upload_file_types": {
"paramDirection": "input",
"persistent": true
},
"params.whid": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 600,
"width": 550
}
},
"root": {
"children": [
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label Text/RightAlign_with_Padding",
"paddingLeft": "5px"
},
"text": "Select File:"
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# when user selects new file, send message to update selected image on parent view\n\tif self.props.value:\n\t\tsuffix \u003d self.view.params.suffix\n\t\tselected_image \u003d self.props.value.replace(suffix, \u0027\u0027)\n\t\tpayload \u003d {\u0027image\u0027: selected_image}\n\t\tsystem.perspective.sendMessage(\u0027update_selected_image\u0027, payload, scope\u003d\u0027session\u0027)\n\t\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Dropdown",
"tooltip": {
"location": "bottom",
"style": {
"whiteSpace": "pre"
},
"text": "Click here to select a different \nstage folder to manage"
}
},
"position": {
"basis": "175px",
"grow": 1,
"shrink": 0
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "{view.params.enables.file}\u0026\u0026try(len({view.params.files})\u003e0,false)"
},
"type": "expr"
}
},
"props.options": {
"binding": {
"config": {
"path": "view.custom.file_options"
},
"type": "property"
}
},
"props.value": {
"binding": {
"config": {
"bidirectional": true,
"path": "view.custom.selected_file"
},
"type": "property"
}
}
},
"props": {
"style": {
"margin": "2px",
"marginRight": "5px"
}
},
"type": "ia.input.dropdown"
},
{
"events": {
"component": {
"onFileReceived": {
"config": {
"script": "\tself.upload_file(event\u003devent)\n"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "FileUpload",
"tooltip": {
"enabled": true
}
},
"position": {
"basis": "26px",
"shrink": 0
},
"propConfig": {
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "stringFormat(\u0027Upload new version of %s\u0027,{view.custom.selected_file})"
},
"type": "expr"
}
},
"meta.visible": {
"binding": {
"config": {
"expression": "{view.params.enables.upload}\u0026\u0026!{view.custom.file_not_found}"
},
"type": "expr"
}
},
"props.supportedFileTypes": {
"binding": {
"config": {
"path": "view.params.upload_file_types"
},
"type": "property"
}
}
},
"props": {
"fileSizeLimit": 20,
"fileUploadIcon": {
"style": {
"borderStyle": "none",
"classes": "Input/Button/Secondary_minimal",
"margin": "-5px"
}
},
"maxUploads": 1
},
"scripts": {
"customMethods": [
{
"name": "update_bindings",
"params": [],
"script": "\t\"\"\"\n\t\tAfter data saved to S3, refresh session and view bindings\n\t\"\"\"\n\t\n\tself.view.custom.loading \u003d False\n\t# reset file upload component to default state\n\tself.clearUploads()\n\t# send message to update files param on parent view\n\tbucket \u003d self.view.params.bucket\n\tsystem.perspective.sendMessage(\u0027update_file_binding\u0027, {\u0027bucket\u0027: bucket}, scope\u003d\u0027session\u0027)\n\t"
},
{
"name": "show_success_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"success\", \n\t\t\"File Uploaded\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t"
},
{
"name": "show_warning_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"warning\", \n\t\t\"File NOT Uploaded\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t"
},
{
"name": "show_error_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"error\", \n\t\t\"File Upload Error!\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t\t"
},
{
"name": "upload_file",
"params": [
"event\u003dNone"
],
"script": "\tfrom AWS.s3 import S3Manager\n\tfrom pprint import pformat\n\tsystem.perspective.print(\u0027FileUpload component upload_file custom method reached...\u0027)\n\tself.view.custom.loading \u003d True\n\ttry:\n\t\tapi_stage \u003d \u0027prod\u0027\n\t\tusername \u003d self.session.props.auth.user.userName\n\t\tapi_region_name \u003d self.view.custom.api_region_name\n\t\tbucket \u003d self.view.params.bucket\n\t\tobj_key \u003d self.view.custom.selected_file_config.Key\n\t\tregion \u003d self.view.custom.stage_config.s3_region\n\t\texisting_filename \u003d self.view.custom.selected_file_config.Filename\n\t\tfilename \u003d event.file.name\n\t\t# verify that uploaded file name matches existing file name. Throw error if not.\n\t\tif filename !\u003d existing_filename:\n\t\t\tmsg \u003d \u0027File uploaded does not have the same name as target object key. Please check spelling and that you selected the correct file to upload. Target filename: %s. Received: %s\u0027 % (\n\t\t\t\t\texisting_filename, filename)\n\t\t\tself.show_error_dialog(msg)\n\t\t\tself.view.custom.loading \u003d False\n\t\t\tself.clearUploads()\n\t\t\treturn\n\t\tsystem.perspective.print(\u0027obj_key to upload: %s\u0027 % obj_key)\n\t\tobj_data \u003d event.file.getString()\n\t\tsystem.perspective.print(\u0027obj_data length: %s\u0027 % len(obj_data))\n\n\t\ts3m \u003d S3Manager(api_stage, api_region_name, username)\n\t\ttry:\n\t\t\tresp \u003d s3m.upload(\n\t\t\t\tobj_data\u003dobj_data,\n\t\t\t\tobj_key\u003dobj_key,\n\t\t\t\tbucket\u003dbucket,\n\t\t\t\tregion\u003dregion\n\t\t\t)\n\t\t\tresp_code \u003d resp.get(\u0027code\u0027, None)\n\t\t\tif (resp_code and resp_code !\u003d 200) or (not resp_code and \u0027message\u0027 in resp):\n\t\t\t\t# this means the API encountered an error, annunciate the error here\n\t\t\t\tmsg \u003d \u0027API encountered error uploading %s to %s bucket. \\nResponse: %s\u0027 % (obj_key, bucket, pformat(resp))\n\t\t\t\tsystem.perspective.print(msg)\n\t\t\t\tself.view.custom.loading \u003d False\n\t\t\t\tself.show_error_dialog(msg)\n\t\t\t\tself.clearUploads()\n\t\t\t\treturn\n\t\t\tmsg \u003d \u0027Successfully uploaded %s object in %s bucket!\\nResponse: %s\u0027 % (obj_key, bucket, pformat(resp))\n\t\t\tsystem.perspective.print(msg)\n\t\t\tself.show_success_dialog(msg)\n\t\t\tself.update_bindings()\n\t\texcept:\n\t\t\timport traceback\n\t\t\tmsg \u003d \u0027Error uploading %s object in %s bucket: %s\u0027 % (obj_key, bucket, traceback.format_exc())\n\t\t\tsystem.perspective.print(msg)\n\t\t\tself.view.custom.loading \u003d False\n\t\t\tself.show_error_dialog(msg)\n\t\t\tself.clearUploads()\n\texcept:\n\t\timport traceback\n\t\tmsg \u003d \u0027General Error uploading %s object in %s bucket: %s\u0027 % (obj_key, bucket, traceback.format_exc())\n\t\tsystem.perspective.print(msg)\n\t\tself.view.custom.loading \u003d False\n\t\tself.show_error_dialog(msg)\n\t\tself.clearUploads()\n\t\t"
}
],
"extensionFunctions": null,
"messageHandlers": []
},
"type": "ia.input.fileupload"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tfrom AWS.s3 import S3Manager\n\tfrom pprint import pformat\n\timport json\n\t\n\tapi_stage \u003d \u0027prod\u0027\n\tusername \u003d self.session.props.auth.user.userName\n\tapi_region_name \u003d self.view.custom.api_region_name\n\tbucket \u003d self.view.params.bucket\n\tobj_key \u003d self.view.custom.selected_file_config.Key\n\tregion \u003d self.view.custom.stage_config.s3_region\n\tfilename \u003d self.view.custom.selected_file_config.Filename\n\t\n\ts3m \u003d S3Manager(api_stage, api_region_name, username)\n\tdata \u003d None\n\ttry:\n\t\tresp \u003d s3m.download(bucket\u003dbucket, obj_key\u003dobj_key, region\u003dregion)\n\t\ttry:\n\t\t\tresp_code \u003d resp.get(\u0027code\u0027, None)\n\t\texcept AttributeError:\n\t\t\tresp_code \u003d None\n\t\tif (resp_code and resp_code !\u003d 200) or (not resp_code and \u0027message\u0027 in resp):\n\t\t\t# this means the API encountered an error, annunciate the error here\n\t\t\tmsg \u003d \u0027API encountered error downloading %s on %s bucket. \\nResponse: %s\u0027 % (obj_key, bucket, pformat(sanitize_tree(resp)))\n\t\t\tsystem.perspective.print(msg)\n\t\t\tself.show_error_dialog(msg)\n\t\t\treturn\n\t\tif isinstance(resp, dict) or isinstance(resp, list):\n\t\t\tdata \u003d json.dumps(resp, indent\u003d2)\n\t\telse:\n\t\t\tdata \u003d resp\n\texcept:\n\t\timport traceback\n\t\tmsg \u003d \u0027error downloading %s obj: %s\u0027 % (obj_key, traceback.format_exc())\n\t\tsystem.perspective.print(msg)\n\t\tself.show_error_dialog(msg)\n\tif data:\n\t\tsystem.perspective.download(filename, data)\n\telse:\n\t\tsystem.perspective.print(\u0027no data for %s obj!\u0027 % obj_key)\n\t\tself.show_error_dialog(msg)\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Download Button",
"tooltip": {
"enabled": true
}
},
"position": {
"basis": "26px",
"shrink": 0
},
"propConfig": {
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "stringFormat(\u0027Download copy of %s\u0027,{view.custom.selected_file})"
},
"type": "expr"
}
},
"props.enabled": {
"binding": {
"config": {
"expression": "{view.params.enables.download}\u0026\u0026!{view.custom.file_not_found}"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/cloud_download"
}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal",
"margin": "2px"
},
"text": ""
},
"scripts": {
"customMethods": [
{
"name": "show_error_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"error\", \n\t\t\"File Download Error!\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t\t\t"
}
],
"extensionFunctions": null,
"messageHandlers": []
},
"type": "ia.input.button"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tself.show_confirm_dialog()"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Delete Button",
"tooltip": {
"enabled": true
}
},
"position": {
"basis": "26px",
"shrink": 0
},
"propConfig": {
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "stringFormat(\u0027Delete record of %s file from %s bucket\u0027,\r\n\t{view.custom.selected_file},{view.params.bucket})"
},
"type": "expr"
}
},
"props.enabled": {
"binding": {
"config": {
"expression": "{view.params.enables.delete}\u0026\u0026!{view.custom.file_not_found}"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/delete_forever"
}
},
"primary": false,
"style": {
"classes": "Input/Button/Secondary_minimal",
"margin": "2px"
},
"text": ""
},
"scripts": {
"customMethods": [
{
"name": "show_success_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"success\", \n\t\t\"File Deleted\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t\t"
},
{
"name": "show_warning_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"warning\", \n\t\t\"File NOT Deleted\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t\t"
},
{
"name": "show_error_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"error\", \n\t\t\"File Delete Error!\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t\t"
},
{
"name": "show_confirm_dialog",
"params": [
"payload\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add payload of data to pass to the popup\n\tmsg \u003d (\u0027Are you sure you want to delete %s file from %s S3 bucket? THIS OPERATION CANNOT BE UNDONE!\u0027) % (\n\t\tself.view.custom.selected_file, self.view.params.bucket)\n\tpayload \u003d {\u0027bucket\u0027: self.view.params.bucket}\t\t\n\tAlerts.showAlert(\n\t\t\"info\", \n\t\t\"Delete from S3?\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"Continue\", \n\t\t\"Cancel\", \n\t\t\"delete_forever\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"confirm_delete_file\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\tpayload\n\t)\n\t\t\t"
},
{
"name": "update_bindings",
"params": [],
"script": "\t\"\"\"\n\t\tAfter deleted from S3, refresh session and view bindings\n\t\"\"\"\n\tself.view.custom.loading \u003d False\n\t# send message to update files param on parent view\n\tbucket \u003d self.view.params.bucket\n\tsystem.perspective.sendMessage(\u0027update_file_binding\u0027, {\u0027bucket\u0027: bucket}, scope\u003d\u0027session\u0027)\n\t"
},
{
"name": "delete_file",
"params": [],
"script": "\t\"\"\"\n\t\tCall AWS.s3.S3Manager.delete() method with user selections\n\t\"\"\"\n\tfrom AWS.s3 import S3Manager\n\tfrom pprint import pformat\n\tfrom helper.helper import sanitize_tree\n\t\n\tapi_region_name \u003d self.view.custom.api_region_name\n\tusername \u003d self.session.props.auth.user.userName\n\tself.view.custom.loading \u003d True\n\n\ts3m \u003d S3Manager(\u0027prod\u0027, api_region_name, username)\n\n\tbucket \u003d self.view.params.bucket\n\tobj_key \u003d self.view.custom.selected_file_config.Key\n\toperation \u003d \u0027delete\u0027\n\tparams \u003d {\u0027obj_key\u0027: obj_key, \u0027bucket\u0027: bucket}\n\ttry:\n\t\tresp \u003d getattr(s3m, operation)(**params)\n\t\tresp_code \u003d resp.get(\u0027code\u0027, None)\n\t\tif (resp_code and resp_code !\u003d 200) or (not resp_code and \u0027message\u0027 in resp):\n\t\t\t# this means the API encountered an error, annunciate the error here\n\t\t\tmsg \u003d \u0027API encountered error deleting %s on %s bucket. \\nResponse: %s\u0027 % (obj_key, bucket, pformat(sanitize_tree(resp)))\n\t\t\tsystem.perspective.print(msg)\n\t\t\tself.view.custom.loading \u003d False\n\t\t\tself.show_error_dialog(msg)\n\t\t\treturn\n\t\tmsg \u003d pformat(sanitize_tree(resp))\n\t\tsystem.perspective.print(msg)\n\t\tself.show_success_dialog(msg)\n\t\tself.update_bindings()\n\texcept:\n\t\timport traceback\n\t\tmsg \u003d \u0027Error executing %s operation! \\nError: %s\u0027 % (\n\t\t\t\toperation, traceback.format_exc())\n\t\tsystem.perspective.print(msg)\n\t\tself.view.custom.loading \u003d False\n\t\tself.show_error_dialog(msg)\n\t"
}
],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "confirm_delete_file",
"pageScope": false,
"script": "\tsystem.perspective.closePopup(\u0027alertDialog\u0027)\n\tif payload is not None:\n\t\tbucket_requested \u003d payload.get(\u0027bucket\u0027, None)\n\t\tif bucket_requested and bucket_requested \u003d\u003d self.view.params.bucket:\n\t\t\t# call the delete custom method\n\t\t\tself.delete_file()",
"sessionScope": true,
"viewScope": true
}
]
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FlexContainer File Selection"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Cards/Row"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label Text/RightAlign_with_Padding",
"paddingLeft": "5px"
},
"text": "Object Key (uri):"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "label_LeftAlign"
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.params.text": {
"binding": {
"config": {
"path": "view.custom.selected_file_config.Key"
},
"type": "property"
}
}
},
"props": {
"path": "Objects/Templates/Labels/label_LeftAlign",
"style": {
"classes": "Framework/Card/Value"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer Object Key"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "!{view.custom.file_not_found}"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Framework/Cards/Row"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label Text/RightAlign_with_Padding",
"paddingLeft": "5px"
},
"text": "Last Modified:"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "label_LeftAlign"
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.params.text": {
"binding": {
"config": {
"path": "view.custom.selected_file_config.LastModified"
},
"type": "property"
}
}
},
"props": {
"path": "Objects/Templates/Labels/label_LeftAlign",
"style": {
"classes": "Framework/Card/Value"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer Last Modified"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "!{view.custom.file_not_found}"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Framework/Cards/Row"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label Text/RightAlign_with_Padding",
"paddingLeft": "5px"
},
"text": "File Size (KB):"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "label_LeftAlign"
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.params.text": {
"binding": {
"config": {
"expression": "round({view.custom.selected_file_config.Size}/1024.0,2)"
},
"type": "expr"
}
}
},
"props": {
"path": "Objects/Templates/Labels/label_LeftAlign",
"style": {
"classes": "Framework/Card/Value"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer File Size"
},
"position": {
"basis": "50%",
"grow": 1
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "Label"
},
"position": {
"basis": "125px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label Text/RightAlign_with_Padding",
"paddingLeft": "5px"
},
"text": "Storage Class:"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "label_LeftAlign"
},
"position": {
"basis": "200px",
"grow": 1
},
"propConfig": {
"props.params.text": {
"binding": {
"config": {
"path": "view.custom.selected_file_config.StorageClass"
},
"type": "property"
}
}
},
"props": {
"path": "Objects/Templates/Labels/label_LeftAlign",
"style": {
"classes": "Framework/Card/Value"
}
},
"type": "ia.display.view"
}
],
"meta": {
"name": "FlexContainer Storage Class"
},
"position": {
"basis": "50%",
"grow": 1
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "FlexContainer File Detail"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "!{view.custom.file_not_found}"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Framework/Cards/Row"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# build out the stage, site, flow-view, and copy_option from the object-key in row\n\tobj_key \u003d self.view.custom.selected_file_config.Key\n\tfilename \u003d self.view.custom.selected_file_config.Filename\n\tsuffix \u003d self.view.params.suffix\n\tpath \u003d obj_key.split(\u0027/\u0027)\n\tsite \u003d path[1]\n\tview \u003d filename.replace(suffix,\u0027\u0027)\n\tbucket \u003d self.view.params.bucket\n\t# build out query_params from row values\n\t# view, site, and bucket are multi-select dropdowns so need to be cast as lists\n\tnull \u003d None\n\tquery_params \u003d {\n\t\t\"copy_option\": null,\n\t\t\"destination_bucket\": bucket,\n\t\t\"destination_site\": site,\n\t\t\"destination_view\": view,\n\t\t\"end_time\": null,\n\t\t\"error_occurred\": null,\n\t\t\"operation\": null,\n\t\t\"source_bucket\": null,\n\t\t\"source_site\": null,\n\t\t\"source_view\": null,\n\t\t\"start_time\": null,\n\t\t\"username\": \"\"\n\t}\n\t# Open audit log viewer\n\tview_path \u003d \u0027PopUp-Views/S3/Audit/Log_Viewer\u0027\n\tparams \u003d {\u0027query_params\u0027: query_params}\n\tsystem.perspective.openPopup(\u0027Audit Log Viewer\u0027, view_path, \n\t\t\t\t\t\t\t\tparams, \u0027SCADA S3 Audit Logs\u0027)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Audit Logs Button",
"tooltip": {
"enabled": true,
"location": "bottom",
"text": "View Audit Logs for this file"
}
},
"position": {
"shrink": 0
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!{view.custom.file_not_found}"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/table_view"
}
},
"primary": false,
"style": {
"margin": "2px",
"paddingLeft": "4px",
"paddingRight": "4px"
},
"text": "Audit Logs"
},
"type": "ia.input.button"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\t# build out the stage, site, flow-view, and copy_option from the object-key in row\n\tobj_key \u003d self.view.custom.selected_file_config.Key\n\tfilename \u003d self.view.custom.selected_file_config.Filename\n\tsuffix \u003d self.view.params.suffix\n\tpath \u003d obj_key.split(\u0027/\u0027)\n\tsite \u003d path[1]\n\tview \u003d filename.replace(suffix,\u0027\u0027)\n\tbucket \u003d self.view.params.bucket\n\t# build out query_params from row values\n\tquery_params \u003d {\n\t\t\"view\": view,\n\t\t\"object_key\": obj_key,\n\t\t\"site\": site,\n\t\t\"bucket\": bucket\n\t}\n\t# Open version history log viewer\n\tview_path \u003d \u0027PopUp-Views/S3/Versions/Log_Viewer\u0027\n\tparams \u003d {\u0027query_params\u0027: query_params}\n\tsystem.perspective.openPopup(\u0027Version Log Viewer\u0027, view_path, \n\t\t\t\t\t\t\t\tparams, \u0027SCADA S3 Version History Log Viewer\u0027)\n\t\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Version History Button",
"tooltip": {
"text": "View Version History for this file"
}
},
"position": {
"shrink": 0
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": "!{view.custom.file_not_found}"
},
"type": "expr"
}
}
},
"props": {
"image": {
"icon": {
"path": "material/history"
}
},
"primary": false,
"style": {
"margin": "2px",
"paddingLeft": "4px",
"paddingRight": "4px"
},
"text": "Version History"
},
"type": "ia.input.button"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "75px",
"shrink": 0
},
"props": {
"style": {
"classes": "Framework/Card/Label Text/RightAlign_with_Padding",
"paddingLeft": "5px"
},
"text": "Upload New File:"
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onFileReceived": {
"config": {
"script": "\tself.upload_file(event\u003devent)\n"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "FileUpload",
"tooltip": {
"enabled": true
}
},
"position": {
"basis": "25%",
"shrink": 0
},
"propConfig": {
"meta.tooltip.text": {
"binding": {
"config": {
"expression": "stringFormat(\u0027Upload new file to %s S3 bucket\u0027,{view.params.bucket})"
},
"type": "expr"
}
},
"position.display": {
"binding": {
"config": {
"path": "view.params.enables.upload"
},
"type": "property"
}
},
"props.supportedFileTypes": {
"binding": {
"config": {
"path": "view.params.upload_file_types"
},
"type": "property"
}
}
},
"props": {
"fileSizeLimit": 100,
"fileUploadIcon": {
"style": {
"classes": ""
}
},
"maxUploads": 1,
"style": {
"backgroundColor": "var(--neutral-30)",
"borderStyle": "none",
"classes": "FadeInFast, background, background-none",
"cursor": "pointer",
"margin": "2px",
"max-height": "40px",
"overflow": "visible"
}
},
"scripts": {
"customMethods": [
{
"name": "update_bindings",
"params": [],
"script": "\t\"\"\"\n\t\tAfter data saved to S3, refresh session and view bindings\n\t\"\"\"\n\t\n\tself.view.custom.loading \u003d False\n\t# reset file upload component to default state\n\tself.clearUploads()\n\t# send message to update files param on parent view\n\tbucket \u003d self.view.params.bucket\n\tsystem.perspective.sendMessage(\u0027update_file_binding\u0027, {\u0027bucket\u0027: bucket}, scope\u003d\u0027session\u0027)\n\t"
},
{
"name": "show_success_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"success\", \n\t\t\"File Uploaded\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t"
},
{
"name": "show_warning_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"warning\", \n\t\t\"File NOT Uploaded\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t"
},
{
"name": "show_error_dialog",
"params": [
"msg\u003dNone"
],
"script": "\t# ~~ 13 PARAMETERS ~~\n\t# state\t\t\t\t\t(default \u003d info) empty string uses generic gray styling\n\t# title \t\t\t\t(default \u003d Alert Title) empty string sets the title visibility to false\n\t# message \t\t\t\t(default \u003d Alert message goes here.)\n\t# show close button\t\t(default \u003d true) boolean\n\t# btn text primary\t\t(default \u003d \"Primary\")\n\t# btn text secondary\t(default \u003d \"Secondary\")\n\t# btn icon primary \t\t(default \u003d chevron_right) do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon secondary \t(default \u003d \"\") do not include \u0027material/\u0027 in the path, just the icon name\n\t# btn icon alignment\t(default \u003d \"right\") left or right\n\t# btn primary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn secondary action\t(default \u003d \"\") add message handlers on this button to enable other script actions\n\t# btn close action\t\t(default \u003d \"\") add message handlers on this icon to enable other script actions\n\t# payload\t\t\t\t(default \u003d {}) add a payload here to return to the target message handler\n\t\n\tAlerts.showAlert(\n\t\t\"error\", \n\t\t\"File Upload Error!\", \n\t\tmsg, \n\t\t\"true\",\n\t\t\"OK\", \n\t\t\"CLOSE\", \n\t\t\"\", \n\t\t\"\", \n\t\t\"left\", \n\t\t\"closePopup\", \n\t\t\"closePopup\", \n\t\t\"closePopup\",\n\t\t{}\n\t)\n\t\t\t\t\t"
},
{
"name": "upload_file",
"params": [
"event\u003dNone"
],
"script": "\tfrom AWS.s3 import S3Manager\n\tfrom pprint import pformat\n\t\n\tself.view.custom.loading \u003d True\n\ttry:\n\t\tapi_stage \u003d \u0027prod\u0027\n\t\tusername \u003d self.session.props.auth.user.userName\n\t\tapi_region_name \u003d self.view.custom.api_region_name\n\t\tbucket \u003d self.view.params.bucket\n\t\tdefault_obj_key \u003d self.view.custom.default_file_config.Key\n\t\tdefault_filename \u003d self.view.custom.default_file_config.Filename\n\t\tregion \u003d self.view.custom.stage_config.s3_region\n\t\tfilename \u003d event.file.name\n\t\t# check if file already exists in S3 site folder, throw error if so\n\t\tif any(x.Filename \u003d\u003d filename for x in self.view.params.files):\n\t\t\tmsg \u003d \u0027%s file already exists in the site folder. Please use the upload button next to the file select dropdown or select a new file to upload\u0027 % filename\n\t\t\tself.show_error_dialog(msg)\n\t\t\tself.view.custom.loading \u003d False\n\t\t\tself.clearUploads()\n\t\t\treturn\n\t\tobj_key \u003d default_obj_key.replace(default_filename, filename)\n\t\tobj_data \u003d event.file.getString()\n\t\t\n\t\ts3m \u003d S3Manager(api_stage, api_region_name, username)\n\t\ttry:\n\t\t\tresp \u003d s3m.upload(\n\t\t\t\tobj_data\u003dobj_data,\n\t\t\t\tobj_key\u003dobj_key,\n\t\t\t\tbucket\u003dbucket,\n\t\t\t\tregion\u003dregion\n\t\t\t)\n\t\t\tresp_code \u003d resp.get(\u0027code\u0027, None)\n\t\t\tif (resp_code and resp_code !\u003d 200) or (not resp_code and \u0027message\u0027 in resp):\n\t\t\t\t# this means the API encountered an error, annunciate the error here\n\t\t\t\tmsg \u003d \u0027API encountered error uploading %s to %s bucket. \\nResponse: %s\u0027 % (obj_key, bucket, pformat(resp))\n\t\t\t\tsystem.perspective.print(msg)\n\t\t\t\tself.view.custom.loading \u003d False\n\t\t\t\tself.show_error_dialog(msg)\n\t\t\t\tself.clearUploads()\n\t\t\t\treturn\n\t\t\tmsg \u003d \u0027Successfully uploaded %s object in %s bucket!\\nResponse: %s\u0027 % (obj_key, bucket, pformat(resp))\n\t\t\tsystem.perspective.print(msg)\n\t\t\tself.show_success_dialog(msg)\n\t\t\tself.update_bindings()\n\t\texcept:\n\t\t\timport traceback\n\t\t\tmsg \u003d \u0027Error uploading %s object in %s bucket: %s\u0027 % (obj_key, bucket, traceback.format_exc())\n\t\t\tsystem.perspective.print(msg)\n\t\t\tself.view.custom.loading \u003d False\n\t\t\tself.show_error_dialog(msg)\n\t\t\tself.clearUploads()\n\texcept:\n\t\timport traceback\n\t\tmsg \u003d \u0027General Error uploading %s object in %s bucket: %s\u0027 % (obj_key, bucket, traceback.format_exc())\n\t\tsystem.perspective.print(msg)\n\t\tself.view.custom.loading \u003d False\n\t\tself.show_error_dialog(msg)\n\t\tself.clearUploads()\n\t\t"
}
],
"extensionFunctions": null,
"messageHandlers": []
},
"type": "ia.input.fileupload"
}
],
"meta": {
"name": "FlexContainer Log Buttons"
},
"position": {
"shrink": 0
},
"props": {
"justify": "center"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "Title"
},
"position": {
"basis": "100%"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"expression": "stringFormat(\u0027%s Object%s\u0027, len({view.params.files}), \r\n\tif(len({view.params.files})\u003d1,\u0027\u0027,\u0027s\u0027))"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Title/Text",
"fontSize": 14,
"overflow": "visible"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "Title"
},
"position": {
"basis": "50%"
},
"props": {
"style": {
"fontSize": 1,
"marginLeft": 10,
"overflow": "visible"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "FilterCheck",
"tooltip": {
"enabled": true,
"location": "top-left",
"text": "Enable Table Search"
}
},
"position": {
"basis": "108px"
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "LEN({..../Table.props.data})\u003e0"
},
"type": "expr"
}
}
},
"props": {
"checkedIcon": {
"style": {
"fontSize": 16
}
},
"indeterminateIcon": {
"style": {
"fontSize": 16
}
},
"style": {
"fontSize": 12
},
"text": "Search?",
"textPosition": "left",
"uncheckedIcon": {
"style": {
"fontSize": 16
}
}
},
"type": "ia.input.checkbox"
},
{
"meta": {
"name": "Spacer1"
},
"position": {
"basis": "1px"
},
"props": {
"style": {
"classes": "General/Divider"
}
},
"type": "ia.container.flex"
},
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tself.view.custom.selected_file \u003d \u0027\u0027\n\ttable \u003d self.parent.parent.parent.getChild(\"Table\")\n\t# ignition perspective has a bug with table where the only way to \n\t# actually de-select and remove the row highlight is to set the\n\t# row and column to -1 and THEN None\n\t# this will automatically clear the selection.data array\n\ttable.props.selection.selectedRow \u003d -1\n\ttable.props.selection.selectedColumn \u003d -1\n\ttable.props.selection.selectedRow \u003d None\n\ttable.props.selection.selectedColumn \u003d None"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "ClearSelectionButton",
"tooltip": {
"enabled": true,
"location": "top-left",
"text": "Clear Selection"
}
},
"position": {
"basis": "31px"
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "len({..../Table.props.selection.data})\u003e0"
},
"type": "expr"
}
}
},
"props": {
"path": "material/clear",
"style": {
"classes": "General/Button"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Spacer2"
},
"position": {
"basis": "1px"
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "../ClearSelectionButton.position.display"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "General/Divider"
}
},
"type": "ia.container.flex"
},
{
"events": {
"dom": {
"onClick": {
"config": {
"draggable": false,
"id": "ColumnSelection",
"modal": true,
"overlayDismiss": true,
"position": {
"relativeLocation": "bottom-left"
},
"positionType": "relative",
"resizable": true,
"showCloseIcon": true,
"type": "toggle",
"viewParams": {
"Columns": "{/root/FlexContainer/TableHeader/TableActions/ColumnSelectionButton.custom.Columns}"
},
"viewPath": "Objects/PowerTable/ColumnSelection",
"viewportBound": false
},
"scope": "C",
"type": "popup"
}
}
},
"meta": {
"name": "ColumnSelectionButton",
"tooltip": {
"enabled": true,
"location": "top-left",
"text": "+/- Columns"
}
},
"position": {
"basis": "29px"
},
"propConfig": {
"custom.Columns": {
"binding": {
"config": {
"path": "..../Table.props.columns"
},
"transforms": [
{
"code": "\tcolumns \u003d {}\n\tif len(value) \u003e 0:\n\t\tfor column in value:\n\t\t\t#field \u003d column.field\n\t\t\tfield \u003d column.header.title\n\t\t\tif field \u003d\u003d \u0027\u0027:\n\t\t\t\tfield \u003d \u0027None\u0027\n\t\t\tcolumns[field] \u003d column.visible\n\treturn columns",
"type": "script"
}
],
"type": "property"
}
},
"position.display": {
"binding": {
"config": {
"expression": "LEN({..../Table.props.data})\u003e0"
},
"type": "expr"
}
}
},
"props": {
"path": "material/view_column",
"style": {
"classes": "General/Button",
"fontSize": 12,
"marginBottom": 5,
"marginTop": 5
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Spacer4"
},
"position": {
"basis": "1px"
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "LEN({..../Table.props.data})\u003e0"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "General/Divider"
}
},
"type": "ia.container.flex"
},
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tself.view.custom.filters.selection_active \u003d not self.view.custom.filters.selection_active"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "FilterButton",
"tooltip": {
"enabled": true,
"location": "top-left",
"text": "Filter Table"
}
},
"position": {
"basis": "29px",
"display": false
},
"props": {
"path": "material/filter_list",
"style": {
"classes": "General/Button",
"fontSize": 12,
"marginBottom": 5,
"marginTop": 5
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Spacer3"
},
"position": {
"basis": "1px"
},
"props": {
"style": {
"classes": "General/Divider"
}
},
"type": "ia.container.flex"
},
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\n\tcsv_headers \u003d []\n\tcsv_data \u003d []\n\tsystem.perspective.print(\u0027DOWNLOADING TABLE DATA\u0027)\n\tsource_data \u003d self.parent.parent.parent.getChild(\"Table\").props.data\n\theaders \u003d source_data[0].keys()\n\t\n\tif \u0027style\u0027 in headers and \u0027value\u0027 in headers and len(headers) \u003d\u003d 2:\n\t\tdata \u003d [row[\u0027value\u0027] for row in source_data]\n\telse:\n\t\tdata \u003d source_data\n\t\t\n\tfor record in data:\n\t\tif len(csv_headers) \u003d\u003d 0:\n\t\t\tcsv_headers \u003d record.keys()\n\t\t\tcsv_headers.sort()\n\t\t\tcsv_headers \u003d [str(i) for i in csv_headers]\n\t\tcsv_row \u003d []\n\t\tfor index in range(len(record)):\n\t\t\tcsv_row.append(str(record[csv_headers[index]]))\n\t\tcsv_data.append(csv_row)\n\t\n\ttry:\n\t\tcsv_dataset \u003d system.dataset.toDataSet(csv_headers, csv_data)\n\texcept Exception, e:\n\t\tsystem.perspective.print(str(e))\n\tcsv_export \u003d system.dataset.toCSV(csv_dataset)\n\tfilename \u003d \u0027{0}.csv\u0027.format(str(system.date.now()).replace(\u0027 \u0027, \u0027_\u0027))\n\tsystem.perspective.download(filename, csv_export)\n\t\n\tsystem.perspective.print(\u0027DONE DOWNLOADING TABLE DATA\u0027)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "SettingsButton",
"tooltip": {
"enabled": true,
"location": "top-left",
"text": "Download Table Contents"
}
},
"position": {
"basis": "30px"
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "LEN({..../Table.props.data})\u003e0"
},
"type": "expr"
}
}
},
"props": {
"path": "material/cloud_download",
"style": {
"classes": "General/Button",
"marginRight": 10
}
},
"type": "ia.display.icon"
}
],
"meta": {
"name": "TableActions",
"tooltip": {
"location": "top-right"
}
},
"position": {
"grow": 1
},
"props": {
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "TableHeader"
},
"position": {
"shrink": 0
},
"props": {
"justify": "space-between",
"style": {
"borderBottomStyle": "solid",
"borderBottomWidth": 1,
"cursor": "pointer"
}
},
"type": "ia.container.flex"
},
{
"events": {
"component": {
"onSelectionChange": {
"config": {
"script": "\t# validate the selection data is not null\n\tif self.props.selection.data:\n\t\tfilename \u003d self.props.selection.data[0].Filename\n\t\tself.view.custom.selected_file \u003d filename\n\t\t# send message to update selected file on parent container\n\t\tsuffix \u003d self.view.params.suffix\n\t\tpayload \u003d {\u0027image\u0027: filename.replace(suffix, \u0027\u0027)}\n\t\tsystem.perspective.sendMessage(\u0027update_selected_image\u0027, payload, scope\u003d\u0027session\u0027)\n\t"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Table"
},
"position": {
"basis": "370px",
"shrink": 0
},
"propConfig": {
"props.data": {
"binding": {
"config": {
"path": "view.params.files"
},
"type": "property"
}
},
"props.filter.enabled": {
"binding": {
"config": {
"path": "../TableHeader/TableActions/FilterCheck.props.selected"
},
"type": "property"
},
"onChange": {
"enabled": null,
"script": "\tif not getattr(currentValue, \u0027value\u0027, None):\n\t\t# clear filter text when filter is disabled\n\t\tself.props.filter.text \u003d \u0027\u0027\n\t\t"
}
}
},
"props": {
"columns": [
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "Filename",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": "Filename"
},
"justify": "center",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": ""
},
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "Size",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": "Size (bytes)"
},
"justify": "center",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": ""
},
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "LastModified",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": "Last Updated"
},
"justify": "center",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": ""
},
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "Key",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": "Key"
},
"justify": "center",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": ""
},
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "ETag",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": "ETag"
},
"justify": "center",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": false,
"width": ""
},
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "StorageClass",
"filter": {
"boolean": {
"condition": ""
},
"date": {
"condition": "",
"value": ""
},
"enabled": false,
"number": {
"condition": "",
"value": ""
},
"string": {
"condition": "",
"value": ""
},
"visible": "on-hover"
},
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "center",
"style": {
"classes": ""
},
"title": "Storage Class"
},
"justify": "center",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": false,
"width": ""
}
],
"filter": {},
"style": {
"margin": "10px"
}
},
"type": "ia.display.table"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "100%",
"grow": 1
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "activate-filter",
"pageScope": true,
"script": "\t# implement your handler here\n\tfilter_position \u003d payload[\u0027id\u0027]\n\tsystem.perspective.print(filter_position)\n\tadd \u003d True\n\tfor filter in self.view.custom.filters.active:\n\t\tif filter.id \u003d\u003d filter_position:\n\t\t\tadd \u003d False\n\tif add:\n\t\tfor filter in self.view.custom.filters.deactive:\n\t\t\tif filter.id \u003d\u003d filter_position:\t\t\t\t\n\t\t\t\tself.view.custom.filters.active.append(filter)",
"sessionScope": true,
"viewScope": false
},
{
"messageType": "deactivate-filter",
"pageScope": true,
"script": "\tfilter_position \u003d payload[\u0027id\u0027]\n\tsystem.perspective.print(filter_position)\n\t\n\tif filter_position \u003d\u003d -1 :\n\t\tself.view.custom.filters.active \u003d []\n\telse:\n\t\tfor index, filter in enumerate(self.view.custom.filters.active):\n\t\t\tif filter.id \u003d\u003d filter_position:\n\t\t\t\tsystem.perspective.print(filter.id)\n\t\t\t\tself.view.custom.filters.active.pop(index)\n\n#\tfor filter in self.view.custom.filter_menu_data:\n#\t\tif filter.filter_id \u003d\u003d filter_position:\n#\t\t\tsystem.perspective.print(filter.filter_id)\n#\t\t\tfilter.active \u003d False\n#\t\t\tbreak",
"sessionScope": true,
"viewScope": false
},
{
"messageType": "column-visibility",
"pageScope": true,
"script": "\t# implement your handler here\n\ttable_columns \u003d self.getChild(\"FlexContainer\").getChild(\"Table\").props.columns\n\tfor table_column in table_columns:\n\t\t#if payload.keys()[0] \u003d\u003d table_column[\u0027field\u0027]:\n\t\tif payload.keys()[0] \u003d\u003d table_column[\u0027header\u0027][\u0027title\u0027]:\n\t\t\ttable_column.visible \u003d payload.values()[0]",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.container.flex"
}
}