Skip to content

5. Development

Szymon Owczarzak edited this page May 6, 2021 · 1 revision

Development

Widget development

Frontend

Add new widget file

All available widgets are listed in cogboard-webapp/src/components/widgets/types. Create a new file or copy any existing widget. Remember to keep filename convention - WidgetNameWidget.js. Widget is a React functional component which consumes props from the backend server.

The very basic structure of the widget component looks as follows:

import React from 'react';

import Typography from '@material-ui/core/Typography';

const DefaultWidget = () => {
  return (
    <Typography color="textSecondary" variant="subtitle2">
      Default content
    </Typography>
  );
};

export default DefaultWidget;

Update index

Also, you must update cogboard-webapp/src/components/widgets/index.js and register your new widget.

Example:

const widgetTypes = {
  // Other widgets
  MyWidget: {
    name: 'My Widget',
    component: MyWidget,
    showUpdateTime: true
  }
};

Configuration:

  • name - name shown in widget type dialog field
  • component - React component used for this widget
  • (optional) dialogFields - dialog fields used for widget configuration
  • (optional) showUpdateTime - display time of a last widget data update
  • (optional) validationConstraints - constraints for dialog fields that prevent inputting incorrect data
  • optional custom properties

Create custom dialog fields (optional)

If your widget needs specific data to function correctly, you can create custom dialog fields using which users can input necessary information.

  1. Create custom dialog field component in cogboard-webapp/src/components/widgets/dialogFields

  2. Register dialog field in cogboard-webapp/src/components/widgets/dialogFields/index.js

    Example:

    const dialogFields = {
      // Other custom dialog fields
      MyField: {
        component: MyField,
        name: 'myField',
        label: 'My Field',
        validator: () => string().required(vm.FIELD_REQUIRED())
      }
    };

    Configuration:

    • name - name under which field will be registered in form data
    • component - React component used for this dialog field
    • label - label shown in widget configuration dialog
    • validator - function which validates inputted data
    • (optional) initialValue - default value for a dialog field
    • optional custom properties

Backend (optional)

When widget just displays fields given in configuration then the backend part is not required.

Add new Widget Class

All available widgets are listed in com.cognifide.cogboard.widget.type package. Create new Kotlin class for new widget. Remember to keep filename convention - WidgetNameWidget.kt. Widget should extend BaseWidget or AsyncWidget. Use AsyncWidget when widget is communicating with 3rd party data source, otherwise - BaseWidget.

Example:

class JenkinsJobWidget(vertx: Vertx, config: JsonObject) : AsyncWidget(vertx, config) {

    private val url: String = config.endpointProp("url")

    // this method will be executed for once or in schedule
    override fun updateState() {
        httpGet(url = "$url/api/json") // send request for JSON to 3rd party
    }

    // handleResponse(...) is executed when httpGet or httpPost finishes and gets data
    override fun handleResponse(responseBody: JsonObject) {
        responseBody.getJsonObject("data")?.let {
            val status = Widget.Status.from(it.getString("result"))

            // at the end use send(...) to notify front-end that widget status has changed
            send(JsonObject()
                    .put(CogboardConstants.PROP_STATUS, status) // new status for widget
                    .put(CogboardConstants.PROP_CONTENT, it)) // new content for widget
        }
    }
}

Update WidgetIndex

Also you must update com.cognifide.cogboard.widget.WidgetIndex and register your new widget.

Debugging

Normal debugging

Uncomment ports in cogboard-local-compose.yml

     ports:
       - "18092:18092"

Uncomment line in Dockerfile

RUN sed -i 's/# JVM_DEBUG=/JVM_DEBUG=/g' /usr/local/knotx/bin/knotx

Startup debugging - use this when debugging start() methods

Uncomment line in Dockerfile

RUN sed -i 's/suspend=n/suspend=y/g' /usr/local/knotx/bin/knotx

IMPORTANT ! - Make sure that CMD [ "knotx", "run-knotx" ] is a last command in Dockerfile

Cypress Automated Functional Tests

Basic Commands

  • ./gradlew functionalTests - will launch all specs with local environment configuration as a background task
  • ./gradlew cypressOpen - will open Cypress window so you can run or implement specific scenarios

Advanced Commands

To override environment add -DcypressEnv=envName system property. It will make cypress run with config named envName.json under functional/cypress-tests/cypress/config directory. Make sure it is there.

Spec customization is not currently implemented in gradle wrapper. If you want to run specific tests only, use cypress explictitly:

npx cypress run [--config-file path/to/config.json]1[--spec path/to/spec.js]2 from the functional/cypress-tests directory.

1 - provide custom config file path. By default it will use functional/cypress-tests/cypress.json

2 - provide spec file(s) to be launched. By default all specs are run.