diff --git a/Makefile b/Makefile index e24a507fec8..befe59f8b4a 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,14 @@ down-swarm: docker-compose -f services/docker-compose.yml -f services/docker-compose.deploy.yml down docker swarm leave -f +stack-up: + docker swarm init + POSTGRES_USER=simcore POSTGRES_PASSWORD=simcore POSTGRES_DB=simcoredb RABBITMQ_USER=simcore RABBITMQ_PASSWORD=simcore RABBITMQ_PROGRESS_CHANNEL=comp.backend.channels.progress RABBITMQ_LOG_CHANNEL=comp.backend.channels.log S3_ENDPOINT=minio:9000 S3_ACCESS_KEY=12345678 S3_SECRET_KEY=12345678 S3_BUCKET_NAME=simcore docker stack deploy -c services/docker-compose.yml -c services/docker-compose.deploy.yml osparc + +stack-down: + docker stack rm osparc + docker swarm leave -f + pylint: # See exit codes and command line https://pylint.readthedocs.io/en/latest/user_guide/run.html#exit-codes /bin/bash -c "pylint --rcfile=.pylintrc $(PY_FILES)" diff --git a/packages/s3wrapper/src/s3wrapper/s3_client.py b/packages/s3wrapper/src/s3wrapper/s3_client.py index 0c8af42c315..ff81360d56a 100644 --- a/packages/s3wrapper/src/s3wrapper/s3_client.py +++ b/packages/s3wrapper/src/s3wrapper/s3_client.py @@ -130,6 +130,14 @@ def list_objects(self, bucket_name, recursive=False): return [] + def list_objects_v2(self, bucket_name, recursive=False): + try: + return self.client.list_objects_v2(bucket_name, recursive=recursive) + except ResponseError as _err: + logging.exception("Could not list objects") + + return [] + def remove_objects(self, bucket_name, objects): try: for del_err in self.client.remove_objects(bucket_name, objects): diff --git a/packages/simcore-sdk/src/simcore_sdk/config/docker.py b/packages/simcore-sdk/src/simcore_sdk/config/docker.py index e382f7cbdf0..7c8aac130dc 100644 --- a/packages/simcore-sdk/src/simcore_sdk/config/docker.py +++ b/packages/simcore-sdk/src/simcore_sdk/config/docker.py @@ -7,15 +7,19 @@ def __init__(self): self._registry = "masu.speag.com" self._user = "z43" self._pwd = "z43" - + @property def registry(self): return self._registry + "/v2" - + + @property + def registry_name(self): + return self._registry + @property def user(self): return self._user @property def pwd(self): - return self._pwd \ No newline at end of file + return self._pwd diff --git a/packages/simcore-sdk/src/simcore_sdk/config/s3.py b/packages/simcore-sdk/src/simcore_sdk/config/s3.py index f0c799f7b95..76f49cf07e6 100644 --- a/packages/simcore-sdk/src/simcore_sdk/config/s3.py +++ b/packages/simcore-sdk/src/simcore_sdk/config/s3.py @@ -3,10 +3,10 @@ """ from os import environ as env -S3_ENDPOINT = env.get("S3_ENDPOINT", "") -S3_ACCESS_KEY = env.get("S3_ACCESS_KEY", "") -S3_SECRET_KEY = env.get("S3_SECRET_KEY", "") -S3_BUCKET_NAME = env.get("S3_BUCKET_NAME", "") +S3_ENDPOINT = env.get("S3_ENDPOINT", "minio:9000") +S3_ACCESS_KEY = env.get("S3_ACCESS_KEY", "12345678") +S3_SECRET_KEY = env.get("S3_SECRET_KEY", "12345678") +S3_BUCKET_NAME = env.get("S3_BUCKET_NAME", "simcore") class Config(): def __init__(self): @@ -14,19 +14,19 @@ def __init__(self): self._access_key = S3_ACCESS_KEY self._secret_key = S3_SECRET_KEY self._bucket_name = S3_BUCKET_NAME - + @property def endpoint(self): return self._endpoint - + @property def access_key(self): return self._access_key - + @property def secret_key(self): return self._secret_key @property def bucket_name(self): - return self._bucket_name \ No newline at end of file + return self._bucket_name diff --git a/services/director/source/director.py b/services/director/source/director.py index 9fef43968f8..b74452b4e4b 100644 --- a/services/director/source/director.py +++ b/services/director/source/director.py @@ -102,6 +102,11 @@ def stop_service(): _LOGGER.exception("Failed to stop service") abort(500) +@APP.route('/list_repositories', methods=['GET']) +def list_repositories(): + repos = registry_proxy.get_repo_details() + + return json.dumps(repos) if __name__ == "__main__": APP.run(host='0.0.0.0', debug=False, port=8001, threaded=True) diff --git a/services/director/source/registry_proxy.py b/services/director/source/registry_proxy.py index 973a7bd6de4..9e0e50c7909 100644 --- a/services/director/source/registry_proxy.py +++ b/services/director/source/registry_proxy.py @@ -86,3 +86,41 @@ def get_service_sub_name(repository_name): if last_suffix_index < 0: raise Exception('Invalid service name: ' + repository_name) return list_of_suffixes[last_suffix_index] + +def _get_repo_details(repo): + #pylint: disable=too-many-nested-blocks + current_repo = [] + if "/comp/" in repo: + req_images = registry_request(repo + '/tags/list') + im_data = req_images.json() + tags = im_data['tags'] + for tag in tags: + image_tags = {} + label_request = registry_request(repo + '/manifests/' + tag) + label_data = label_request.json() + labels = json.loads(label_data["history"][0]["v1Compatibility"])["container_config"]["Labels"] + if labels: + for key in labels.keys(): + if key.startswith("io.simcore."): + label_data = json.loads(labels[key]) + for label_key in label_data.keys(): + image_tags[label_key] = label_data[label_key] + if image_tags: + current_repo.append(image_tags) + + return current_repo + +def get_repo_details(): + request_result = registry_request('_catalog') + + repos = request_result.json()['repositories'] + repositories = {} + for repo in repos: + details = _get_repo_details(repo) + if details: + repositories[repo] = details + + result_json = json.dumps(repositories) + + + return result_json diff --git a/services/docker-compose.deploy.yml b/services/docker-compose.deploy.yml index 91b5e85e59f..305bb2e4b3c 100644 --- a/services/docker-compose.deploy.yml +++ b/services/docker-compose.deploy.yml @@ -23,3 +23,5 @@ services: constraints: - node.platform.os == linux - node.role == manager + sidecar: + image: services_sidecar:latest diff --git a/services/docker-compose.devel.yml b/services/docker-compose.devel.yml index fc59d5bc322..e9e1e5255e6 100644 --- a/services/docker-compose.devel.yml +++ b/services/docker-compose.devel.yml @@ -22,7 +22,7 @@ services: volumes: - ./web/server:/home/scu/server - ./web/client/source-output:/home/scu/client - - ../packages/simcore-sdk/src:/home/scu/packages + - ../packages:/home/scu/packages depends_on: - webclient #-------------------------------------------------------------------- diff --git a/services/sidecar/src/sidecar/sidecar.py b/services/sidecar/src/sidecar/sidecar.py index 6c9ddbdf3da..1b88a31711e 100644 --- a/services/sidecar/src/sidecar/sidecar.py +++ b/services/sidecar/src/sidecar/sidecar.py @@ -59,6 +59,7 @@ def _create_shared_folders(self): def _process_task_input(self, port, input_ports): port_name = port['key'] port_value = port['value'] + _LOGGER.debug("PROCESSING %s %s", port_name, port_value) _LOGGER.debug(type(port_value)) if isinstance(port_value, str) and port_value.startswith("link."): if port['type'] == 'file-url': @@ -91,6 +92,9 @@ def _process_task_input(self, port, input_ports): for oport in other_task.output: if oport['key'] == other_output_port_id: input_ports[port_name] = oport['value'] + else: + _LOGGER.debug('Non link data %s : %s', port_name, port_value) + input_ports[port_name] = port_value def _process_task_inputs(self): """ Writes input key-value pairs into a dictionary @@ -110,16 +114,25 @@ def _process_task_inputs(self): _LOGGER.debug(port) self._process_task_input(port, input_ports) + _LOGGER.debug('DUMPING json') #dump json file if input_ports: file_name = os.path.join(self._executor.in_dir, 'input.json') with open(file_name, 'w') as f: json.dump(input_ports, f) + _LOGGER.debug('DUMPING DONE') + def _pull_image(self): + _LOGGER.debug('PULLING IMAGE') + _LOGGER.debug('reg %s user %s pwd %s', self._docker.registry, self._docker.registry_user,self._docker.registry_pwd ) + + self._docker.client.login(registry=self._docker.registry, username=self._docker.registry_user, password=self._docker.registry_pwd) + _LOGGER.debug('img %s tag %s', self._docker.image_name, self._docker.image_tag) + self._docker.client.images.pull(self._docker.image_name, tag=self._docker.image_tag) def _bg_job(self, task, log_file): @@ -213,7 +226,7 @@ def _process_task_log(self): def initialize(self, task): self._task = task - self._docker.image_name = task.image['name'] + self._docker.image_name = self._docker.registry_name + "/" + task.image['name'] self._docker.image_tag = task.image['tag'] self._executor.in_dir = os.path.join("/", "input", task.job_id) self._executor.out_dir = os.path.join("/", "output", task.job_id) diff --git a/services/sidecar/src/sidecar/sidecar_utils.py b/services/sidecar/src/sidecar/sidecar_utils.py index c132bca9f87..cd68898cc44 100644 --- a/services/sidecar/src/sidecar/sidecar_utils.py +++ b/services/sidecar/src/sidecar/sidecar_utils.py @@ -38,6 +38,7 @@ def __init__(self): self._config = docker_config() self.client = docker.from_env(version='auto') self.registry = self._config.registry + self.registry_name = self._config.registry_name self.registry_user = self._config.user self.registry_pwd = self._config.pwd self.image_name = "" diff --git a/services/web/Dockerfile b/services/web/Dockerfile index 49b498b8698..504a33b6798 100644 --- a/services/web/Dockerfile +++ b/services/web/Dockerfile @@ -41,8 +41,7 @@ RUN apk add --no-cache \ ENV HOME /home/scu ENV SIMCORE_WEB_OUTDIR $HOME/client -ENV PYTHONPATH "$HOME/server/src:$HOME/packages" - +ENV PYTHONPATH "$HOME/server/src:$HOME/packages/simcore-sdk/src:$HOME/packages/s3wrapper/src" WORKDIR /home/scu @@ -91,7 +90,7 @@ RUN pip3 install --no-cache-dir -r requirements/prod.txt && \ rm -rf requirements # 2. install 2nd party packages -COPY --chown=scu:scu packages/simcore-sdk/src packages +COPY --chown=scu:scu packages packages # 3. install client COPY --from=services_webclient:build --chown=scu:scu /home/scu/client/build-output client diff --git a/services/web/client/source/class/qxapp/components/form/Auto.js b/services/web/client/source/class/qxapp/components/form/Auto.js index 7df5597175d..65bc2122484 100644 --- a/services/web/client/source/class/qxapp/components/form/Auto.js +++ b/services/web/client/source/class/qxapp/components/form/Auto.js @@ -45,6 +45,8 @@ * */ +/* eslint no-warning-comments: "off" */ + qx.Class.define("qxapp.components.form.Auto", { extend : qx.ui.form.Form, include : [qx.locale.MTranslation], @@ -366,6 +368,10 @@ qx.Class.define("qxapp.components.form.Auto", { ); }, __addField: function(s) { + // FIXME: OM why null? + if (s === null) { + return; + } let option = { exposable: s.exposable }; // for passing info into the form renderer @@ -384,12 +390,21 @@ qx.Class.define("qxapp.components.form.Auto", { } s.set.value = s.defaultValue; } + // FIXME: This should go away + if (s.value) { + if (!s.set) { + s.set = {}; + } + s.set.value = s.value; + } if (!s.widget) { s.widget = { string: "text", integer: "spinner", + number: "spinner", bool: "checkBox", - fileUrl: "fileButton" + "file-url": "fileButton", + "folder-url": "fileButton" }[s.type]; } let control; @@ -405,6 +420,10 @@ qx.Class.define("qxapp.components.form.Auto", { break; case "spinner": control = new qx.ui.form.Spinner(); + control.set({ + maximum: 10000, + minimum: -10000 + }); setup = this.__setupSpinner; break; case "password": diff --git a/services/web/client/source/class/qxapp/components/workbench/NodeBase.js b/services/web/client/source/class/qxapp/components/workbench/NodeBase.js index 5f640c13b7b..79a477dccb7 100644 --- a/services/web/client/source/class/qxapp/components/workbench/NodeBase.js +++ b/services/web/client/source/class/qxapp/components/workbench/NodeBase.js @@ -238,7 +238,7 @@ qx.Class.define("qxapp.components.workbench.NodeBase", { label.isInput = isInput; label.portType = portData.type; - label.ui = new qx.ui.basic.Label(portData.label).set({ + label.ui = new qx.ui.basic.Label(portData.key).set({ height: 16, draggable: true, droppable: true diff --git a/services/web/client/source/class/qxapp/components/workbench/Workbench.js b/services/web/client/source/class/qxapp/components/workbench/Workbench.js index 94da8c6ccd7..3148c6cfb02 100644 --- a/services/web/client/source/class/qxapp/components/workbench/Workbench.js +++ b/services/web/client/source/class/qxapp/components/workbench/Workbench.js @@ -208,7 +208,7 @@ qx.Class.define("qxapp.components.workbench.Workbench", { var node = d["Node"]; var msg = d["Message"]; this.__updateLogger(node, msg); - }); + }, this); } socket.emit("logger"); @@ -220,7 +220,7 @@ qx.Class.define("qxapp.components.workbench.Workbench", { var node = d["Node"]; var progress = 100*Number.parseFloat(d["Progress"]).toFixed(4); this.updateProgress(node, progress); - }); + }, this); } if (this.getCanStart()) { @@ -811,9 +811,10 @@ qx.Class.define("qxapp.components.workbench.Workbench", { // post pipeline let currentPipeline = this.__serializeData(); console.log(currentPipeline); - var req = new qx.io.request.Xhr(); - var data = {}; - data["pipeline_mockup_id"] = currentPipeline; + let req = new qx.io.request.Xhr(); + let data = {}; + data = currentPipeline; + data["pipeline_mockup_id"] = qxapp.utils.Utils.uuidv4(); req.set({ url: "/start_pipeline", method: "POST", @@ -832,7 +833,7 @@ qx.Class.define("qxapp.components.workbench.Workbench", { }, __onPipelinesubmitted: function(e) { - var req = e.getTarget(); + let req = e.getTarget(); console.debug("Everything went fine!!"); console.debug("status : ", req.getStatus()); console.debug("phase : ", req.getPhase()); diff --git a/services/web/client/source/class/qxapp/components/workbench/servicesCatalogue/ServicesCatalogue.js b/services/web/client/source/class/qxapp/components/workbench/servicesCatalogue/ServicesCatalogue.js index 11febdd5816..c0247600c38 100644 --- a/services/web/client/source/class/qxapp/components/workbench/servicesCatalogue/ServicesCatalogue.js +++ b/services/web/client/source/class/qxapp/components/workbench/servicesCatalogue/ServicesCatalogue.js @@ -23,20 +23,26 @@ qx.Class.define("qxapp.components.workbench.servicesCatalogue.ServicesCatalogue" let searchLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)); let searchLabel = new qx.ui.basic.Label("Search"); searchLayout.add(searchLabel); - let textfield = new qx.ui.form.TextField(); + let textfield = this.__textfield = new qx.ui.form.TextField(); textfield.setLiveUpdate(true); searchLayout.add(textfield, { flex: 1 }); this.add(searchLayout); - this.__allServices = qxapp.data.Fake.getServices(); + this.__allServices = qxapp.data.Fake.getFakeServices(); + let store = qxapp.data.Store.getInstance(); + store.addListener("servicesRegistered", function(e) { + console.log("servicesRegistered", e.getData()); + this.__addNewData(e.getData()); + }, this); + store.getServices(); // TODO: OM & PC replace this with delegates - let rawData2 = []; + let names = []; for (let i = 0; i < this.__allServices.length; i++) { - rawData2.push(this.__allServices[i].name); + names.push(this.__allServices[i].name); } - this.__rawData = new qx.data.Array(rawData2); + let rawData = new qx.data.Array(names); this.__list = new qx.ui.form.List(); this.add(this.__list, { @@ -45,7 +51,7 @@ qx.Class.define("qxapp.components.workbench.servicesCatalogue.ServicesCatalogue" this.__list.setSelectionMode("one"); // create the controller - this.__controller = new qx.data.controller.List(this.__rawData, this.__list); + this.__controller = new qx.data.controller.List(rawData, this.__list); // controller.setLabelPath("name"); // create the filter @@ -97,7 +103,7 @@ qx.Class.define("qxapp.components.workbench.servicesCatalogue.ServicesCatalogue" members: { __allServices: null, - __rawData: null, + __textfield: null, __list: null, __controller: null, __contextNodeId: null, @@ -136,6 +142,17 @@ qx.Class.define("qxapp.components.workbench.servicesCatalogue.ServicesCatalogue" this.__controller.setModel(filteredData); }, + __addNewData: function(newData) { + console.log(this.__controller.getModel()); + let names = []; + this.__allServices = this.__allServices.concat(newData); + for (let i = 0; i < this.__allServices.length; i++) { + names.push(this.__allServices[i].name); + } + let rawData = new qx.data.Array(names); + this.__controller.setModel(rawData); + }, + __keyEvent: function(keyEvent) { if (keyEvent.getKeyIdentifier() === "Enter") { this.__onAddService(); diff --git a/services/web/client/source/class/qxapp/components/workbench/widgets/FileManager.js b/services/web/client/source/class/qxapp/components/workbench/widgets/FileManager.js index 57bb837d850..1e6d1349edd 100644 --- a/services/web/client/source/class/qxapp/components/workbench/widgets/FileManager.js +++ b/services/web/client/source/class/qxapp/components/workbench/widgets/FileManager.js @@ -16,7 +16,7 @@ qx.Class.define("qxapp.components.workbench.widgets.FileManager", { this.getContentElement().add(input); - let pick = new qx.ui.form.Button(this.tr("Add file")); + let pick = new qx.ui.form.Button(this.tr("Add file(s)")); this.add(pick); // Add an event listener diff --git a/services/web/client/source/class/qxapp/data/Converters.js b/services/web/client/source/class/qxapp/data/Converters.js new file mode 100644 index 00000000000..c05148997f3 --- /dev/null +++ b/services/web/client/source/class/qxapp/data/Converters.js @@ -0,0 +1,27 @@ + +qx.Class.define("qxapp.data.Converters", { + type: "static", + + statics: { + registryToMetadata: function(data) { + let metadata = {}; + [ + "key", + "name", + "tag", + "description", + "authors", + "contact", + "inputs", + "outputs", + "settings" + ].forEach(field => { + metadata[field] = null; + if (Object.prototype.hasOwnProperty.call(data, field)) { + metadata[field] = data[field]; + } + }); + return metadata; + } + } +}); diff --git a/services/web/client/source/class/qxapp/data/Fake.js b/services/web/client/source/class/qxapp/data/Fake.js index e08389d13d4..2869f261fc8 100644 --- a/services/web/client/source/class/qxapp/data/Fake.js +++ b/services/web/client/source/class/qxapp/data/Fake.js @@ -93,9 +93,9 @@ qx.Class.define("qxapp.data.Fake", { "nodes": [{ "uuid": "dd329e10-a906-42da-a7b3-4c4fec4a786f", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 1", - "desc": "Node 1", + "description": "Node 1", "position": { "x": 50, "y": 100 @@ -103,28 +103,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -132,9 +132,9 @@ qx.Class.define("qxapp.data.Fake", { }, { "uuid": "3fad99a2-31b3-48a2-9066-1a66fc21aa52", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 2", - "desc": "Node 2", + "description": "Node 2", "position": { "x": 50, "y": 300 @@ -142,28 +142,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -171,9 +171,9 @@ qx.Class.define("qxapp.data.Fake", { }, { "uuid": "3a97f542-93c4-419c-b5c9-bcf9ff3ada7e", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 3", - "desc": "Node 3", + "description": "Node 3", "position": { "x": 300, "y": 100 @@ -181,28 +181,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -210,9 +210,9 @@ qx.Class.define("qxapp.data.Fake", { }, { "uuid":"9c35ecbc-8219-4538-ba2e-bad8b6e64cda", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 4", - "desc": "Node 4", + "description": "Node 4", "position": { "x": 300, "y": 300 @@ -220,28 +220,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -249,9 +249,9 @@ qx.Class.define("qxapp.data.Fake", { }, { "uuid":"51ad1bc0-615e-406a-9886-e3639f51208c", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 5", - "desc": "Node 5", + "description": "Node 5", "position": { "x": 550, "y": 200 @@ -259,28 +259,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -288,9 +288,9 @@ qx.Class.define("qxapp.data.Fake", { }, { "uuid":"5df77702-29d5-4513-b3f8-f2a40ed317fe", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 6", - "desc": "Node 6", + "description": "Node 6", "position": { "x": 800, "y": 100 @@ -298,28 +298,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -327,9 +327,9 @@ qx.Class.define("qxapp.data.Fake", { }, { "uuid": "de2c84ed-a3bc-47c2-b54d-84a5c048236b", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 7", - "desc": "Node 7", + "description": "Node 7", "position": { "x": 800, "y": 300 @@ -337,28 +337,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -366,9 +366,9 @@ qx.Class.define("qxapp.data.Fake", { }, { "uuid": "ba22104c-99e1-45c9-a09d-228400a6f9fb", "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Node 8", - "desc": "Node 8", + "description": "Node 8", "position": { "x": 1050, "y": 200 @@ -376,28 +376,28 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "value": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -475,7 +475,7 @@ qx.Class.define("qxapp.data.Fake", { "key": "node1", "tag": "1.0", "name": "Node 1", - "desc": "Node 1", + "description": "Node 1", "position": { "x": 50, "y": 100 @@ -484,19 +484,19 @@ qx.Class.define("qxapp.data.Fake", { "outputs": [{ "key": "out_1", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": "" }, { "key": "out_2", "label": "String", - "desc": "String", + "description": "String", "type": "string", "value": "" }, { "key": "out_3", "label": "Bool", - "desc": "Bool", + "description": "Bool", "type": "bool", "value": null }], @@ -506,7 +506,7 @@ qx.Class.define("qxapp.data.Fake", { "key": "node2", "tag": "1.0", "name": "Node 2", - "desc": "Node 2", + "description": "Node 2", "position": { "x": 400, "y": 100 @@ -514,19 +514,19 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }, { "key": "in_2", "label": "String", - "desc": "String", + "description": "String", "type": "string", "value": null }, { "key": "in_3", "label": "Bool", - "desc": "Bool", + "description": "Bool", "type": "bool", "value": null }], @@ -534,13 +534,13 @@ qx.Class.define("qxapp.data.Fake", { "settings": [{ "key": "sett_1", "label": "Bool_1", - "desc": "Bool_1", + "description": "Bool_1", "type": "bool", "value": 0 }, { "key": "sett_2", "label": "Bool_2", - "desc": "Bool_2", + "description": "Bool_2", "type": "bool", "value": 0 }] @@ -549,7 +549,7 @@ qx.Class.define("qxapp.data.Fake", { "key": "node3", "tag": "1.0", "name": "Node 3", - "desc": "Node 3", + "description": "Node 3", "position": { "x": 400, "y": 300 @@ -557,13 +557,13 @@ qx.Class.define("qxapp.data.Fake", { "inputs": [{ "key": "in_1", "label": "String", - "desc": "String", + "description": "String", "type": "string", "value": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "value": null }], @@ -575,12 +575,12 @@ qx.Class.define("qxapp.data.Fake", { return temp2Data; }, - getServices: function() { - let availableServices = []; - Array.prototype.push.apply(availableServices, qxapp.data.Fake.getProducers()); - Array.prototype.push.apply(availableServices, qxapp.data.Fake.getComputationals()); - Array.prototype.push.apply(availableServices, qxapp.data.Fake.getAnalyses()); - return availableServices; + getFakeServices: function() { + let fakeServices = []; + Array.prototype.push.apply(fakeServices, qxapp.data.Fake.getProducers()); + Array.prototype.push.apply(fakeServices, qxapp.data.Fake.getComputationals()); + Array.prototype.push.apply(fakeServices, qxapp.data.Fake.getAnalyses()); + return fakeServices; }, getProducers: function() { @@ -588,11 +588,11 @@ qx.Class.define("qxapp.data.Fake", { "key": "modeler", "tag": "1.0", "name": "Modeler", - "desc": "Modeler", + "description": "Modeler", "inputs": [{ "key": "in_1", "label": "ViPModel", - "desc": "Select ViP Model", + "description": "Select ViP Model", "type": "string", "defaultValue": "rat", "widget": "selectBox", @@ -612,7 +612,7 @@ qx.Class.define("qxapp.data.Fake", { "outputs": [{ "key": "out_1", "label": "Scene", - "desc": "Scene", + "description": "Scene", "type": "scene", "defaultValue": null }], @@ -625,13 +625,13 @@ qx.Class.define("qxapp.data.Fake", { "key": "FileManager", "tag": "1.0", "name": "File Manager", - "desc": "File Manager", + "description": "File Manager", "inputs": [], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "defaultValue": null }], "settings": [] @@ -639,24 +639,24 @@ qx.Class.define("qxapp.data.Fake", { "key": "RandomNumberGeneratorID", "tag": "1.0", "name": "Random Number Generator", - "desc": "Random Number Generator", + "description": "Random Number Generator", "inputs": [{ "key": "in_1", "label": "Number Min", - "desc": "Number Min", + "description": "Number Min", "type": "integer", "defaultValue": 0 }, { "key": "in_2", "label": "Number Max", - "desc": "Number Max", + "description": "Number Max", "type": "integer", "defaultValue": 10 }], "outputs": [{ "key": "out_1", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "defaultValue": null }], @@ -670,53 +670,53 @@ qx.Class.define("qxapp.data.Fake", { "key": "ColleenClancy", "tag": "1.0", "name": "Colleen Clancy - dummy", - "desc": "Colleen Clancy - dummy", + "description": "Colleen Clancy - dummy", "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "defaultValue": null }, { "key": "in_2", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "defaultValue": null }, { "key": "in_3", "label": "NaValue", - "desc": "Na blocker drug concentration", + "description": "Na blocker drug concentration", "type": "integer", "defaultValue": 10 }, { "key": "in_4", "label": "KrValue", - "desc": "Kr blocker drug concentration", + "description": "Kr blocker drug concentration", "type": "integer", "defaultValue": 10 }, { "key": "in_5", "label": "BCLValue", - "desc": "Basic cycle length (BCL)", + "description": "Basic cycle length (BCL)", "type": "integer", "defaultValue": 10 }, { "key": "in_6", "label": "beatsValue", - "desc": "Number of beats", + "description": "Number of beats", "type": "integer", "defaultValue": 10 }, { "key": "in_7", "label": "LigandValue", - "desc": "Ligand concentration", + "description": "Ligand concentration", "type": "integer", "defaultValue": 10 }, { "key": "in_8", "label": "cAMKIIValue", - "desc": "Adjust cAMKII activity level", + "description": "Adjust cAMKII activity level", "type": "string", "widget": "selectBox", "cfg": { @@ -733,7 +733,7 @@ qx.Class.define("qxapp.data.Fake", { }, { "key": "in_9", "label": "solverMode", - "desc": "Solver Mode", + "description": "Solver Mode", "type": "string", "widget": "selectBox", "cfg": { @@ -751,7 +751,7 @@ qx.Class.define("qxapp.data.Fake", { "outputs": [{ "key": "out_1", "label": "csv-url", - "desc": "csv-url", + "description": "csv-url", "type": "csv-url", "defaultValue": null }], @@ -760,56 +760,56 @@ qx.Class.define("qxapp.data.Fake", { "key": "Computational2", "tag": "1.0", "name": "Computational 2", - "desc": "Computational 2", + "description": "Computational 2", "inputs": [{ "key": "in_1", "label": "Scene", - "desc": "Scene", + "description": "Scene", "type": "scene", "defaultValue": null }], "outputs": [{ "key": "out_1", "label": "Numbers", - "desc": "Other numbers", + "description": "Other numbers", "type": "integer", "defaultValue": null }], "settings": [] }, { "key": "masu.speag.com/simcore/services/comp/sleeper", - "tag": "1.0", + "tag": "0.0.1", "name": "Sleeper", - "desc": "Sleeper", + "description": "Sleeper", "inputs": [{ "key": "in_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "defaultValue": null }, { "key": "in_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "defaultValue": 0 }, { "key": "in_3", "label": "Number", - "desc": "Sleep extra sec", + "description": "Sleep extra sec", "type": "integer", "defaultValue": 0 }], "outputs": [{ "key": "out_1", "label": "File-url", - "desc": "File-url", - "type": "fileUrl", + "description": "File-url", + "type": "file-url", "defaultValue": null }, { "key": "out_2", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "defaultValue": 0 }], @@ -823,11 +823,11 @@ qx.Class.define("qxapp.data.Fake", { "key": "jupyter-base-notebook", "tag": "1.0", "name": "Jupyter", - "desc": "Jupyter", + "description": "Jupyter", "inputs": [{ "key": "in_1", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "defaultValue": null }], @@ -841,11 +841,11 @@ qx.Class.define("qxapp.data.Fake", { "key": "Analysis2", "tag": "1.0", "name": "Analysis 2", - "desc": "Analysis 2", + "description": "Analysis 2", "inputs": [{ "key": "in_1", "label": "Number", - "desc": "Number", + "description": "Number", "type": "integer", "defaultValue": null }], @@ -855,11 +855,11 @@ qx.Class.define("qxapp.data.Fake", { "key": "csv-table-graph", "tag": "1.0", "name": "CSV Viewer", - "desc": "CSV Viewer", + "description": "CSV Viewer", "inputs": [{ "key": "in_1", "label": "csv-url", - "desc": "csv-url", + "description": "csv-url", "type": "csv-url", "defaultValue": null }], diff --git a/services/web/client/source/class/qxapp/data/Store.js b/services/web/client/source/class/qxapp/data/Store.js new file mode 100644 index 00000000000..ab815d840aa --- /dev/null +++ b/services/web/client/source/class/qxapp/data/Store.js @@ -0,0 +1,35 @@ +qx.Class.define("qxapp.data.Store", { + extend: qx.core.Object, + + type : "singleton", + + events: { + "servicesRegistered": "qx.event.type.Event" + }, + + members: { + getServices: function() { + let req = new qx.io.request.Xhr(); + req.set({ + url: "/repositories", + method: "GET" + }); + req.addListener("success", function(e) { + let requ = e.getTarget(); + const listOfRepositories = JSON.parse(requ.getResponse()); + let services = []; + for (const key of Object.keys(listOfRepositories)) { + const repo = listOfRepositories[key]; + const nTags = repo.length; + for (let i=0; i