diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 467ad45c3..50cf1386c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -272,6 +272,9 @@ contributions. Run both the Webpack and Sass watchers simultaneously with `npm run watch:all`. +To debug TypeScript code in the browser, change the `devtool` setting in +`webpack.config.js`. + ### Updating embedded icon files ### Some icon files are stored as base64-encoded strings which describe PNG images diff --git a/karma.conf.js b/karma.conf.js index 5371d9e3a..bbe7c8a02 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -30,6 +30,7 @@ module.exports = function(config) { }; // simulate the way Django structures directories for static file serving serveDjangoPath(cfgObj, { + 'container': ['templates', 'static', 'test_assets'], 'pipeline': ['templates', 'static', 'test_assets'], 'portal': ['static'], }); diff --git a/kive/container/static/container/canvas/drydock.ts b/kive/container/static/container/canvas/drydock.ts index 31041a363..5ba834c23 100644 --- a/kive/container/static/container/canvas/drydock.ts +++ b/kive/container/static/container/canvas/drydock.ts @@ -1340,15 +1340,6 @@ export class CanvasState { this.dispatchChangeEvent({ removed: sel }); } - findMethodNode (method_pk: number): MethodNode { - for (let method of this.methods) { - if (method.pk === method_pk) { - return method; - } - } - return null; - } - findOutputNode (pk: number): OutputNode { for (let output of this.outputs) { if (output.pk === pk) { diff --git a/kive/container/static/container/canvas/drydock_objects.ts b/kive/container/static/container/canvas/drydock_objects.ts index 8142bd7f9..765c9f147 100644 --- a/kive/container/static/container/canvas/drydock_objects.ts +++ b/kive/container/static/container/canvas/drydock_objects.ts @@ -792,6 +792,12 @@ export class MethodNode extends BaseNode implements CNode { this.n_inputs = Object.keys(inputs).length; this.n_outputs = Object.keys(outputs).length; this.h = Math.max(this.n_inputs, this.n_outputs) * this.spacing; + if (this.n_inputs === 0) { + throw "No inputs passed to MethodNode." + } + if (this.n_outputs === 0) { + throw "No outputs passed to MethodNode." + } for (let input of this.inputs) { this.addInput(input); diff --git a/kive/container/static/container/container_content.ts b/kive/container/static/container/container_content.ts index 781a414b2..94964b734 100755 --- a/kive/container/static/container/container_content.ts +++ b/kive/container/static/container/container_content.ts @@ -43,14 +43,11 @@ CanvasListeners.initResizeListeners(canvasState); /** * Part 2/8: Load initial pipeline data if present. */ -let parent_revision_id; let text = $("#initial_data").text(); let loader = new Pipeline(canvasState); if (text) { - loader.setUpdateCtrl('#id_update'); loader.setRevertCtrl('#id_revert'); loader.loadFromString(text); - parent_revision_id = loader.pipeline.id; loader.draw(); $(canvas).hide().fadeIn(); } @@ -123,18 +120,8 @@ $view_menu.find('#autolayout_btn').click( */ $('#id_pipeline_form').submit(buildPipelineSubmit( canvasState, - $('#id_pipeline_action').val(), - $('#id_family_name'), $('#id_family_desc'), - parseInt($('#id_family_pk').val(), 10), - $('#id_revision_name'), $('#id_revision_desc'), - parent_revision_id, - $('#published'), - $("#id_permissions_0"), $("#id_permissions_1"), - $('#id_submit_error'), - function() { - family_dialog.show(); - $('#id_family_name').addClass('submit-error-missing').focus(); - } + parseInt($('#id_container_pk').val(), 10), + $('#id_submit_error') )); /** diff --git a/kive/container/static/container/io/PipelineApi.d.ts b/kive/container/static/container/io/PipelineApi.d.ts index d8629f283..dae9d27c8 100644 --- a/kive/container/static/container/io/PipelineApi.d.ts +++ b/kive/container/static/container/io/PipelineApi.d.ts @@ -19,15 +19,17 @@ export interface PipelineConfig { threads: number; } -export interface DataSource extends Point { +export interface DataSource { + x?: number; + y?: number; dataset_name: string; - source_step: number; - source_dataset_name: string; + source_step?: number; + source_dataset_name?: string; } interface Step extends Point { driver: string; - fill_colour: string; + fill_colour?: string; inputs: DataSource[]; outputs: string[]; } diff --git a/kive/container/static/container/io/pipeline_load.ts b/kive/container/static/container/io/pipeline_load.ts index f178d49cc..ec25f1351 100755 --- a/kive/container/static/container/io/pipeline_load.ts +++ b/kive/container/static/container/io/pipeline_load.ts @@ -10,6 +10,7 @@ import {Container, PipelineData} from "./PipelineApi"; */ export class Pipeline { + container: Container = null; pipeline: PipelineData = null; files: string[] = []; private REVISION_API_URL = "/api/pipelines/"; @@ -26,6 +27,7 @@ export class Pipeline { * @param container: serialized pipeline array */ load(container: Container) { + this.container = container; this.pipeline = container.pipeline; this.files = container.files; this.canvasState.reset(); @@ -280,20 +282,6 @@ export class Pipeline { return url.replace(host_pattern, ""); } - findNewStepRevisions() { - let steps = this.canvasState.getSteps(); - Pipeline.updateSignalsOf(steps, "update in progress"); - this.canvasState.valid = false; - RestApi.get( - Pipeline.stripHostFrom(this.pipeline.step_updates), - updates => this.applyStepRevisions(updates), - () => { - Pipeline.updateSignalsOf(steps, "unavailable"); - this.canvasState.valid = false; - } - ); - } - private static checkForCrrAndDepUpdates(method: MethodNode, update): boolean { if (update.code_resource_revision) { method.new_code_resource_revision = update.code_resource_revision; @@ -338,39 +326,12 @@ export class Pipeline { this.canvasState.valid = false; } - /** - * Returns whether or not the pipeline has been published - */ - isPublished() { - return this.pipeline.published; - } - - /** - * Sets this pipeline as published - * @todo test and utilize this! - * - * @param callback: Function called on success - */ - publish(callback) { - RestApi.patch(this.REVISION_API_URL + this.pipeline.id, { published: true }, callback); - } - - /** - * Sets this pipeline as unpublished - * @todo test and utilize this! - * - * @param callback: Function called on success - */ - unpublish(callback) { - RestApi.patch(this.REVISION_API_URL + this.pipeline.id, { published: false }, callback); - } - setRevertCtrl(ctrl: string) { document.querySelector(ctrl).addEventListener('click', () => { let $canvas = $(this.canvasState.canvas); $canvas.fadeOut({ complete: () => { - this.load(this.pipeline); + this.load(this.container); $canvas.fadeIn(); } }); @@ -380,9 +341,5 @@ export class Pipeline { }); } - - setUpdateCtrl(ctrl: string) { - document.querySelector(ctrl).addEventListener('click', () => this.findNewStepRevisions()); - } } diff --git a/kive/container/static/container/io/pipeline_submit.ts b/kive/container/static/container/io/pipeline_submit.ts index 3778b6132..5b5c2afdf 100644 --- a/kive/container/static/container/io/pipeline_submit.ts +++ b/kive/container/static/container/io/pipeline_submit.ts @@ -2,56 +2,20 @@ import { CanvasState } from "../canvas/drydock"; import { RestApi } from "../rest_api.service"; import { serializePipeline } from "./serializer"; -export function buildPipelineSubmit(canvasState: CanvasState, action: string, $family_name: JQuery, - $family_desc: JQuery, family_pk: number, $revision_name: JQuery, $revision_desc: JQuery, - parent_revision_id: number, $published: JQuery, $user_permissions: JQuery, - $group_permissions: JQuery, $error: JQuery, familyNameError: () => any) { - - // $action, $family_pk, and parent_revision_id are static +export function buildPipelineSubmit( + canvasState: CanvasState, + container_pk: number, + $error: JQuery) { + if (!container_pk && container_pk !== 0) { + throw 'Container primary key must be specified'; + } if (!(canvasState instanceof CanvasState)) { throw "Invalid object given as CanvasState."; } - if (action === 'revise') { - if (typeof parent_revision_id !== 'number' || isNaN(parent_revision_id) || parent_revision_id < 0) { - throw 'Parent revision ID must be specified'; - } - } - if (action === 'revise' || action === 'add') { - if (!family_pk && family_pk !== 0) { - throw 'Family primary key must be specified'; - } - } - if ($family_name.length === 0) { - throw "Family name element could not be found."; - } - if ($family_desc.length === 0) { - throw "Family description element could not be found."; - } - if ($revision_name.length === 0) { - throw "Revision name element could not be found."; - } - if ($revision_desc.length === 0) { - throw "Revision name element could not be found."; - } - if ($published.length === 0) { - throw "Published checkbox element could not be found."; - } - if ($published.prop('checked') === undefined) { - throw "Published checkbox element does not conform to spec."; - } - if ($user_permissions.length === 0) { - throw "User permissions widget could not be found."; - } - if ($group_permissions.length === 0) { - throw "Group permissions widget could not be found."; - } if ($error.length === 0) { throw "User error message element could not be found."; } - if (typeof familyNameError !== "function") { - throw "Error function callback was not supplied or not callable."; - } /* * Trigger AJAX transaction on submitting form. @@ -59,51 +23,14 @@ export function buildPipelineSubmit(canvasState: CanvasState, action: string, $f return function(e) { e.preventDefault(); // override form submit action clearErrors($error); - let family = $family_name.val(); - if (action === "new" && family === '') { - familyNameError(); - submitError('Pipeline family must be named', $error); - } else { - try { - // @todo: action can also be 'add' when pipeline family exists with 0 revisions - let form_data = serializePipeline( - canvasState, - { - users_allowed: getPermissionsArray($user_permissions), - groups_allowed: getPermissionsArray($group_permissions), - - // There is no PipelineFamily yet; we're going to create one. - family, - family_desc: $family_desc.val(), - - // arguments to add first pipeline revision - revision_name: $revision_name.val(), - revision_desc: $revision_desc.val(), - revision_parent: action === 'revise' ? parent_revision_id : null, - published: $published.prop('checked'), + try { + // @todo: action can also be 'add' when pipeline family exists with 0 revisions + let form_data = serializePipeline(canvasState); - // Canvas information to store in the Pipeline object. - canvas_width: canvasState.width, - canvas_height: canvasState.height - } - ); + submitPipelineAjax(container_pk, form_data, $error); - if (action !== "new") { - submitPipelineAjax(family_pk, form_data, $error); - } else { // Pushing a new family - submitPipelineFamilyAjax({ - users_allowed: form_data.users_allowed, - groups_allowed: form_data.groups_allowed, - name: form_data.family, - description: form_data.family_desc - }, $error).done(function (result) { - submitPipelineAjax(result.id, form_data, $error); - }); - } - - } catch (e) { - submitError(e, $error); - } + } catch (e) { + submitError(e, $error); } }; } @@ -145,13 +72,13 @@ function submitError(errors, $error) { $error.show(); setTimeout(() => $error.hide(), 8000); } -function submitPipelineAjax(family_pk, form_data, $error) { +function submitPipelineAjax(container_pk, form_data, $error) { return RestApi.post( - '/api/pipelines/', + '/api/containers/' + container_pk + '/content', JSON.stringify(form_data), function() { $(window).off('beforeunload'); - window.location.href = '/pipelines/' + family_pk; + window.location.href = '/container_update/' + container_pk; }, function (xhr, status, error) { let json = xhr.responseJSON; @@ -172,19 +99,3 @@ function submitPipelineAjax(family_pk, form_data, $error) { } ); } -function submitPipelineFamilyAjax(family_form_data, $error) { - return RestApi.post( - '/api/pipelinefamilies/', - JSON.stringify(family_form_data), - () => {}, - function(xhr, status, error) { - let json = xhr.responseJSON; - let serverErrors = json && - (json.non_field_errors || json.detail) || []; - if (serverErrors.length === 0) { - serverErrors = xhr.status + " - " + error; - } - submitError(serverErrors, $error); - } - ); -} diff --git a/kive/container/static/container/io/serializer.ts b/kive/container/static/container/io/serializer.ts index ea096e9c0..824baa40c 100644 --- a/kive/container/static/container/io/serializer.ts +++ b/kive/container/static/container/io/serializer.ts @@ -1,7 +1,7 @@ import { CanvasState } from "../canvas/drydock"; import { Geometry } from "../canvas/geometry"; import { CdtNode, RawNode, MethodNode, Magnet, OutputNode } from "../canvas/drydock_objects"; -import { PipelineForApi, ApiXputData, StepForApi, ApiCableData, OutcableForApi } from "./PipelineApi"; +import {Container, DataSource, PipelineData, Step} from "./PipelineApi"; /** * This method serializes the pipeline into an object that can be @@ -20,7 +20,7 @@ import { PipelineForApi, ApiXputData, StepForApi, ApiCableData, OutcableForApi } * form_data will be merged with existing this.metadata if setMetadata() * is used first. */ -export function serializePipeline (canvasState: CanvasState, metadata?: PipelineForApi) { +export function serializePipeline (canvasState: CanvasState, metadata?: Container) { let pipeline_outputs = canvasState.getOutputNodes(); let pipeline_inputs = canvasState.getInputNodes(); @@ -41,10 +41,12 @@ export function serializePipeline (canvasState: CanvasState, metadata?: Pipeline pipeline_inputs.sort(Geometry.isometricSort); pipeline_outputs.sort(Geometry.isometricSort); - let form_data = metadata || {}; - form_data.steps = serializeSteps(pipeline_steps, canvas_dimensions); - form_data.inputs = serializeInputs(pipeline_inputs, canvas_dimensions); - form_data.outcables = serializeOutcables(pipeline_outputs, pipeline_steps, canvas_dimensions); + let form_data = metadata || {}; + let pipeline_data = form_data.pipeline || {}; + form_data.pipeline = pipeline_data; + pipeline_data.steps = serializeSteps(pipeline_steps, canvas_dimensions); + pipeline_data.inputs = serializeInputs(pipeline_inputs, canvas_dimensions); + pipeline_data.outputs = serializeOutcables(pipeline_outputs, pipeline_steps, canvas_dimensions); // this code written on Signal Hill, St. John's, Newfoundland // May 2, 2014 - afyp @@ -61,7 +63,7 @@ export function serializePipeline (canvasState: CanvasState, metadata?: Pipeline return form_data; } -function serializeInputs(pipeline_inputs: (CdtNode|RawNode)[], canvas_dimensions: [ number, number ]): ApiXputData[] { +function serializeInputs(pipeline_inputs: (CdtNode|RawNode)[], canvas_dimensions: [ number, number ]): DataSource[] { let serialized_inputs = []; let [ x_ratio, y_ratio ] = canvas_dimensions; @@ -92,7 +94,7 @@ function serializeInputs(pipeline_inputs: (CdtNode|RawNode)[], canvas_dimensions return serialized_inputs; } -function serializeSteps(pipeline_steps: MethodNode[], canvas_dimensions: [ number, number ]): StepForApi[] { +function serializeSteps(pipeline_steps: MethodNode[], canvas_dimensions: [ number, number ]): Step[] { let serialized_steps = []; let [ x_ratio, y_ratio ] = canvas_dimensions; @@ -122,7 +124,7 @@ function serializeSteps(pipeline_steps: MethodNode[], canvas_dimensions: [ numbe return serialized_steps; } -function serializeInMagnets(in_magnets: Magnet[], pipeline_steps: MethodNode[]): ApiCableData[] { +function serializeInMagnets(in_magnets: Magnet[], pipeline_steps: MethodNode[]): DataSource[] { let serialized_cables = []; // retrieve Connectors @@ -152,7 +154,7 @@ function serializeOutcables( pipeline_outputs: OutputNode[], pipeline_steps: MethodNode[], canvas_dimensions: [ number, number ] -): OutcableForApi[] { +): DataSource[] { let serialized_outputs = []; let [ x_ratio, y_ratio ] = canvas_dimensions; @@ -163,15 +165,11 @@ function serializeOutcables( let source_step = connector.source.parent; serialized_outputs[i] = { - output_name: output.label, - output_idx: i + 1, - output_cdt: connector.source.cdt, - source: source_step.pk, + dataset_name: output.label, source_step: pipeline_steps.indexOf(source_step) + 1, // 1-index source_dataset_name: connector.source.label, // magnet label x: output.x / x_ratio, - y: output.y / y_ratio, - custom_wires: [] // in the future we might have this + y: output.y / y_ratio }; } return serialized_outputs; diff --git a/kive/container/static/container/pipeline_dialogs.ts b/kive/container/static/container/pipeline_dialogs.ts index f4c3d7af0..63b39f225 100644 --- a/kive/container/static/container/pipeline_dialogs.ts +++ b/kive/container/static/container/pipeline_dialogs.ts @@ -1,5 +1,6 @@ -import { RawNode, CdtNode, MethodNode, OutputNode } from "./canvas/drydock_objects"; -import { CanvasState } from "./canvas/drydock"; +import {CdtNode, MethodNode, OutputNode, RawNode} from "./canvas/drydock_objects"; +import {CanvasState} from "./canvas/drydock"; +import {Container} from "@container/io/PipelineApi"; /** * Mini jQuery plugin to make dialogs draggable. @@ -63,9 +64,9 @@ $.fn.extend({ * UI is used to set pipeline metadata, add new nodes, and access other controls. */ export class Dialog { - + private visible = false; - + /** * @param jqueryRef * The root element of the dialog as a jQuery object. @@ -90,7 +91,7 @@ export class Dialog { // hide this menu if it's visible $(document).click( () => { this.visible && this.cancel(); } ); } - + /** * Opens the dialog */ @@ -146,7 +147,7 @@ export class Dialog { for (let propertyName in this) { if (propertyName[0] === "$" && this[propertyName]['constructor'] === $) { if (this[propertyName]['length'] === 0) { - throw "Error in dialog: could not find " + this[propertyName]['selector'] + " in template"; + throw "Error in dialog: " + propertyName + " is empty."; } } } @@ -173,7 +174,7 @@ export class Dialog { abstract class NodePreviewDialog extends Dialog { protected preview_canvas: HTMLCanvasElement; protected is_modal = true; - + /** * NodePreviewDialogs have a element and are draggable. * @param jqueryRef @@ -190,7 +191,7 @@ abstract class NodePreviewDialog extends Dialog { this.preview_canvas.width = jqueryRef.width(); this.preview_canvas.height = 60; } - + /** * Converts the coords of the preview canvas to the coords of another CanvasState. * @param otherCanvasState @@ -480,21 +481,16 @@ export class MethodDialog extends NodePreviewDialog {
*/ - private $delete_outputs; - private $delete_outputs_details; private $submit_button; private $select_method; - private $select_method_family; - private $input_name; + private $input_names; + private $output_names; private $error; - private $expand_outputs_ctrl; + private container: Container; private colour_picker; private add_or_revise: string = "add"; private editing_node: MethodNode; - private methodInputs: any[]; - private methodOutputs: any[]; - private cached_api_result: any; - + /** * In addition to the NodePreviewDialog functionality, MethodDialog will wire up all the necessary template * elements. It also sets event watchers on UI which is internal to the dialog. Finally, it initializes the method @@ -503,19 +499,27 @@ export class MethodDialog extends NodePreviewDialog { * The root element of the dialog as a jQuery object. * @param activator * The primary UI control for activating the dialog. + * @param container + * Definition of the container contents. */ - constructor(jqueryRef, activator) { + constructor(jqueryRef, activator, container?: Container) { super(jqueryRef, activator); - + + this.container = container; this.colour_picker = colourPickerFactory(); // not a class-based object - note no "new" - this.$delete_outputs = $('#id_method_delete_outputs'); - this.$delete_outputs_details = $('#id_method_delete_outputs_details'); this.$submit_button = $('#id_method_button'); this.$select_method = $("#id_select_method"); - this.$select_method_family = $('#id_select_method_family'); - this.$input_name = $('#id_method_name'); + this.$input_names = $('#id_input_names'); + this.$output_names = $('#id_output_names'); this.$error = $('#id_method_error'); - this.$expand_outputs_ctrl = $('.expand_outputs_ctrl', this.jqueryRef); + let option_elements = container.files.map(file_name => + $("
- + {% endblock %} diff --git a/kive/container/templates/container/content_input_dialog.tpl.html b/kive/container/templates/container/content_input_dialog.tpl.html new file mode 100644 index 000000000..c7eb7816d --- /dev/null +++ b/kive/container/templates/container/content_input_dialog.tpl.html @@ -0,0 +1,18 @@ +
+ +

Inputs

+ +
+ + + + + +
+
+
\ No newline at end of file diff --git a/kive/container/templates/container/content_method_dialog.tpl.html b/kive/container/templates/container/content_method_dialog.tpl.html new file mode 100644 index 000000000..b50617272 --- /dev/null +++ b/kive/container/templates/container/content_method_dialog.tpl.html @@ -0,0 +1,30 @@ +
+ +

Methods

+ +
+ +
+
+
+
+
+
+
+
+
+
+ +
+ +
+ + + + + +
+
+
diff --git a/kive/container/templates/container/content_output_dialog.tpl.html b/kive/container/templates/container/content_output_dialog.tpl.html new file mode 100644 index 000000000..116ea2fd2 --- /dev/null +++ b/kive/container/templates/container/content_output_dialog.tpl.html @@ -0,0 +1,11 @@ +
+ +

Outputs

+ +
+ + + +
+
+
\ No newline at end of file diff --git a/kive/container/templates/container/content_view_dialog.tpl.html b/kive/container/templates/container/content_view_dialog.tpl.html new file mode 100644 index 000000000..9862e5b20 --- /dev/null +++ b/kive/container/templates/container/content_view_dialog.tpl.html @@ -0,0 +1,25 @@ +
+

View Options

+ + +
+ Always  + Never  + Only when ambiguous  +
+ + +
+ + + + +
+ + {% if parent_revision %} + + + {% endif %} + + +
\ No newline at end of file diff --git a/kive/container/tests/canvas.tests.ts b/kive/container/tests/canvas.tests.ts index a6acc20c0..830c3999d 100644 --- a/kive/container/tests/canvas.tests.ts +++ b/kive/container/tests/canvas.tests.ts @@ -2034,8 +2034,11 @@ describe("Container canvas classes", function() { var method_id = 77, family_id = 3, fill = "#999", - inputs = [], - outputs = [], + inputs = [{ + dataset_name: "in1", + source_step: 0, + source_dataset_name: "in1"}], + outputs = ["out1"], extra_method = new MethodNode( 200, 100, diff --git a/kive/container/tests/dialog.tests.ts b/kive/container/tests/dialog.tests.ts index 93d975212..e64949041 100644 --- a/kive/container/tests/dialog.tests.ts +++ b/kive/container/tests/dialog.tests.ts @@ -1,24 +1,27 @@ -import { MethodDialog, Dialog, InputDialog, OutputDialog } from "@container/pipeline_dialogs"; +import {MethodDialog, Dialog, InputDialog, OutputDialog} from "@container/pipeline_dialogs"; import {MethodNode, CdtNode, OutputNode} from "@container/canvas/drydock_objects"; import { REDRAW_INTERVAL, CanvasState } from "@container/canvas/drydock"; import * as imagediff from 'imagediff'; import {RawNode} from "@container/canvas/drydock_objects"; +import {Container} from "@container/io/PipelineApi"; -jasmine.getFixtures().fixturesPath = '/templates/pipeline'; -jasmine.getStyleFixtures().fixturesPath = '/static/pipeline'; +jasmine.getFixtures().fixturesPath = '/templates/container'; +jasmine.getStyleFixtures().fixturesPath = '/static/container'; +// noinspection TypeScriptValidateJSTypes jasmine.getFixtures().preload( - 'pipeline_view_dialog.tpl.html', - 'pipeline_method_dialog.tpl.html', - 'pipeline_input_dialog.tpl.html', - 'pipeline_output_dialog.tpl.html' + 'content_view_dialog.tpl.html', + 'content_method_dialog.tpl.html', + 'content_input_dialog.tpl.html', + 'content_output_dialog.tpl.html' ); +// noinspection TypeScriptValidateJSTypes jasmine.getStyleFixtures().preload('drydock.css'); describe("Dialog fixture", function() { let dlg; beforeEach(function(){ - appendLoadFixtures('pipeline_view_dialog.tpl.html'); + appendLoadFixtures('content_view_dialog.tpl.html'); appendLoadStyleFixtures('drydock.css'); appendSetFixtures("Activator"); dlg = new Dialog( @@ -76,12 +79,10 @@ describe("Container MethodDialog fixture", function() { let $cp_hidden_input; let $cp_pick; let $cp_menu; - let $delete_outputs; - let $delete_outputs_details; let $submit_button; let $select_method; - let $select_method_family; - let $input_name; + let $input_names; + let $output_names; let $error; let $expand_outputs_ctrl; let canvas; @@ -89,277 +90,128 @@ describe("Container MethodDialog fixture", function() { let expected_ctx; let expected_method; - let mockData1 = { - "status": 200, - "responseText": `[ - { - "revision_name": "sam2aln", - "display_name": "1: sam2aln", - "revision_number": 1, - "revision_desc": "Conversion of SAM data into aligned format.", - "revision_DateTime": "2014-08-11T21:34:09.900000Z", - "revision_parent": null, - "user": "kive", - "users_allowed": [], - "groups_allowed": [ - "Everyone" - ], - "id": 6, - "url": "http://localhost:8000/api/methods/6/", - "absolute_url": "/method_revise/6/", - "view_url": "/method_view/6/", - "removal_plan": "http://localhost:8000/api/methods/6/removal_plan/", - "family_id": 5, - "family": "sam2aln", - "driver": 8, - "reusable": 1, - "threads": 1, - "dependencies": [ - { - "requirement": 3, - "path": "./", - "filename": "" - } - ], - "inputs": [ - { - "dataset_name": "remap", - "dataset_idx": 1, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 8, - "min_row": null, - "max_row": null - } - } - ], + let initial_container: Container = { + "files": [ + "prelim_map.py", + "remap.py", + "helper.py" + ], + "pipeline": { + "kive_version": "0.14", + "default_config": { + "parent_family": "sample", + "parent_tag": "basic", + "parent_md5": "8dab0b3c7b7d812f0ba4819664be8acb", + "memory": 100, + "threads": 1 + }, + "inputs": [{ + "dataset_name": "input2", + "x": 0.15, + "y": 0.15, + }, { + "dataset_name": "input1", + "x": 0.05, + "y": 0.3, + }], + "outputs": [{ + "dataset_name": "unmapped2_fastq", + "source_step": 2, + "source_dataset_name": "unmapped2_fastq", + "x": 0.637772562280456, + "y": 0.633208895290869, + }, { + "dataset_name": "unmapped1_fastq", + "source_step": 2, + "source_dataset_name": "unmapped1_fastq", + "x": 0.637772562280456, + "y": 0.633208895290869, + }, { + "dataset_name": "remap_conseq", + "source_step": 2, + "source_dataset_name": "remap_conseq", + "x": 0.637772562280456, + "y": 0.633208895290869, + }, { + "dataset_name": "remap", + "source_step": 2, + "source_dataset_name": "remap", + "x": 0.637772562280456, + "y": 0.633208895290869, + }, { + "dataset_name": "remap_counts", + "source_step": 2, + "source_dataset_name": "remap_counts", + "x": 0.637772562280456, + "y": 0.633208895290869, + }], + "steps": [{ + "x": 0.344662650584514, + "y": 0.5, + "driver": "prelim_map.py", + + "inputs": [{ + "dataset_name": "fastq1", + "source_step": 0, + "source_dataset_name": "input1", + }, { + "dataset_name": "fastq2", + "source_step": 0, + "source_dataset_name": "input2", + }], + "outputs": ["prelim"], + }, { + "x": 0.450583501602465, + "y": 0.257130788000083, + "driver": "remap.py", + "inputs": [{ + "dataset_name": "fastq1", + "source_step": 0, + "source_dataset_name": "input1", + }, { + "dataset_name": "fastq2", + "source_step": 0, + "source_dataset_name": "input2", + }, { + "dataset_name": "prelim", + "source_step": 1, + "source_dataset_name": "prelim", + }], "outputs": [ - { - "dataset_name": "aligned", - "dataset_idx": 1, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 11, - "min_row": null, - "max_row": null - } - }, - { - "dataset_name": "conseq_ins", - "dataset_idx": 2, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 12, - "min_row": null, - "max_row": null - } - }, - { - "dataset_name": "failed_read", - "dataset_idx": 3, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 13, - "min_row": null, - "max_row": null - } - } - ] - } - ]` - }; - let mockData2 = { - "status": 200, - "responseText": `{ - "revision_name": "sam2aln", - "display_name": "1: sam2aln", - "revision_number": 1, - "revision_desc": "Conversion of SAM data into aligned format.", - "revision_DateTime": "2014-08-11T21:34:09.900000Z", - "revision_parent": null, - "user": "kive", - "users_allowed": [], - "groups_allowed": [ - "Everyone" - ], - "id": 6, - "url": "http://localhost:8000/api/methods/6/", - "absolute_url": "/method_revise/6/", - "view_url": "/method_view/6/", - "removal_plan": "http://localhost:8000/api/methods/6/removal_plan/", - "family_id": 5, - "family": "sam2aln", - "driver": 8, - "reusable": 1, - "threads": 1, - "dependencies": [ - { - "requirement": 3, - "path": "./", - "filename": "" - } - ], - "inputs": [ - { - "dataset_name": "remap", - "dataset_idx": 1, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 8, - "min_row": null, - "max_row": null - } - } - ], - "outputs": [ - { - "dataset_name": "aligned", - "dataset_idx": 1, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 11, - "min_row": null, - "max_row": null - } - }, - { - "dataset_name": "conseq_ins", - "dataset_idx": 2, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 12, - "min_row": null, - "max_row": null - } - }, - { - "dataset_name": "failed_read", - "dataset_idx": 3, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 13, - "min_row": null, - "max_row": null - } - } - ] - }` - }; - let mockData3 = { - "status": 200, - "responseText": `{ - "revision_name": "sam2aln", - "display_name": "1: sam2aln", - "revision_number": 1, - "revision_desc": "Conversion of SAM data into aligned format.", - "revision_DateTime": "2014-08-11T21:34:09.900000Z", - "revision_parent": null, - "user": "kive", - "users_allowed": [], - "groups_allowed": [ - "Everyone" - ], - "id": 6, - "url": "http://localhost:8000/api/methods/6/", - "absolute_url": "/method_revise/6/", - "view_url": "/method_view/6/", - "removal_plan": "http://localhost:8000/api/methods/6/removal_plan/", - "family_id": 5, - "family": "sam2aln", - "driver": 8, - "reusable": 1, - "threads": 1, - "dependencies": [ - { - "requirement": 3, - "path": "./", - "filename": "" - } - ], - "inputs": [ - { - "dataset_name": "remap", - "dataset_idx": 1, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 8, - "min_row": null, - "max_row": null - } - }, - { - "dataset_name": "remap_duplicate", - "dataset_idx": 1, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 8, - "min_row": null, - "max_row": null - } - } - ], - "outputs": [ - { - "dataset_name": "aligned", - "dataset_idx": 1, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 11, - "min_row": null, - "max_row": null - } - }, - { - "dataset_name": "failed_read", - "dataset_idx": 3, - "x": 0.0, - "y": 0.0, - "structure": { - "compounddatatype": 13, - "min_row": null, - "max_row": null - } - } - ] - }` + "remap", + "remap_counts", + "remap_conseq", + "unmapped1_fastq", + "unmapped2_fastq" + ] + }] + } }; - beforeAll(function() { jasmine.addMatchers(imagediff.jasmine); }); beforeEach(function(){ - appendLoadFixtures('pipeline_method_dialog.tpl.html'); + appendLoadFixtures('content_method_dialog.tpl.html'); appendLoadStyleFixtures('drydock.css'); appendSetFixtures("Activator"); dlg = new MethodDialog( $('.ctrl_menu').attr('id', '#id_method_ctrl'), - $('#activator') - ); + $('#activator'), + initial_container); $cp_hidden_input = $('#id_select_colour'); $cp_pick = $('#colour_picker_pick'); $cp_menu = $('#colour_picker_menu'); - $delete_outputs = $('#id_method_delete_outputs'); - $delete_outputs_details = $('#id_method_delete_outputs_details'); $submit_button = $('#id_method_button'); $select_method = $("#id_select_method"); - $select_method_family = $('#id_select_method_family'); - $input_name = $('#id_method_name'); + $input_names = $('#id_input_names'); + $output_names = $('#id_output_names'); $error = $('#id_method_error'); $expand_outputs_ctrl = $('.ctrl_menu .expand_outputs_ctrl'); + $input_names.val('in1'); + $output_names.val('out1 out2 out3'); canvas = $('canvas')[0]; expected_canvas = imagediff.createCanvas(canvas.width, 78); expected_ctx = expected_canvas.getContext('2d'); @@ -369,15 +221,9 @@ describe("Container MethodDialog fixture", function() { "#999", // fill null, // label [ - { dataset_name: '', source_step: 0, source_dataset_name: ''} + { dataset_name: 'in1', source_step: 0, source_dataset_name: 'in1'} ], // inputs - ['', '', '']); // outputs - - $select_method_family.find('option') - .filter(function() { return $(this).val() !== ""; }) - .remove(); - - $('