You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2021/06/18 19:38:21 UTC
[airavata-django-portal] 04/20: AIRAVATA-3453 Integrated
jquery-textcomplete plugin
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch airavata-3453
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit e54afd181f296ec1985f98c959c04226adb261ee
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Mon May 3 11:15:17 2021 -0400
AIRAVATA-3453 Integrated jquery-textcomplete plugin
To get the plugin and the hide/show logic to work
I needed to switch from Vue slots to native slots
which are now dynamically generated for exp
inputs in ExperimentEditor.
---
django_airavata/apps/workspace/package.json | 1 +
.../jquery.textcomplete.css | 33 ++++
.../jquery.textcomplete.min.js | 3 +
.../js/web-components/ExperimentEditor.vue | 40 +++--
.../django_airavata_workspace/supcrtbl2.html | 180 +++++++++++++++++++--
django_airavata/apps/workspace/yarn.lock | 5 +
6 files changed, 236 insertions(+), 26 deletions(-)
diff --git a/django_airavata/apps/workspace/package.json b/django_airavata/apps/workspace/package.json
index 6d227b1..883c65d 100644
--- a/django_airavata/apps/workspace/package.json
+++ b/django_airavata/apps/workspace/package.json
@@ -37,6 +37,7 @@
"@vue/cli-plugin-unit-jest": "^3.3.0",
"@vue/cli-service": "^3.1.1",
"@vue/test-utils": "^1.0.0-beta.28",
+ "@vue/web-component-wrapper": "^1.3.0",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/jquery.textcomplete.css b/django_airavata/apps/workspace/static/django_airavata_workspace/jquery.textcomplete.css
new file mode 100644
index 0000000..37a761b
--- /dev/null
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/jquery.textcomplete.css
@@ -0,0 +1,33 @@
+/* Sample */
+
+.dropdown-menu {
+ border: 1px solid #ddd;
+ background-color: white;
+}
+
+.dropdown-menu li {
+ border-top: 1px solid #ddd;
+ padding: 2px 5px;
+}
+
+.dropdown-menu li:first-child {
+ border-top: none;
+}
+
+.dropdown-menu li:hover,
+.dropdown-menu .active {
+ background-color: rgb(110, 183, 219);
+}
+
+
+/* SHOULD not modify */
+
+.dropdown-menu {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.dropdown-menu a:hover {
+ cursor: pointer;
+}
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/jquery.textcomplete.min.js b/django_airavata/apps/workspace/static/django_airavata_workspace/jquery.textcomplete.min.js
new file mode 100644
index 0000000..ce1536d
--- /dev/null
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/jquery.textcomplete.min.js
@@ -0,0 +1,3 @@
+/*! jquery-textcomplete - v1.8.4 - 2017-08-29 */
+!function(a){if("function"==typeof define&&define.amd)define(["jquery"],a);else if("object"==typeof module&&module.exports){var b=require("jquery");module.exports=a(b)}else a(jQuery)}(function(a){if("undefined"==typeof a)throw new Error("jQuery.textcomplete requires jQuery");return+function(a){"use strict";var b=function(a){console.warn&&console.warn(a)},c=1;a.fn.textcomplete=function(d,e){var f=Array.prototype.slice.call(arguments);return this.each(function(){var g=this,h=a(this),i=h.da [...]
+//# sourceMappingURL=dist/jquery.textcomplete.min.map
\ No newline at end of file
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/web-components/ExperimentEditor.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/web-components/ExperimentEditor.vue
index fc36687..0de4bff 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/web-components/ExperimentEditor.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/web-components/ExperimentEditor.vue
@@ -10,16 +10,12 @@
</slot>
</div>
<template v-for="input in experiment.experimentInputs">
- <div :key="input.name" @input="updateInputValue($event, input)">
- <slot :name="input.name">
- {{ input.name }}
- <input
- v-if="input.type.name == 'STRING'"
- :name="`input:${input.name}`"
- :value="input.value"
- />
- </slot>
- <!-- TODO: add support for other input types -->
+ <div
+ :ref="input.name"
+ :key="input.name"
+ @input="updateInputValue($event, input)"
+ >
+ <!-- programmatically define slots as native slots (not Vue slots), see #mounted() -->
</div>
</template>
<slot name="save-button">
@@ -48,12 +44,32 @@ export default {
required: false,
},
},
- async created() {
+ async created() {},
+ async mounted() {
this.applicationModule = await getApplicationModule(this.applicationId);
this.appInterface = await getApplicationInterfaceForModule(
this.applicationId
);
this.experiment = await this.loadExperiment();
+ // vue-web-component-wrapper clones native slots and turns them into Vue
+ // slots which means they lose any event listeners and they basically aren't
+ // in the DOM any more. As a workaround, programmatically create native
+ // slots. See also https://github.com/vuejs/vue-web-component-wrapper/issues/38
+ this.$nextTick(() => {
+ for (const input of this.experiment.experimentInputs) {
+ const slot = document.createElement("slot");
+ slot.setAttribute("name", input.name);
+ if (input.type.name === "STRING") {
+ slot.textContent = `${input.name} `;
+ const textInput = document.createElement("input");
+ textInput.setAttribute("type", "text");
+ textInput.setAttribute("value", input.value);
+ slot.appendChild(textInput);
+ }
+ // TODO: add support for other input types
+ this.$refs[input.name][0].append(slot);
+ }
+ });
},
data() {
return {
@@ -105,7 +121,7 @@ export default {
const defaultProjectId = await getDefaultProjectId();
experiment.projectId = defaultProjectId;
experiment.userConfigurationData.computationalResourceScheduling.resourceHostId =
- "bigred3.uits.iu.edu_2141bf96-c458-4ecd-8759-aa3a08f31956";
+ "js-169-51.jetstream-cloud.org_6672e8fe-8d63-4bbe-8bf8-4ea04092e72f";
this.$emit("loaded", experiment);
return experiment;
}
diff --git a/django_airavata/apps/workspace/templates/django_airavata_workspace/supcrtbl2.html b/django_airavata/apps/workspace/templates/django_airavata_workspace/supcrtbl2.html
index 0d9c78f..638c6ce 100644
--- a/django_airavata/apps/workspace/templates/django_airavata_workspace/supcrtbl2.html
+++ b/django_airavata/apps/workspace/templates/django_airavata_workspace/supcrtbl2.html
@@ -8,6 +8,7 @@
{% comment %} {% render_bundle 'chunk-vendors' 'css' 'WORKSPACE' %} {% endcomment %}
{% comment %} {% render_bundle 'chunk-common' 'css' 'WORKSPACE' %} {% endcomment %}
{% comment %} {% render_bundle 'adpf' 'css' 'WORKSPACE' %} {% endcomment %}
+ <link href="{% static 'django_airavata_workspace/jquery.textcomplete.css' %}" rel="stylesheet" type="text/css">
{% endblock %}
{% block content %}
@@ -178,31 +179,32 @@
{% comment %} {% render_bundle 'chunk-common' 'js' 'WORKSPACE' %} {% endcomment %}
{% comment %} {% render_bundle 'adpf' 'js' 'WORKSPACE' %} {% endcomment %}
<script src="{% static 'django_airavata_workspace/wc/adpf.min.js' %}"></script>
+<script src="{% static 'django_airavata_workspace/jquery.textcomplete.min.js' %}"></script>
<script>
document.getElementById("experiment-editor").addEventListener('loaded', e => {
const [experiment] = e.detail;
for (const input of experiment.experimentInputs) {
- // TODO: just iterate over the slotted inputs
- const inputEl = document.querySelector(`[name="input:${input.name}"]`)
- if (!inputEl) {
- console.warn("Could not find input editor for ", input);
- } else {
- if (inputEl.type === 'radio') {
- const radios = document.querySelectorAll(`[name="input:${input.name}"]`);
- for (const radio of radios) {
+ const slotEl = document.querySelector(`[slot="${input.name}"]`);
+ // console.log("slotEl=", slotEl);
+ if (slotEl) {
+ const inputEls = slotEl.querySelectorAll('input');
+ // console.log("inputEls=", inputEls);
+ if (!inputEls || inputEls.length === 0) {
+ continue;
+ }
+ if (inputEls[0].type === 'text') {
+ inputEls[0].value = input.value;
+ } else if (inputEls[0].type === 'radio') {
+ for (radio of inputEls) {
if (radio.value === input.value) {
- // Have to set value with setAttribute so it is part of the DOM
- // since the slot content doesn't appear to get added to the custom
- // element until later. Setting as a property doesn't work.
- radio.setAttribute("checked", "checked");
+ radio.checked = true;
break;
}
}
- } else if (inputEl.type === 'text') {
- inputEl.setAttribute("value", input.value);
}
}
}
+ resetViews();
});
function validateExperiment(event) {
const [experiment] = event.detail;
@@ -213,5 +215,155 @@ function validateExperiment(event) {
}
}
document.getElementById('experiment-editor').addEventListener('save', validateExperiment);
+
+$('document').ready(function() {
+ $('#reaction').textcomplete([{
+ match: /(^|\b)(\S{1,})$/,
+ search: function (term, callback) {
+ var words = ["ALMANDINE","ANDRADITE","GROSSULAR","KNORRINGITE","MAJORITE","PYROPE","SPESSARTINE","CLINOHUMITE","FAYALITE","FORSTERITE","MONTICELLITE","TEPHROITE","ANDALUSITE","KYANITE","Al-MULLITE","Si-MULLITE","Fe-CHLORITOID","Mg-CHLORITOID","Mn-CHLORITOID","Fe-STAUROLITE","Mg-STAUROLITE","Mn-STAUROLITE","HYDROXY-TOPAZ","AKERMANITE","JULGOLDITE(FeFe)","MERWINITE","PUMPELLYITE(FeAl)","PUMPELLYITE(MgAl)","RANKINITE","SPURRITE","TILLEYITE","ZIRCON","CLINOZOISITE","EPIDOTE(ORDERED)"," [...]
+ callback($.map(words, function (word) {
+ return word.toLowerCase().indexOf(term.toLowerCase()) === 0 ? word : null;
+ }));
+ },replace: function (word) {
+ return word + ' ';
+ }
+ }]);
+});
+
+function resetViews() {
+ $('#lipVapSat').hide();
+ $('#indVar').hide();
+ $('#tabulationBaric').hide();
+ $('#tabulationChoric').hide();
+ $('#table').hide();
+ $('#univariantCurve').hide();
+ $('#univariantCalc').hide();
+ $('#isochores').hide();
+ $('#temp').hide();
+ $('#dH2OTemp').hide();
+ $('#logK').hide();
+ $('#isotherms').hide();
+ $('#dH2O').hide();
+ $('#tempDH2O').hide();
+ $('#isobars').hide();
+ $('#logKBoundingTemp').hide();
+ $('#logKBoundingPres').hide();
+ $('#presTemp').hide();
+ $('#pres').hide();
+ $('#tempPres').hide();
+ $('#lipVapSatTemp').hide();
+ $('#lipVapSatPres').hide();
+ $('#submit').hide();
+ if($('input:radio[name=solventPhase]:checked').val() == "0"){
+ $('#indVar').show();
+ if($('input:radio[name=independentStateVar]:checked').val() == "0"){
+ $('#tabulationChoric').show();
+ if($('input:radio[name=tabulationChoricOption]:checked').val() == "0"){
+ $('#table').show();
+ if($('input:radio[name=tableIncrement]:checked').val() == "0"){
+ $('#isochores').show();
+ $('#temp').show();
+ $('#submit').show();
+
+ }
+ else if($('input:radio[name=tableIncrement]:checked').val() == "1"){
+ $('#dH2OTemp').show();
+ $('#submit').show();
+ }
+ }
+ else if($('input:radio[name=tabulationChoricOption]:checked').val() == "1"){
+ $('#table').show();
+ if($('input:radio[name=tableIncrement]:checked').val() == "0"){
+ $('#isotherms').show();
+ $('#dH2O').show();
+ $('#submit').show();
+
+ }
+ else if($('input:radio[name=tableIncrement]:checked').val() == "1"){
+ $('#tempDH2O').show();
+ $('#submit').show();
+ }
+ }
+ }
+ else if($('input:radio[name=independentStateVar]:checked').val() == "1"){
+ $('#univariantCurve').show();
+ if($('input:radio[name=univariantCurveOption]:checked').val() == "0"){
+ $('#univariantCalc').show();
+ if($('input:radio[name=univariantCalcOption]:checked').val() == "0") {
+ $('#isobars').show();
+ $('#logK').show();
+ $('#logKBoundingTemp').show();
+ $('#submit').show();
+ }
+ else if($('input:radio[name=univariantCalcOption]:checked').val() == "1"){
+ $('#isotherms').show();
+ $('#logK').show();
+ $('#logKBoundingPres').show();
+ $('#submit').show();
+ }
+ }
+ if($('input:radio[name=univariantCurveOption]:checked').val() == "1"){
+ $('#tabulationBaric').show();
+ if($('input:radio[name=tabulationBaricOption]:checked').val() == "0"){
+ $('#table').show();
+ if($('input:radio[name=tableIncrement]:checked').val() == "0"){
+ $('#isobars').show();
+ $('#temp').show();
+ $('#submit').show();
+
+ }
+ else if($('input:radio[name=tableIncrement]:checked').val() == "1"){
+ $('#presTemp').show();
+ $('#submit').show();
+ }
+ }
+ else if($('input:radio[name=tabulationBaricOption]:checked').val() == "1"){
+ $('#table').show();
+ if($('input:radio[name=tableIncrement]:checked').val() == "0"){
+ $('#isotherms').show();
+ $('#pres').show();
+ $('#submit').show();
+ }
+ else if($('input:radio[name=tableIncrement]:checked').val() == "1"){
+ $('#tempPres').show();
+ $('#submit').show();
+ }
+ }
+ }
+
+ }
+ }
+ else if($('input:radio[name=solventPhase]:checked').val() == "1"){
+ $('#lipVapSat').show();
+ if($('input:radio[name=lipVapSatVar]:checked').val() == "0"){
+ $('#table').show();
+ if($('input:radio[name=tableIncrement]:checked').val() == "0"){
+ $('#temp').show();
+ $('#submit').show();
+ }
+ if($('input:radio[name=tableIncrement]:checked').val() == "1"){
+ $('#lipVapSatTemp').show();
+ $('#submit').show();
+ }
+ }
+ if($('input:radio[name=lipVapSatVar]:checked').val() == "1"){
+ $('#table').show();
+ if($('input:radio[name=tableIncrement]:checked').val() == "0"){
+ $('#pres').show();
+ $('#submit').show();
+ }
+ if($('input:radio[name=tableIncrement]:checked').val() == "1"){
+ $('#lipVapSatPres').show();
+ $('#submit').show();
+ }
+ }
+ }
+ }
+ $(document).ready(function() {
+ resetViews();
+ $("input:radio").change(function () {
+ resetViews();
+ });
+ });
</script>
{% endblock %}
diff --git a/django_airavata/apps/workspace/yarn.lock b/django_airavata/apps/workspace/yarn.lock
index a3e1e2a..2d5c8b1 100644
--- a/django_airavata/apps/workspace/yarn.lock
+++ b/django_airavata/apps/workspace/yarn.lock
@@ -1122,6 +1122,11 @@
resolved "https://registry.yarnpkg.com/@vue/web-component-wrapper/-/web-component-wrapper-1.2.0.tgz#bb0e46f1585a7e289b4ee6067dcc5a6ae62f1dd1"
integrity sha512-Xn/+vdm9CjuC9p3Ae+lTClNutrVhsXpzxvoTXXtoys6kVRX9FkueSUAqSWAyZntmVLlR4DosBV4pH8y5Z/HbUw==
+"@vue/web-component-wrapper@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz#b6b40a7625429d2bd7c2281ddba601ed05dc7f1a"
+ integrity sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==
+
"@webassemblyjs/ast@1.8.5":
version "1.8.5"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"