Skip to content

A hackable universal dashboard framework for your desktop task automation and visualise tooling.

License

Notifications You must be signed in to change notification settings

etamity/dashpad

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dashpad

A hackable universal dashboard framework for your desktop task automation and visualise tooling.

docs

Video Demo

Screens

Tutorial Module

Environment Requirement

  • Node >= v8.16.0

    If we get fsevents.watch is not a function error, try to change node version greater than v8.16.0.

Getting Started

To get started developing, set up the nteract monorepo.

Set the monorepo up in dev mode

Requires Node.js and yarn.

  1. Fork this repo
  2. Clone your fork or this repo git clone https://github.com/etamity/dashpad
  3. cd to the directory where we cloned it

Install

yarn install

Start

yarn start

build

Your built version will be under build folder.

yarn build

Bundle

Your bundled version will be under dist folder.

yarn pack:mac

or

yarn pack:win

Config

The application config file is in /Users/${username}/documents/dashpad/db/db.json, we can change the window size and port etc.

{
  "config": {
    "port": 9999,
    "uiport": 8888,
    "host": "localhost",
    "window": {
        "width": 1308,
        "height": 1024,
        "show": false
    },
    ...
    }
}

Cli Command

If we wish to use dashpad command, run npm global install and link it inside your project root folder.

npm i -g & npm link

and then we can run dashpad in the terminal to open the dashpad.

The default work workspace directory will be under /Users/${username}/documents/dashpad

Dev Guide

Integrate your node module

Step 1

Create new folder in /Users/${username}/documents/dashpad/packages/${your_module}, and open terminal in your module folder,

npm init

to create package.json

and create an index.js file in the folder, with below code:

module.exports = function(params) {
    Dashpad.showToast({ message: 'hello form module' });
};

Dashpad is a global object that we can access dashpad api here.

Step 2

Create _dash/config.yml file, and copy the menu items as below:

---
navs:
  - name: My First Module
    icon: icon-speedometer
    isOpen: true
    goto: ui.yml # Your entry ui file
    badge:
        variant: info
        text: NEW
# This settings will display in Dashpad settings in UI
# settings: 
  # username: Joey
  # token: someToken
  # configFile: !import someConfigFile.json

Now restart dashpad, we will see the new side menu My First Module.

Step 3

Create _dash/ui.yaml file and fill the ui schema:

---
Tabs:
    activeTab: 0
    Card:
        label: The first Tab
        Header:
            title: A registration form
        Form:
            Button_notification:
                label: Notification
                onClick: >
                    (e) => {
                        Dashpad.showNotification({
                        title: 'Notification title',
                        message: 'Notification message'
                        });
                        console.log('e', e, 'this', this);

                        Dashpad.run('index.js', {someParams: 'test'}); // calling backend index.js
                    }
                    

and now go back to dashpad and click side menu My First Module, we will see new we ui has been created.

if click Notification button, we will recevie a notification.

React Way

Dashpad also allow us to create ui with react code base, but the main entry file must be .mdx, please check out mdxjs.

Example of the config.yml:

---
navs:
  - name: My First Module
    icon: icon-speedometer
    isOpen: true
    goto: index.mdx # Your entry ui file
    badge:
        variant: info
        text: NEW

example of the index.mdx file:

import ExampleComponent from './example.js';
# Hello, *world*!

Below is an example of JSX embedded in Markdown. <br /> **Try and change
the background color!**

<ExampleComponent />

or 

<div>
use jsx sytex directly
</div>

example of the example.js file:

import React from 'react';

export default () => (<div style={{ padding: '20px', backgroundColor: 'tomato' }}>
  <h3>This is JSX Component</h3>
</div>);

Block and State

If we want to use redux, we just need to use Block component to wrap up your custom component.

example of index.mdx file:

import { Button } from 'reactstrap';

<Block name="example" defaultState={{
    name: 'init state'
    }}
    >
    {(state)=> {
        return <Button onClick={()=> {
            state.set({name: 'state changed'});
            // Or access Dashpad api here
            }}>Start {state.name}</Button>
        }
    }
</Block>

Dashpad api available in global scope, we can access Dashpad anypoint in the mdx or jsx file

Note

If we want to split the js code from yml file into a external js file, we can just create a js file with exact same name as yaml file, and write logic or function in that js file, Dashpad will preload the code for yaml file usage.

e.g

If _dash/ui.yaml file exist already then create another js file call _dash/ui.js, so that we can write js code in the file.

ui.js

const onTabsMount = () => {
    console.log('Tab Mounted');
}

const onTabsChanged = () => {
    console.log('Tab Changed');
}

console.log('This code is loaded');

and then we can call onTabsMount in component events, such as onClick, onMount, onWillMount etc.

---
Tabs:
    activeTab: 0
    onMount: >
        (e) => {
            onTabsMount();
        }
    onChange: >
        (e) => {
            onTabsChanged();
        }
    Card:
        label: The first Tab

        Header:
            title: A registration form

Now check the console, will find message 'This code is loaded' is there, and then is 'Tab Mounted', if change the tab will see the output 'Tab Changed'.

Yaml Spliting

You can split yaml file into sub component files, but have to named the file start with @, e.g @filename.yml, this is for recognising the file as a component, so when we update the component file, it will only re-render main entry file.

e.g

Tabs:
    Slot_1: !import components/@Card_dashpad.yml
    Slot_2: !import components/@Card_test.yml

Slot is a warpper component which doesn't doing anything on appearance, it's useful to organise structure or import sepreated file components.

This Context

You can access this ref in any events, such as onClick, onMount, onWillMount etc.

Container:
    Collapse:
      isOpen: true
      List:
        items:
            - Some example text!
            - another example text!
    Button:
      label: Get Context
      position: left
      brand: linkedin
      onClick: >
        (e) => {
              console.log(this);
              const brand = this.get('brand').value();
              const isOpenProp = this.sibling('Collapse.isOpen');
              const isOpen = isOpenProp.value();
              const newButtonLabel = (isOpen ? 'isOpen' : 'isClosed') 
              this.get('label').set(newButtonLabel+ ' : ' + brand);
              isOpenProp.set(!isOpen);
        }

this.props refer to the event target itself, we can direct acces target's props object, keypath, type, name etc.

this.get(key) refer to the event target itself, we can access target's props object; this.get(key).value() will return the value of the prop key.

this.set(value) refer to the event target itself, we can set target's props value directly; We also can do chain keypath lookup: this.parent(key).sibling(key2).set(value).

this.sibling(key) refer to the event target sibling props object, we can set sibling's props value directly; this.sibling(key).value() will return the value of the sibling prop key.

this.parent(key) refer to the event target parent props object, we can get parent's props value directly; this.parent(key).value() will return the value of the parent prop key.

this.ref() refer to the event target instance, we can access target's instance, currently only Webview component has the value return from ref().

UI Schema

The yaml ui schema is a tree structure file, when dashpad parse the ui, it alwasy will look for the key name of the object, the format will look like Type_name. E.g. Tabs_mytabs

Dashpad will parse Tabs_mytabs as Tabs component and the component name is Tabs_mytabs.

Important : Type_name the Type must start with capital character, so Dashpad will recognise it is a component Type, otherwise will parse it as an attribute.

Components


  • Alert

Alert:
  color: warning
  Html:
    content: >
      <h4 className="alert-heading">Well done!</h4>
        <p>
          Aww yeah, we successfully read this important alert message. This example text is going
          to run a bit longer so that we can see how spacing within an alert works with this kind
          of content.
        </p>
        <hr />
        <p className="mb-0">
          Whenever we need to, be sure to use margin utilities to keep things nice and tidy.
      </p>
  • Container

Container:
    Card:
    Text:
        position: center
        content: this is a container
  • Tabs

Tabs:
    activeTab: 0
    Card_1:
        label: tab1
    Card_2:
        label: tab2
  • Card

Card:
    label: tab1
    Header:
        title: card title
        Button_1:
            label: left button
            position: left
        Button_2:
            label: right button
            position: right
    Form:
        Username:
            type: text
            value: joey
  • Collapse

Collapse:
    isOpen: false
    Card:
        title: card title
Button_control:
    label: button to control collapse
    onClick: >
        (e) => {
            Dashpad.setVars('isOpen', !isOpen);
        }
  • Form

Form:
    Username:
      type: text
      label: Username
      tooltip: Choose your username
      value: First name
      prepend:
        - type: button
          icon: icon-drop
          color: warning
      append:
        - type: text
          icon: icon-drop
          label: hajajaj
          color: success
    Password:
      type: password
      label: Password
      tooltip: Please input the password
  • Row

One row with equally width colums

Row:
    fluid: 'true'
    Username:
        type: text
        value: joey
        label: Username
        tooltip: Please input your username
    Password:
        type: password
        value: 1234
        label: Password
        tooltip: Please input your password

Also we can specify col props in child components

Row:
  fluid: 'true'
  Username:
      col:
          md: 8   # Bootstrap 12 colums in one row
          lg: 4
      type: text
      value: joey
      label: Username
      tooltip: Please input your username
  Password:
      col:
          md: 4   # Bootstrap 12 colums in one row
          lg: 8
      type: password
      value: 1234
      label: Password
      tooltip: Please input your password
  • Button

Button:
    brand: twitter
    label: Run Script
    color: success
    icon: icon-drop
    disabled: false
    outline: false
    size: md
    className: ''
    onClick: >
        console.log('Button clicked')
  • Input

Input component can specific type as ['text', 'password', 'number', 'email', 'textarea','datetime', 'time', 'date']

Input:
    type: date # ['text', 'password', 'number', 'email', 'textarea','datetime', 'time', 'date']
    label: Birthday
    tooltip: Please Input Your Birthday
  • Field

Field component can specific type as Input, Button, RADIO, SELECT, CHECKBOX, SWITCH

Form:
  Field_input:
    type: text
    label: Text Field
  Field_button:
    type: button
    label: Button Field
  Field_radio:
    type: radio
    title: Radio Field
    options:
      - Male
      - Female
  Field_checkbox:
    type: checkbox
    title: Checkbox Field
    options:
      - Foot Ball
      - Piano
      - Games
      - Movies
  Field_select:
    type: select
    title: Select Field
    options:
      - London
      - York
      - Manchester
      - Liverpool
  Field_switch:
    type: switch
    label: Switch Field
    checked: true
    color: danger
  • Checkbox

Hobbies:
    type: checkbox
    title: Foot Ball
    options:
      - Foot Ball
      - Piano
      - Games
      - Movies
  • Radio

Gender:
  type: radio
  title: Gender
  inline: true
  options:
    - Male
    - Female
  • Link

Link component will open the link in browser

Link:
    icon: icon-links
    link: http://somelink.com/
    label: Open the link
    color: danger
  • Select

City:
  type: select
  title: City
  options:
    - London
    - York
    - Manchester
    - Liverpool
  • Switch

RememberMe:
    type: switch
    label: Remember Me
    color: primary
    checked: true
  • Badge

Badge:
    icon: icon-settingd
    color: primary
  • Markdown

Markdown:
    content: >
        <h2>Full example</h2>

        ``` jsx
        console.log('this is test Markdown');
        ```
  • List

List:
    items:
        - list item 1
        - list item 2
        - list item 3
        - title: list item 4
          description: this is list item 4 content
        - Text:
            context: just text
    Table:
        labels: ['id', 'name', 'email', 'color']
        dataset:
            - ['1', 'joey', '[email protected]', 'red']
            - ['2', 'joe', '[email protected]', 'blue']
            - ['3', 'jack', '[email protected]', 'green']
            - ['3', 'joseph', '[email protected]', 'black']
  • Html

Html:
    content: >
        <h1>You can put html in here<h1>
  • Table

Table:
    labels: ['id', 'name', 'email', 'color']
    dataset:
        - ['1', 'joey', '[email protected]', 'red']
        - ['2', 'joe', '[email protected]', 'blue']
        - ['3', 'jack', '[email protected]', 'green']
        - ['3', 'joseph', '[email protected]', 'black']
  • Buttongroup

Buttongroup:
    type: dropdown # ['group', 'toolbar', 'dropdown', 'wrap']
    label: Menu
    className: d-flex
    childClassName: m-1
    onClick: >
        (e) => {
            console.log('test group', this.e.target);
        }
    items:
        - label: Button 1
        - label: Button 2
        - label: Button 3
  • Progress

Progress:
    color: primary
    value: 40
    max: 100
  • Text

Text:
    tag: h3 #['h1', 'h2', ... , 'h6']
    content: this is the typograph component
    position: center # ['left', 'center', 'right']
    color: info # ['primary', 'info', 'warning', 'danger', 'white', 'black']
    weight: bold # ['ligth', 'normal', 'bold']
    transform: uppercase # ['uppercase', 'lowercase', 'capitalise']
  • Code

Code:
    width: '100%'
    theme: solarized_dark #['javascript', 'java', 'python', 'xml', 'ruby', 'sass', 'markdown', 'mysql', 'json', 'html', 'handlebars', 'golang', 'csharp', 'elixir', 'typescript', 'css', 'sh', 'yaml', 'sql', 'jsx', 'css']
    mode: markdown #['github', 'solarized_dark', 'terminal']
    value: const js = console.log;
    wrapEnabled: true
    readOnly: true

Dashpad Api

  • getVars

You can get variables value from $vars properties by keyPath,

e.g.

Dashpad.getVars(keyPath);

If we predefined key default value in the yaml file header under $vars key:

---
$vars:
    username: Joey
    header: This is Header
    progress: 0

Then we can get the value simple pass they username key to getVars, it will return variables username value.

Dashpad.getVars('username');  // return 'joey'
  • setVars

You can set variable value to all components where it refers to this variable,

e.g.

Dashpad.setVars(keyPath, value);

If we predefined key default value in the yaml file header under $vars key:

---
$vars:
    username: Joey
    progress: 0

And we can set the props refers ${username} and ${progress} to these variable keys:

---
Username:
    type: text
    label: Username
    tooltip: Please input your username
    value: ${username} # set the refers
Progress:
    value: ${progress} # set the refers
    max: 1000
    animated: true

Then we can set the value simple pass they username key to getVars, it will set Username.value and Progress.value props value.

Dashpad.setVars('username', 'joseph');
// or
Dashpad.setVars({ keyPath: 'username', value: 'joseph' });

Or we can set mutiple value in one goal:

Dashpad.setVars([
    { keyPath: 'username', value: 'Hello!!!!' },
    { keyPath: 'username', value: 'this will be set at same time!!!!' },
]);
  • getVarsState

You can get current state by keyPath,

e.g.

Dashpad.getVarsState(keyPath);

If we predefined key path in the yaml file header under $vars key:

---
$vars:
    username: Tabs_1.Card_1.Row.Username.value
    header: Tabs_1.Card_1.Header.title

Then we can get the value simple pass they username key to getVarsState, it will return Tabs_1.Card_1.Row.Username.value state value.

Dashpad.getVarsState('username');
  • setVarsState

You can get current state by keyPath,

e.g.

Dashpad.setVarsState(keyPath, value);

If we predefined key path in the yaml file header under $vars key:

---
$vars:
    username: Tabs_1.Card_1.Row.Username.value
    header: Tabs_1.Card_1.Header.title

Then we can set the value simple pass they username key to getVars, it will set Tabs_1.Card_1.Row.Username.value state value.

Dashpad.setVarsState('username', 'joseph');
// or
Dashpad.setVarsState({ keyPath: 'username', value: 'joseph' });

Or we can set mutiple value in one goal:

Dashpad.setVarsState([
    { keyPath: 'username', value: 'Hello!!!!' },
    { keyPath: 'username', value: 'this will be set at same time!!!!' },
]);
  • settings

You can have your own scope settings variable by access Dashpad.settings

e.g.

Dashpad.settings.get(); // get all settings under your package name
Dashpad.settings.get(keyPath); // get the keyPath settings under your package name
Dashpad.settings.set(keyPath, value); // set the variables under your package name
Dashpad.settings.push(keyPath, value); // push an element into an array under your package name
Dashpad.settings.delete(keyPath); // delete the variables under your package name
Dashpad.settings.value(); // get all Dashpad settings

If we have a node package name sample_module, and we can set your settings variable as below:

Dashpad.settings.set('myToken', 'token_data'); // set the variables under your package name

Dashpad will save token_data value under settings.sample_module.myToken. You will see the settings in the dashboard settings view.

  • getState

You can get current state by keyPath,

e.g.

Dashpad.getState(keyPath);

Dashpad.getState('Tabs_1.Card_1.Header.title');
  • setState

You can set current state by keyPath and value,

e.g.

Dashpad.setState(keyPath, value);

Dashpad.setState('Tabs_1.Card_1.Header.title', 'Hello!!!!');
// or
Dashpad.setState({ keyPath: 'Tabs_1.Card_1.Header.title', value: 'Hello!!!!' });

Or we can set mutiple value in one goal:

Dashpad.setState([
    { keyPath: 'Tabs_1.Card_1.Header.title', value: 'Hello!!!!' },
    {
        keyPath: 'Tabs_1.Card_1.Header.Button_1.label',
        value: 'this will be set at same time!!!!',
    },
]);
  • showNotification

e.g.

Dashpad.showNotification({titile, message});

Dashpad.showNotification({
    titile: 'Hello world',
    message: 'This is notification',
});
  • showToast

e.g.

Dashpad.showToast({message, options});

const options = {
  type: 'info' // 'info' | 'success' | 'warning' | 'error' | 'default'
}
Dashpad.showToast({
    message: 'This is toast',
    options
});
  • showModal

e.g.

Dashpad.showModal({title, message, onConfirm});

Dashpad.showModal({
    title: 'show a modal'
    message: 'This is modal'
    });
  • loadJson

load Json file and return json object

e.g.

Dashpad.loadJson(jsonfile);

const json = Dashpad.loadJson('somejson.json');
  • run (In Yaml file only)

Run node scirpt from yml file

e.g.

Dashpad.run(nodeScript, parameters);

Dashpad.run('index.js', { obj: 'hey, node can get this parameter!' });
  • exit

Once your task is finished, call Dashpad.exit(); to exit the process in the node.

e.g.

Dashpad.exit();

VM Enviroment

The reason to have js VM library is to avoid global scope poisioning. All yml (frontend) script will be running in a closure function.

E.g

// VM filter the global object in frontend
(function anonymous(window..., Dashpad
) {
"use strict";

commonFunc('just loaded!!');

return function VMScope() {
  return {
    run: function run(code) {
      eval(code);
    },
    runEvent: function runEvent(code, e) {
      eval(code);
    }
  };
}()
})

So all global objects are being filtered, window object will be undefined.

Github API

Dashpad has integrated official github rest sdk @octokit/rest, we can generate auth token on github setting, and set it up on Dashpad settings page, then get the Github object by

const { Github } = Dashpad.platform;

Github.search({q, ...});

By default if we didn't set up the auth token, the Github object will be empty.

Jenkins API

If we set up the endpoint under settings.platform.Jenkins.endpoint in Dashpad, it will connect to that jenkins endpoint by default, then we can use the Jenkins object to call jenkins api.

Example:

const { Jenkins } = Dashpad.platform;
Jenkins.build('some_job', function(err, data) {})

For connecting to different endpoint, we can use JenkinsConnect function to construct a new object to use it.

const { JenkinsConnect } = Dashpad.platform;
const devtoolJenkins = JenkinsConnect('someurl.to.jenkins');

The jenkins api originally from node-jenkins-api

Here is list of available api.

Builds

build

Jenkins.build('job-in-jenkins', (optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

build_with_params

Jenkins.build_with_params('job-in-jenkins', (optional){depth: 1, <param>:<value>, token: 'jenkins-token',...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

stop build

Jenkins.stop_build('job-in-jenkins', 'build-number', (optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

console output

Jenkins.console_output('job-in-jenkins', 'buildname', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

build info

Jenkins.build_info('job-in-jenkins', 'build-number', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

last build info

Jenkins.last_build_info('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

last completed build info

Jenkins.last_completed_build_info('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

all builds

Jenkins.all_builds('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

test result/report

Jenkins.test_result('job-in-jenkins', 'build-number', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

last build report - OBSOLET use last_build_info

// Jenkins.last_build_report('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
//   if (err){ return console.log(err); }
//   console.log(data)
// });

delete build data for job

Jenkins.delete_build('job-in-jenkins', 'build-number', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

Jobs

all jobs

Jenkins.all_jobs((optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

get config xml

Jenkins.get_config_xml('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

update existing job configuration

Jenkins.update_config('job-to-update'
                ,function(config) {
                    // function which takes the config.xml, and returns
                    // the new config xml for the new job
                    return config.replace('development','feature-branch');
                }
                ,(optional){token: 'jenkins-token', ...}
                ,function(err, data) {
                      // if no error, job was copied
                      if (err){ return console.log(err); }
                      console.log(data)
                });

update job

Jenkins.update_job('job-to-update', xmlConfigString, (optional){token: 'jenkins-token', ...}, function(err, data) {
  // if no error, job was copied
  if (err){ return console.log(err); }
  console.log(data)
});

job info

Jenkins.job_info('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

create job

Jenkins.create_job('job-in-jenkins', xmlConfigString, (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

copy job

Jenkins.copy_job('job-to-copy'
                ,'new-job-title'
                ,function(config) {
                    // function which takes the config.xml, and returns
                    // the new config xml for the new job
                    return config.replace('development','feature-branch');
                }
                ,(optional){token: 'jenkins-token', ...}
                ,function(err, data) {
                      // if no error, job was copied
                      if (err){ return console.log(err); }
                      console.log(data)
                });

delete job

Jenkins.delete_job('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

enable job

Jenkins.enable_job('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

disable job

Jenkins.disable_job('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

last success

Jenkins.last_success('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

last result

Jenkins.last_result('job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

Queue

get all queued items

Jenkins.queue((optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

get one queued item

Jenkins.queue_item('queue-item-number', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

cancel queued item

Jenkins.cancel_item('queue-item-number', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

get all jenkins computers (aka workers)

Jenkins.computers((optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

Views

get all views

Jenkins.all_views((optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
      if (err){ return console.log(err); }
        console.log(data)
});

create view

Jenkins.create_view('new-view-name', (optional)viewMode = 'hudson.model.ListView', (optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

view info

Jenkins.create_view('view-name', (optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

update view

var viewConfig = {
            name: "view-in-jenkins",
            "description": "This is the view-in-jenkins View",
            "statusFilter": "",
            "job-in-jenkins": true,
            "useincluderegex": true,
            "includeRegex": "prefix.*",
            "columns": [{"stapler-class": "hudson.views.StatusColumn", "$class": "hudson.views.StatusColumn"}, {"stapler-class": "hudson.views.WeatherColumn", "$class": "hudson.views.WeatherColumn"}, {"stapler-class": "hudson.views.JobColumn", "$class": "hudson.views.JobColumn"}, {"stapler-class": "hudson.views.LastSuccessColumn", "$class": "hudson.views.LastSuccessColumn"}, {"stapler-class": "hudson.views.LastFailureColumn", "$class": "hudson.views.LastFailureColumn"}, {"stapler-class": "hudson.views.LastDurationColumn", "$class": "hudson.views.LastDurationColumn"}, {"stapler-class": "hudson.views.BuildButtonColumn", "$class": "hudson.views.BuildButtonColumn"}]
        };

Jenkins.update_view('view-in-jenkins', viewConfig, (optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

delete view

Jenkins.delete_view('view-in-jenkins', (optional){token: 'jenkins-token', ...}, function(err, data) {
  if (err){ return console.log(err); }
  console.log(data)
});

add job to view

Jenkins.add_job_to_view('view-in-jenkins', 'job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
      if (err){ return console.log(err); }
        console.log(data)
});

remove job from view

Jenkins.remove_job_from_view('view-in-jenkins', 'job-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
      if (err){ return console.log(err); }
        console.log(data)
});

get all jobs in view

Jenkins.all_jobs_in_view('view-in-jenkins', (optional) {depth: 1, <param>:<value>, ...}, function(err, data) {
      if (err){ return console.log(err); }
        console.log(data)
});

Plugins

get all installed plugins

Jenkins.all_installed_plugins((optional){token: 'jenkins-token', ...}, function(err, data){
    if (err){ return console.log(err); }
    console.log(data)
})

install a plugin

// var plugin = '[email protected]';
var plugin = 'copyartifact@current';
Jenkins.install_plugin(plugin, (optional){token: 'jenkins-token', ...}, function(err, data){
    if (err){ return console.log(err, data); }
    console.log(data)
});

NOTE: It will report successful even if the plugin is already installed. NOTE: Prevent Cross Site Request Forgery exploits need be disabled in Configure Global Security.

Dashpad Development

Create New Plugin (Dashpad Source Code)

To create new plugin, go to packages/frontend/dashpad/plugins and create new folder with NewPlguin style, and then create and index.js file as entry point.

index.js

export * from './NewPlguin';

Also we can copy the template __SamplePlugin folder, we can find it under plugins folder to start your new plugin.

NewPlguin.js

import React, { Component } from 'react';

export class NewPlguin extends Component {
    static Config() {
        return {
            name: 'New Plguin'
            SideMenus, // Side menu items
            TopRightIcons, //  Top right icon buttons
            SubRoutes: [],
            TopMenus, // Top menu (on left side)
            Aside, // Aside panel (if any)
        };
    }
    render() {
        return (
            <div className="animated fadeIn">
                <Container />
            </div>
        );
    }
}

Sidemenu

configs/Menu.js

There are two main menu, Top menu and Side menu

Add MenuItem to Side menu

const SideMenuItems = [
    {
        name: 'Dashboard',
        url: '/dashboard',
        icon: 'icon-speedometer',
    },
    {
        name: 'Frontend Tools',
        url: '/frontendtools',
        icon: 'icon-wrench',
        badge: {
            variant: 'info',
            text: 'NEW',
        },
    },
];

Add menu item to SideMenu menu

export class NewPlugin extends Component {
    static get Config() {
        return {
            SideMenu: SideMenuItems,
        };
    }
}

Each SideMenu menu item also can have submenu, and we can assign it to children array in the menu item.

SideMenu Add sub menu into menu item

    const SideMenuItems = [
        {
            name: 'Dashboard',
            url: '/dashboard',
            icon: 'icon-speedometer'
             children: [
            {
                name: 'Colors',
                url: '/dashboard/page1',
                icon: 'icon-drop',
                badge: {
                    variant: 'info',
                    text: 'NEW',
                }
            },
            {
                name: 'Typography',
                url: '/dashboard/page2',
                icon: 'icon-pencil',
            },
        ],
        },
        {
            name: 'Frontend Tools',
            url: '/frontendtools',
            icon: 'icon-wrench',
            badge: {
                variant: 'info',
                text: 'NEW'
            }
        }
    ];

Publish Your Tools/Plugins

Once we push your code, add dashpad topic on the github descirption area, your plugin will show up on the Dashpad main page, it will be nice to add README.md to tell a bit more about your plugin, let people know what it does.

Routing

When we created new plugin, it will automatically create new route for we. For example when we created a new plugin under packages/frontend/dashpad/plugins/NewPlugin, and export the plugin in the packages/frontend/dashpad/plugins/index.js file:

export * from './NewPlugin';

it will generate a new route /newplugin.

Custom Style

Go to src/sass folder to change style, it's using Bootstrap 4, reactstrap and Core UI

Electron

All exports to renderer thread are under packages/frontend/dashpad/libs/Remote.js which can be use in frontend. The reason to import it from frontend is for live reloading node code just by refreshing frontend page.

packages/electron/main.js are electron entry file.

All node backend operation function are under packages/core folder.

Route Map

Notice

While running the application, two ports will be using. (8888, and 9999)

About

A hackable universal dashboard framework for your desktop task automation and visualise tooling.

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published

Languages