<commit_before>import Morph from './Morph.js';

const isLocalHost = document.location.hostname.indexOf('localhost') > -1;
const localBaseURL = 'http://localhost:9007/';
const remoteBaseURL = 'https://lively-kernel.org/lively4services/';
var servicesURL = isLocalHost ? localBaseURL : remoteBaseURL;
const localDebugURL = 'http://localhost:9008/';
const remoteDebugURL = 'https://lively-kernel.org/lively4servicesDebug/';
var debuggerURL = isLocalHost ? localDebugURL : remoteDebugURL;

export default class Services extends Morph {

  initialize() {
    this.windowTitle = 'Services';
    this.pid = null;
    this.logType = 'stdout';
    this.services = {};

    this.serviceTop = this.getSubmorph('#service-top');
    this.entryPoint = this.getSubmorph('#entryPoint');

    this.serviceList = this.getSubmorph('.items');
    $(this.serviceList).on('click', 'lively-services-item', this.itemClick.bind(this));

    this.addButton = this.getSubmorph('#addButton');
    this.addButton.addEventListener('click', this.addButtonClick.bind(this));
    this.removeButton = this.getSubmorph('#removeButton');
    this.removeButton.addEventListener('click', this.removeButtonClick.bind(this));
    this.editButton = this.getSubmorph('#editButton');
    this.editButton.addEventListener('click', this.editButtonClick.bind(this));
    this.settingsButton = this.getSubmorph('#settingsButton');
    this.settingsButton.addEventListener('click', this.settingsButtonClick.bind(this));
    this.startButton = this.getSubmorph('#startButton');
    this.startButton.addEventListener('click', this.startButtonClick.bind(this));
    this.stopButton = this.getSubmorph('#stopButton');
    this.stopButton.addEventListener('click', this.stopButtonClick.bind(this));
    this.debugButton = this.getSubmorph('#debugButton');
    this.debugButton.addEventListener('click', this.debugButtonClick.bind(this));
    this.stdoutButton = this.getSubmorph('#stdoutButton');
    this.stderrButton = this.getSubmorph('#stderrButton');
    this.stdoutButton.addEventListener('click', this.stdoutButtonClick.bind(this));
    this.stderrButton.addEventListener('click', this.stderrButtonClick.bind(this));

    this.logEditor = this.getSubmorph('#log').editor;
    this.logEditor.setReadOnly(true);

    this.refreshServiceList();
    this.refreshInterval = window.setInterval(() => {
      this.refreshServiceList();
    }, 5000);
    this.logInterval = null;

    this.detachedCallback = () => {
      window.clearInterval(this.refreshInterval);
      window.clearInterval(this.logInterval);
    };
  }

  /*
  * Event handlers
  */
  itemClick(evt) {
    this.unselectAll();
    evt.target.getSubmorph('.item').classList.add('selected');
    this.pid = evt.target.getAttribute('data-id');
    this.showService();
  }

  addButtonClick(evt) {
    this.serviceTop.removeAttribute('data-id');
    this.entryPoint.value = '';
    this.entryPoint.focus();
    this.logEditor.setValue('');
    this.unselectAll();
  }

  removeButtonClick() {
    if (this.pid === null) {
      console.log('Nothing to remove');
      return;
    }
    this.post('remove', { id: this.pid }, function(res) {
      console.log(res);
      this.refreshServiceList();
    }.bind(this));
  }

  editButtonClick() {
    lively.openBrowser(servicesURL + 'lively/');
  }

  settingsButtonClick() {
    var userInput;
    userInput = window.prompt('Please enter service endpoint', servicesURL);
    if (userInput !== null) {
      servicesURL = userInput;
    }
    userInput = window.prompt('Please enter debugger endpoint', debuggerURL);
    if (userInput !== null) {
      debuggerURL = userInput;
    }
  }

  startButtonClick() {
    var data;
    if (this.pid !== null) {
      data = { id: this.pid };
    } else {
      data = { entryPoint: this.entryPoint.value };
    }
    this.post('start', data, function(res) {
      console.log(res);
      this.refreshServiceList();
    }.bind(this));
  }
<commit_msg>Minor UX bugfix [ci skip]<commit_after>import Morph from './Morph.js';

const isLocalHost = document.location.hostname.indexOf('localhost') > -1;
const localBaseURL = 'http://localhost:9007/';
const remoteBaseURL = 'https://lively-kernel.org/lively4services/';
var servicesURL = isLocalHost ? localBaseURL : remoteBaseURL;
const localDebugURL = 'http://localhost:9008/';
const remoteDebugURL = 'https://lively-kernel.org/lively4servicesDebug/';
var debuggerURL = isLocalHost ? localDebugURL : remoteDebugURL;

export default class Services extends Morph {

  initialize() {
    this.windowTitle = 'Services';
    this.pid = null;
    this.logType = 'stdout';
    this.services = {};

    this.serviceTop = this.getSubmorph('#service-top');
    this.entryPoint = this.getSubmorph('#entryPoint');

    this.serviceList = this.getSubmorph('.items');
    $(this.serviceList).on('click', 'lively-services-item', this.itemClick.bind(this));

    this.addButton = this.getSubmorph('#addButton');
    this.addButton.addEventListener('click', this.addButtonClick.bind(this));
    this.removeButton = this.getSubmorph('#removeButton');
    this.removeButton.addEventListener('click', this.removeButtonClick.bind(this));
    this.editButton = this.getSubmorph('#editButton');
    this.editButton.addEventListener('click', this.editButtonClick.bind(this));
    this.settingsButton = this.getSubmorph('#settingsButton');
    this.settingsButton.addEventListener('click', this.settingsButtonClick.bind(this));
    this.startButton = this.getSubmorph('#startButton');
    this.startButton.addEventListener('click', this.startButtonClick.bind(this));
    this.stopButton = this.getSubmorph('#stopButton');
    this.stopButton.addEventListener('click', this.stopButtonClick.bind(this));
    this.debugButton = this.getSubmorph('#debugButton');
    this.debugButton.addEventListener('click', this.debugButtonClick.bind(this));
    this.stdoutButton = this.getSubmorph('#stdoutButton');
    this.stderrButton = this.getSubmorph('#stderrButton');
    this.stdoutButton.addEventListener('click', this.stdoutButtonClick.bind(this));
    this.stderrButton.addEventListener('click', this.stderrButtonClick.bind(this));

    this.logEditor = this.getSubmorph('#log').editor;
    this.logEditor.setReadOnly(true);

    this.refreshServiceList();
    this.refreshInterval = window.setInterval(() => {
      this.refreshServiceList();
    }, 5000);
    this.logInterval = null;

    this.detachedCallback = () => {
      window.clearInterval(this.refreshInterval);
      window.clearInterval(this.logInterval);
    };
  }

  /*
  * Event handlers
  */
  itemClick(evt) {
    this.unselectAll();
    evt.target.getSubmorph('.item').classList.add('selected');
    this.pid = evt.target.getAttribute('data-id');
    this.showService();
  }

  addButtonClick(evt) {
    this.serviceTop.removeAttribute('data-id');
    this.entryPoint.value = '';
    this.entryPoint.focus();
    this.logEditor.setValue('');
    this.unselectAll();
  }

  removeButtonClick() {
    if (this.pid === null) {
      console.log('Nothing to remove');
      return;
    }
    this.post('remove', { id: this.pid }, function(res) {
      console.log(res);
      this.refreshServiceList();
    }.bind(this));
  }

  editButtonClick() {
    lively.openBrowser(servicesURL + 'lively/');
  }

  settingsButtonClick() {
    var userInput;
    userInput = window.prompt('Please enter service endpoint', servicesURL);
    if (userInput !== null) {
      servicesURL = userInput;
    }
    userInput = window.prompt('Please enter debugger endpoint', debuggerURL);
    if (userInput !== null) {
      debuggerURL = userInput;
    }
  }

  startButtonClick() {
    var data;
    if (this.pid !== null) {
      data = { id: this.pid };
    } else {
      data = { entryPoint: this.entryPoint.value };
    }
    this.post('start', data, function(res) {
      console.log(res);
      this.refreshServiceList();
      this.showService();
    }.bind(this));
  }

{'fraction_non_alphanumeric': 0.1540785498489426, 'fraction_numerical': 0.0037764350453172208, 'mean_word_length': 3.9687304565353347, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4486687', 'n_tokens_mistral': 2412, 'n_tokens_neox': 2373, 'n_words': 361}