Skip to content
This repository has been archived by the owner on Nov 3, 2020. It is now read-only.

Feature: Discover

Sjors Wijsman edited this page Jun 13, 2020 · 19 revisions

Discover

Overview

TODO: Screenshot, quick description, table of contents

CLI

Concept

To fit the programmer theme we thought of a CLI as an additional way to navigate and perform actions on the webapp. We looked at a few examples of CLI-themed web interfaces and noticed there are often a few flaws with the implementation. The two most obvious flaws that strongly deteriorate the user's experience are:

  1. It's not obvious what commands there are and how to use these commands with the correct arguments, values, etc.
  2. It's the website's only means of navigation/interaction. By forcing the user to use the CLI it quickly becomes a chore instead of a fun and playful extension of the website.

These issues both have a very straightforward solution: 1, add a list of commands somewhere on the website and 2, make sure the user can do everything without the CLI. We weren't satisfied with the first solution however, and wanted something a bit more elegant. So we settled for an 'autocomplete'-like functionality. When the user clicks on the CLI input, a dialogue shows up with all the commands available for the user. The user can now manually enter a command or click the command to quickly perform it.

When the user starts typing the autocomplete dialogue narrows down the available commands according to the input of the user. Once the user entered a valid command, the interface shows all the possible values (arguments) that can follow this command. For example, after entering the cd command the user will be prompted with a list of possible locations to navigate.

Implementation

The creation of this command-line interface consisted of a few steps in the following order:

Step 1: Parsing & validating commands

Allowing the user to insert a command, parsing & validating it and, if correct, run the command's function. By storing these commands inside of an object, we can also store functions along with the command. A simple command looks like this:

addInterest: {
  tag: 'actions',
  arguments: [
    {
      label: 'interest',
      values: ['language', 'skillLevel', 'occupation'],
    },
    {
      label: 'value',
      dependant: true,
      values: [
        ['Java', 'C', 'Python', 'JavaScript', '.NET'],
        ['amateur', 'intermediate', 'expert'],
        ['frontend', 'backend', 'fullStack'],
      ],
    },
  ],
  function: function(req, res, args) {
    console.log('Add Interest: ' + args[0] + ' - ' + args[1]);
  },
},

After the user inputs a command and runs it, it gets sent to a post function. This function goes through a few steps to validate the command:

  1. Split up the input into a command and arguments:
const input = req.body.command.split(' ');
const command = input.slice(0, 1);
const args = input.slice(1);
> Step 2
  1. Check if the command exists in the command list:
if (command in commandList) {
  > Step 3
}
  1. Check if the amount of given arguments are the required amount:
if (args.length === chosenCommand.arguments.length) {
  > Step 4
}
  1. Loop through input arguments and check against defined command argument values. If it is a dependant, find out which value list to use according to the index of the value of the previous argument:
let argsCorrect = true;
for ([i, argument] of args.entries()) {
  if (argsCorrect) {
    let valueList = chosenCommand.arguments[i].values;
    if (chosenCommand.arguments[i].dependant) {
      valueList = valueList[chosenCommand.arguments[i-1].values.indexOf(args[i-1])];
    }
    if (!valueList.includes(argument)) {
      argsCorrect = false;
    }
  }
  > Step 5
};
  1. Run the command if arguments are of correct values:
if (argsCorrect) {
  chosenCommand.function(req, res, args);
}