<div id="operationsPage" x-data="alpineOperations()" x-init="initOperations()"
     xmlns="http://www.w3.org/1999/html">
    <div>
        <div>
            <div x-ref="operationsHeader">
                <h2>Operations</h2>
            </div>
            <hr>
        </div>

        <form>
            <div id="select-operation" class="field has-addons">
                <label class="label">Select an operation &nbsp;&nbsp;&nbsp;</label>
                <div class="control is-expanded">
                    <div class="select is-small is-fullwidth">
                        <select x-on:change="getOperations(); getOperation();" x-model="selectedOperationID">
                            <option value="" default disabled selected>Select one...</option>
                            <template x-for="op in operations" :key="op.id">
                                <option x-bind:value="op.id"
                                        x-bind:title="op.name + ' has ' + op.chain.length + ' decisions'">
                                    <span x-text="op.name"></span>
                                    <span x-text="' - ' + op.chain.length + ' decisions | ' + getHumanFriendlyTimeISO8601(op.start)"></span>
                                </option>
                            </template>
                        </select>
                    </div>
                </div>
                <div class="control">
                    <button type="button" class="button is-primary is-small"
                            x-on:click="openOperationCreateModal()">
                        <em class="pr-1 fas fa-plus"></em>
                        Create Operation
                    </button>
                </div>
            </div>
        </form>

        <template x-if="selectedOperation && selectedOperationID">
            <div class="section p-2 pb-2">
                <div class="control-buttons is-flex is-flex-direction-row is-justify-content-space-between">
                    <div class="buttons">
                        <button class="button is-small" x-on:click="openModal='showOperationDetails'" title="view operation details">Operation Details</button>
                        <button title="download reports" class="button is-primary is-small" x-on:click="openModal = 'showDownloadMenu'">
                            <span class="icon">
                                <em class="fas fa-arrow-down"></em>
                            </span>
                            <span>Download</span>
                        </button>
                        <button type="button" title="delete operation" class="button is-danger is-outlined is-small" x-on:click="openModal = 'deleteOperationModal'">
                            <span class="icon">
                                <em class="fas fa-trash"></em>
                            </span>
                            <span>Delete</span>
                        </button>
                        <div class="vr"></div>
                        <span>Current state: <span class="level-item tag is-medium m-0"><span
                                class="has-text-success" x-text="selectedOperation.state"></span></span></span>
                    </div>

                    <!-- OPERATION CONTROLS -->
                    <div class="controls-container is-flex is-justify-content-center is-align-items-center">
                        <template x-if="isOperationRunning">
                            <div class="is-flex is-flex-direction-column is-align-items-center">
                                <button x-bind:disabled="!isOperationRunning" class="button no-style is-large"
                                        x-on:click="updateOperation('state', 'cleanup')" id="op-stop-button"><em
                                        title="stop" class="fas fa-stop"></em></button>
                                <label class="label is-small" for="op-stop-button">Stop</label>
                            </div>
                        </template>
                        <template x-if="selectedOperation.state === 'running' && isOperationRunning">
                            <div class="is-flex is-flex-direction-column is-align-items-center">
                                <button x-bind:disabled="!isOperationRunning"
                                        class="button no-style is-larger" id="op-pause-button"
                                        x-on:click="updateOperation('state', 'paused')"><em
                                        title="pause" class="fas fa-pause-circle"></em></button>
                                <label class="label is-small" for="op-pause-button">Pause</label>
                            </div>
                        </template>
                        <template x-if="selectedOperation.state !== 'running' && isOperationRunning">
                            <div class="is-flex is-flex-direction-column is-align-items-center">
                                <button x-bind:disabled="!isOperationRunning"
                                        class="button no-style is-larger" id="op-run-button"
                                        x-on:click="updateOperation('state', 'running')">
                                    <em title="run" class="fas fa-play-circle"></em></button>
                                <label class="label is-small" for="op-run-button">Run</label>
                            </div>
                        </template>
                        <template x-if="isOperationRunning">
                            <div class="is-flex is-flex-direction-column is-align-items-center">
                                <button x-bind:disabled="!isOperationRunning" class="button no-style is-medium"
                                        x-on:click="updateOperation('state', 'run_one_link')" id="op-run-1-button">
                                    <em title="run one step" class="fas fa-play"><sub>1</sub></em></button>
                                <label class="label is-small" for="op-run-1-button">Run 1 Link</label>
                            </div>
                        </template>
                        <template x-if="!isOperationRunning">
                            <div class="is-flex is-flex-direction-column is-align-items-center">
                                <button class="button no-style is-large" x-on:click="rerunOperation()">
                                        <em title="Re-run operation with same settings" class="fas fa-redo-alt"></em>
                                </button>
                                <label class="label is-small">Re-run operation</label>
                            </div>
                        </template>
                    </div>

                    <div class="is-flex is-flex-direction-row">
                        <!-- OBFUSCATION DROPDOWN -->
                        <div>
                            <span class="is-flex is-align-items-center">
                                <span class="mr-2">Obfuscation:</span>
                                <template x-if="!isOperationRunning">
                                    <span class="level-item tag is-medium m-0"><span
                                            class="has-text-success"
                                            x-text="selectedOperation.obfuscator"></span></span>
                                </template>
                                <template x-if="isOperationRunning">
                                    <div class="select is-small">
                                        <select id="operation-obfuscator"
                                                x-on:change="updateOperation('obfuscator', $el.value)"
                                                x-model="selectedOperation.obfuscator">
                                            <option value="" default disabled selected>Select one...</option>
                                            <template x-for="o in OBFUSCATORS" :key="o.name">
                                                <option x-bind:value="o.name" x-text="o.name"></option>
                                            </template>
                                        </select>
                                    </div>
                                </template>
                            </span>
                        </div>

                        <div class="vr"></div>

                        <!-- TOGGLE -->
                        <div class="mb-5 is-flex is-flex-direction-row is-justify-content-center is-align-items-center">
                            <template x-if="!isOperationRunning">
                                <span class="level-item tag is-medium m-0">
                                    <span class="has-text-success" x-text="selectedOperation.autonomous === 0 ? 'manual' : 'autonomous'"></span>
                                </span>
                            </template>
                            <template x-if="isOperationRunning">
                                <div class="toggleContainer flex is-flex-direction-column is-align-items-left">
                                  <div>
                                    <label for="toggleAutonomous">Manual</label>
                                    <div class="toggleSwitch mx-2">
                                        <input type="checkbox"
                                               id="toggleAutonomous"
                                               x-model="selectedOperation.autonomous"
                                               x-bind:checked="Boolean(selectedOperation.autonomous) ? 'checked' : null"/>
                                        <span class="toggleSlider toggleSliderRound"
                                              title="Toggle operation to run autonomously"
                                              x-on:click="selectedOperation.autonomous = (selectedOperation.autonomous === 0) ? 1 : 0; updateOperation('autonomous', Number(selectedOperation.autonomous))"
                                              x-bind:class="Boolean(selectedOperation.autonomous) ? 'toggle-on' : 'toggle-off'">
                                            <span x-bind:class="Boolean(selectedOperation.autonomous) ? 'toggle-slider-on' : 'toggle-slider-off'"></span>
                                        </span>
                                    </div>
                                    <label for="toggleAutonomous">Autonomous</label>
                                  </div>
                                  <div class="mt-4">
                                    <label for="toggleScroll">Autoscroll</label>
                                    <div class="toggleSwitch">
                                        <input type="checkbox"
                                               id="toggleAutonomous"
                                               x-model="linkScrollHistory.isEnabled"
                                               x-bind:checked="linkScrollHistory.isEnabled ? 'checked' : null"/>
                                        <span class="toggleSlider toggleSliderRound"
                                              title="Toggle autoscrolling"
                                              x-on:click="linkScrollHistory.isEnabled = (linkScrollHistory.isEnabled === false) ? true : false"
                                              x-bind:class="linkScrollHistory.isEnabled ? 'toggle-on' : 'toggle-off'">
                                            <span x-bind:class="linkScrollHistory.isEnabled ? 'toggle-slider-on' : 'toggle-slider-off'"></span>
                                        </span>
                                    </div>
                                  </div>
                                </div>
                            </template>
                        </div>
                    </div>
                </div>
            </div>
        </template>
        <div>
            <!--            TIMELINE-->
            <template x-if="selectedOperation && selectedOperationID">
                <div>
                    <div class="navbar-divider mb-5"></div>
                    <template x-if="isOperationRunning">
                        <div class="is-flex is-flex-direction-row is-justify-content-space-between">
                            <div class="has-text-grey-light is-size-7">
                                <em x-show="selectedOperation.chain.length > 0"><span
                                        class="has-text-grey-light"
                                        x-text="'Last ran ' + selectedOperation.chain[selectedOperation.chain.length-1]?.ability.name + ' (' + getLastDecideTime() + ')'"></span></em>
                            </div>
                            <div class="is-flex is-flex-direction-row is-justify-content-flex-end">
                                <div class="mb-6 mr-4 text-align-right">
                                    <button title="add manual command" class="button is-small" x-on:click="addNewRow = true; getAgents(); setTimeout(() => {document.querySelector('#input-command').scrollIntoView()}, 2);">
                                        <span class="icon"><em class="pr-1 fas fa-plus"></em></span>
                                        <span>Manual Command</span>
                                    </button>
                                </div>
                                <div class="mb-6 mr-4">
                                    <button title="add potential link" class="button is-small" x-on:click="openPotentialLinkModal()">
                                        <span class="icon"><em class="pr-1 fas fa-plus"></em></span>
                                        <span>Potential Link</span>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </template>
                    <div class="timeline-table">
                        <table class="table">
                            <thead>
                            <tr class="table-header">
                                <th class="decideColumn">Decide</th>
                                <th id="link-status-header" class="statusColumn csv-exclude pl-4"
                                    title="Link Status Indicator">
                                    Status
                                </th>
                                <th class="infoColumn">Link/Ability Name</th>
                                <th>Agent #paw</th>
                                <th>Host</th>
                                <th>pid</th>
                                <th>Link Command</th>
                                <th>Link Output</th>
                                <th title="Link Actions" class="csv-exclude"></th>
                            </tr>
                            </thead>

                            <template x-if="selectedOperation.chain.length === 0">
                                <tbody>
                                <tr class="csv-exclude">
                                    <td colspan="9" class="has-text-centered"><em>No links––click the buttons on the
                                        right to add
                                        commands/links.</em>
                                    </td>
                                </tr>
                                </tbody>
                            </template>
                            <template x-for="(link, index) in selectedOperation.chain" :key="link.id">
                                <tbody>
                                <tr x-bind:id="link.id"
                                    x-on:click="selectedLink = link" x-ref="linkRow" x-init="$nextTick(() => scrollToLastLink($refs.linkRow, index))">
                                    <td class="decideColumn">
                                        <span class="has-text-grey-light" x-text="getReadableTime(link.decide)"></span>
                                    </td>
                                    <td class="linkStatusColumn csv-exclude" headers="link-status-header">
                                        <span x-bind:class="'linkStatus status-'+((link.status in LINK_STATUSES) ? LINK_STATUSES[link.status] : 'queued')"
                                              x-bind:data-content="link.status in LINK_STATUSES ? LINK_STATUSES[link.status] : 'queued'"
                                              x-bind:title="link.status in LINK_STATUSES ? LINK_STATUSES[link.status] : 'queued'"></span>
                                    </td>
                                    <td class="linkInfoColumn"
                                        x-text="link.ability.name + ((link.ability.cleanup) ? '(CLEANUP)' : '')"></td>

                                    <!--AGENT COLUMN-->
                                    <td class="agentDetails">
                                        <p x-show="!link.paw"><em>n/a</em></p>
                                        <p x-show="link.paw"><em x-text="link.paw"></em></p>
                                    </td>
                                    <td class="agentDetails">
                                        <p x-show="!link.host"><em>n/a</em></p>
                                        <p x-show="link.host"><em x-text="link.host"></em></p>
                                    </td>
                                    <td class="agentDetails">
                                        <p x-show="!link.pid" class="mb-0"><em>n/a</em></p>
                                        <p x-show="link.pid"><em x-text="link.pid"></em></p>
                                    </td>

                                    <!--COMMAND COLUMN-->
                                    <td class="commandDetails">
                                        <div class="is-flex is-justify-content-flex-start">
                                            <template x-if="!isLinkEditable(link)">
                                                <button class="button is-small"
                                                        x-on:click="getLink(link); openModal='showCommand'"
                                                        title="view output">View Command
                                                </button>
                                            </template>
                                            <template x-if="isLinkEditable(link)">
                                                <button class="button is-small is-warning is-outlined"
                                                        x-on:click="getLink(link); openModal='showCommand'"
                                                        title="view output">
                                                    <i class="fas fa-exclamation-triangle pr-2"></i>
                                                    Review Command
                                                </button>
                                            </template>
                                        </div>
                                    </td>

                                    <!--OUTPUT/FACTS COLUMN-->
                                    <td class="outputDetails">
                                        <template x-if="link.output !== 'True'">
                                            <p class="is-size-7 is-italic ml-4">No output.</p>
                                        </template>
                                        <template x-if="link.output === 'True'">
                                            <div>
                                                <button class="button is-small"
                                                        x-on:click="getLink(link); openModal='showOutput'"
                                                        title="view output">View Output
                                                </button>
                                            </div>
                                        </template>
                                    </td>

                                    <td class="csv-exclude">
                                        <button x-show="selectedLink === link && isOperationRunning && !(link.status in LINK_STATUSES)"
                                                type="button" title="delete link"
                                                class="button is-danger is-outlined is-small ml-2"
                                                x-on:click="openModal = 'deleteLinkModal'"><em
                                                class="pr-1 fas fa-trash"></em>Discard Link
                                        </button>
                                    </td>
                                </tr>
                                </tbody>
                            </template>

                            <!--                                NEW ROW TO ADD MANUAL COMMAND-->
                            <template x-if="addNewRow">
                                <tbody>
                                <tr class="csv-exclude" x-data="{manualCommand: EMPTY_MANUAL_COMMAND_OBJECT}">
                                    <template x-if="selectedOperation.host_group.length < 1">
                                        <td colspan="9" class="has-text-right"><em>No agents running. Add an agent
                                            to run an operation.</em></td>
                                    </template>
                                </tr>

                                <template x-if="selectedOperation.host_group.length > 0">
                                    <tr class="csv-exclude" x-data="{manualCommand: EMPTY_MANUAL_COMMAND_OBJECT}">
                                        <td></td>
                                        <td></td>
                                        <td>New Manual Command</td>
                                        <td>
                                            <label x-show="false" for="manual-agent">Choose an agent:</label>
                                            <div class="select is-small my-2 ml-3">
                                                <select id="manual-agent" x-model="selectedAgentIndex"
                                                        x-on:change="getAgent(selectedAgent.paw)" required>
                                                    <option value="" disabled>Choose agent</option>
                                                    <template x-for="(agent, index) in selectedOperation.host_group"
                                                              :key="agent.paw">
                                                        <option x-bind:selected="index === 0"
                                                                :value="index"
                                                                x-text="agent.display_name + '-' + agent.paw"></option>
                                                    </template>
                                                </select>
                                            </div>
                                        </td>
                                        <td>
                                            <div class="select is-small my-2 ml-3">
                                                <select x-model="manualCommand.executor.name"
                                                        id="manual-executors"
                                                        class="executor-selector">
                                                    <option value="" disabled>Choose executor</option>
                                                    <template x-for="(executor, index) in selectedAgentExecutors"
                                                              :key="executor.executor">
                                                        <option x-bind:selected="index === 0"
                                                                x-text="executor.display"
                                                                :value="executor.executor"></option>
                                                    </template>
                                                </select>
                                            </div>
                                        </td>
                                        <td colspan="2">
                                            <label x-show="false" for="input-command">Type manual command:</label>
                                            <div class="is-flex is-align-items-flex-end is-justify-content-center is-flex-direction-column">
                                            <textarea x-model="manualCommand.executor.command"
                                                      class="input executor-command"
                                                      id="input-command"
                                                      type="text"
                                                      spellcheck="false"
                                                      contenteditable
                                                      required></textarea>
                                            </div>
                                        </td>
                                        <td class="is-flex is-justify-content-center is-flex-direction-column">
                                            <button type="button"
                                                    class="button is-primary is-small my-2"
                                                    x-on:click="addManualCommand(manualCommand)">
                                                Add Command
                                            </button>
                                            <button type="button"
                                                    class="button is-small"
                                                    x-on:click="addNewRow = false">
                                                Cancel
                                            </button>
                                        </td>
                                    </tr>
                                </template>
                                </tbody>
                            </template>
                        </table>
                    </div>

                    <!--                                ADD COMMAND/LINK BUTTONS-->
                    <template x-if="isOperationRunning">
                        <div class="is-flex is-flex-direction-row is-justify-content-flex-end">
                            <div class="mb-6 mr-4 text-align-right">
                                <button title="add manual command" class="button is-small" x-on:click="addNewRow = true; getAgents(); setTimeout(() => {document.querySelector('#input-command').scrollIntoView()}, 2);">
                                    <span class="icon"><em class="pr-1 fas fa-plus"></em></span>
                                    <span>Manual Command</span>
                                </button>
                            </div>
                            <div class="mb-6 mr-4">
                                <button title="add potential link" class="button is-small" x-on:click="openPotentialLinkModal()">
                                    <span class="icon"><em class="pr-1 fas fa-plus"></em></span>
                                    <span>Potential Link</span>
                                </button>
                            </div>
                        </div>
                    </template>
                </div>
            </template>
        </div>

        <!--    MODALS      -->
        <template x-if="openModal">
            <div class="modal is-active">
                <div class="modal-background" @click="openModal = null; selectPotentialLink({})"></div>

                <template x-if="openModal === 'showOutput'">
                    <div class="modal-card wide">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Output</p>
                        </header>
                        <section class="modal-card-body">
                            <template x-if="selectedLinkFacts?.length > 0">
                                <div class="mb-2">
                                    <p class="mt-3 mb-2">Facts:</p>
                                    <pre class="has-text-left white-space-pre-line">
                                        <table>
                                            <thead>
                                                <tr>
                                                    <th>Name</th>
                                                    <th>Value</th>
                                                    <th>Score</th>
                                                </tr>
                                            </thead>
                                            <tbody>
                                                <template x-for="(fact, index) in selectedLinkFacts" :key="fact+index">
                                                    <tr>
                                                        <td x-text="fact.name"></td>
                                                        <td x-text="fact.value"></td>
                                                        <td x-text="fact.score"></td>
                                                    </tr>
                                                </template>
                                            </tbody>
                                        </table>
                                    </pre>
                                </div>
                            </template>
                            <div>
                                <p class="mt-3 mb-2" x-text="`Exit Code: ${selectedLinkResults && selectedLinkResults.exit_code ? selectedLinkResults.exit_code : 'Nothing to show'}`"></p>
                                <p class="mt-3 mb-2" x-text="`Standard Output: ${selectedLinkResults && selectedLinkResults.stdout ? '' : 'Nothing to show'}`"></p>
                                <template x-if="selectedLinkResults != null && selectedLinkResults.stdout !== ''">
                                    <pre class="has-text-left white-space-pre-line" x-text="selectedLinkResults.stdout"></pre>
                                </template>
                            </div>
                            <div>
                                <p class="mt-3 mb-2" x-text="`Standard Error: ${selectedLinkResults && selectedLinkResults.stderr ? '' : 'Nothing to show'}`"></p>
                                <template x-if="selectedLinkResults != null && selectedLinkResults.stderr !== ''">
                                    <pre class="has-text-left white-space-pre-line has-text-danger" x-text="selectedLinkResults.stderr"></pre>
                                </template>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'showCommand'">
                    <div class="modal-card wide">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Command</p>
                        </header>
                        <section class="modal-card-body">
                            <template x-if="isLinkEditable(selectedLink)">
                                <div>
                                    <label x-show="false" htmlFor="edit-command">Edit command</label>
                                    <textarea id="edit-command"
                                              class="textarea is-small code"
                                              contentEditable
                                              x-model="editableCommand"
                                              spellCheck="false"></textarea>
                                </div>
                            </template>
                            <template x-if="!isLinkEditable(selectedLink)">
                                <div>
                                <template x-if="!selectedLinkPlaintextCommand || selectedLinkPlaintextCommand == selectedLinkCommand">      
                                    <div>
                                        <pre class="has-text-left white-space-pre-line" x-text="selectedLinkCommand"></pre>
                                    </div>
                                </template>
                                <template x-if="selectedLinkPlaintextCommand && selectedLinkPlaintextCommand !== selectedLinkCommand">
                                    <div>
                                        <p class="mt-3 mb-2">Obfuscated:</p>
                                        <pre class="has-text-left white-space-pre-line" x-text="selectedLinkCommand"></pre>
                                        <p class="mt-3 mb-2">Plaintext:</p>
                                        <pre class="has-text-left white-space-pre-line" x-text="selectedLinkPlaintextCommand"></pre>
                                    </div>
                                </template>
                                </div>
                            </template>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <template x-if="isLinkEditable(selectedLink)">
                                        <button type="button"
                                                class="button is-danger is-outlined is-small"
                                                x-on:click="updateLink(-2); openModal = null;">
                                            Discard
                                        </button>
                                    </template>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                    <template x-if="isLinkEditable(selectedLink)">
                                        <div class="level-item">
                                            <button type="button"
                                                    class="button is-primary is-small"
                                                    x-on:click="updateLink(-3, editableCommand); openModal = null;">
                                                Approve
                                            </button>
                                        </div>
                                    </template>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'addOperation'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Start New Operation</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <label for="op-name">Operation name</label>
                                    <div class="modal-form-fields">
                                        <input class="input is-small" id="op-name" type="text"
                                               x-model="operationToStart.name" required>
                                    </div>
                                </div>
                                <div>
                                    <label for="basic-adversary"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Adversary']">Adversary</span></label>
                                    <div class="modal-form-fields" id="basic-adversary">
                                        <div class="select is-small my-2 ml-3">
                                            <select x-model="operationToStart.adversary.adversary_id"
                                                    x-on:change="handleSelectAdversary()">
                                                <option value="" selected>No adversary (manual)</option>
                                                <template x-for="a in ADVERSARIES" :key="a.adversary_id">
                                                    <option :value="a.adversary_id" x-text="a.name"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>

                                <div>
                                    <label for="autonomous-source"><span class="has-tooltip-multiline has-tooltip-top" x-bind:data-tooltip="usage['Fact source']">Fact source</span></label>
                                    <div class="modal-form-fields" id="autonomous-source">
                                        <div class="select is-small my-2 ml-3">
                                            <select x-model="operationToStart.source.id">
                                                <template x-for="s in SOURCES" :key="s.id">
                                                    <option :value="s.id" x-text="s.name"
                                                            x-bind:selected="operationToStart.source.id === s.id"></option>
                                                </template>
                                            </select>
                                        </div>
                                    </div>
                                </div>

                            </div>
                            <div class="modal-form-group-header">
                                <button type="button" class="button no-style heading pt-2"
                                        x-on:click="openModalForm.advanced = !openModalForm.advanced"
                                        x-bind:class="openModalForm.advanced ? 'expanded' : 'collapsed'">
                                    <span>Advanced</span>
                                    <span class="navbar-divider"></span>
                                </button>
                            </div>
                            <div class="modal-form" x-show="openModalForm.advanced">
                                <div>
                                    <label for="basic-groups"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Group']">Group</span></label>
                                    <div class="modal-form-fields"
                                         id="basic-groups">
                                        <button type="button"
                                                class="is-small button is-rounded is-primary m-1"
                                                x-bind:class="(operationToStart.group === '') ? '' : 'is-outlined has-text-white'"
                                                x-on:click="operationToStart.group = ''">
                                            all groups
                                        </button>
                                        <template x-for="(group, index) in agentGroups" :key="group">
                                            <button type="button"
                                                    class="is-small button is-rounded is-primary m-1"
                                                    x-bind:class="(operationToStart.group === group) ? '' : 'is-outlined has-text-white'"
                                                    x-on:click="operationToStart.group = group"
                                                    x-show="group !== ''"
                                                    x-text="group">
                                            </button>
                                        </template>
                                    </div>
                                </div>
                                <div>
                                    <label for="autonomous-planner"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Planner']">Planner</span></label>
                                    <div class="modal-form-fields">
                                        <div class="select is-small my-2 ml-3">
                                            <select id="autonomous-planner" x-model="operationToStart.planner.id">
                                                <template x-for="p in PLANNERS" :key="p.id">
                                                    <option :value="p.id"
                                                            x-bind:selected="operationToStart.planner.id === p.id"
                                                            x-bind:disabled="(!p.allow_repeatable_abilities && isSelectedAdversaryRepeatable)"
                                                            x-text="p.name"></option>
                                                </template>
                                            </select>
                                        </div>
                                        <span x-show="isSelectedAdversaryRepeatable" class="icon has-text-warning ml-2"
                                              data-tooltip="The selected adversary has repeated abilities so some planners are unavailable.">
                                            <em class="fas fa-exclamation-triangle"></em>
                                        </span>
                                    </div>
                                </div>
                                <div>
                                    <label for="stealth-obfuscator"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Obfuscators']">Obfuscators</span></label>
                                    <div class="modal-form-fields" id="stealth-obfuscator">
                                        <template x-for="o in OBFUSCATORS" :key="o.name">
                                            <button class="is-small button is-rounded is-primary m-1"
                                                    type="button"
                                                    x-bind:class="operationToStart.obfuscator === o.name ? '' : 'is-outlined has-text-white'"
                                                    x-on:click="operationToStart.obfuscator = o.name"
                                                    x-text="o.name">
                                            </button>
                                        </template>
                                    </div>
                                </div>
                                <div>
                                    <label for="autonomous-autonomous"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Autonomous']">Autonomous</span></label>
                                    <div class="modal-form-fields" id="autonomous-autonomous">
                                        <input type="radio" id="run-autonomously"
                                               x-model="operationToStart.autonomous" value="1" checked>
                                        <label for="run-autonomously">Run autonomously</label>
                                        <input type="radio" id="manual-approval"
                                               x-model="operationToStart.autonomous" value="0">
                                        <label for="manual-approval">Require manual approval</label>
                                    </div>
                                </div>

                                <div>
                                    <label for="autonomous-use_learning_parsers"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Parser']">Parser</span></label>
                                    <div class="modal-form-fields" id="autonomous-use_learning_parsers">
                                        <input type="radio" id="parsers-default"
                                               x-model="operationToStart.use_learning_parsers" value="1" checked>
                                        <label for="parsers-default">Use default parsers</label>
                                        <input type="radio" id="parsers-no_default"
                                               x-model="operationToStart.use_learning_parsers" value="0">
                                        <label for="parsers-no_default">Do not use default parsers</label>
                                    </div>
                                </div>

                                <div>
                                    <label for="basic-keep"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Auto-close']">Auto-close</span></label>
                                    <div class="modal-form-fields" id="basic-keep">
                                        <input type="radio" id="keep-open"
                                               x-model="operationToStart.auto_close"
                                               value="0" checked>
                                        <label for="keep-open">Keep open forever</label>
                                        <input type="radio" id="auto-close"
                                               x-model="operationToStart.auto_close"
                                               value="1">
                                        <label for="auto-close">Auto close operation</label>
                                    </div>
                                </div>
                                <div>
                                    <label for="basic-run"><span
                                            class="has-tooltip-multiline has-tooltip-bottom"
                                            x-bind:data-tooltip="usage['Run immediately']">Run state</span></label>

                                    <div class="modal-form-fields" id="basic-run">
                                        <input type="radio" x-model="operationToStart.state"
                                               id="run-immediately"
                                               value="running" checked>
                                        <label for="run-immediately">Run immediately</label>
                                        <input type="radio" x-model="operationToStart.state"
                                               id="pause-on-start"
                                               value="paused">
                                        <label for="pause-on-start">Pause on start</label>
                                    </div>
                                </div>

                                <div>
                                    <label for="stealth-jitter"><span
                                            class="has-tooltip-multiline has-tooltip-top"
                                            x-bind:data-tooltip="usage['Jitter']">Jitter (sec/sec)</span></label>
                                    <div class="modal-form-fields" id="stealth-jitter">
                                        <input class="input"
                                               :class="{ 'is-danger': !isJitterValid() }"
                                               x-model="jitterMin"
                                               id="stealth-jitterMin"
                                               type="number"
                                               required
                                               pattern="[0-9]*"
                                               placeholder="2"/>
                                        <label class="input-hover-label" for="stealth-jitterMin">min</label>
                                        <span>/</span>
                                        <input class="input"
                                               :class="{ 'is-danger': !isJitterValid() }"
                                               x-model="jitterMax"
                                               id="stealth-jitterMax"
                                               type="number"
                                               required
                                               pattern="[0-9]*"
                                               placeholder="8"/>
                                        <label class="input-hover-label" for="stealth-jitterMax">max</label>
                                        <button type="button" class="button is-primary no-style reset"
                                                title="reset to default"
                                                x-on:click="jitterMin = 2; jitterMax = 8;">
                                            Reset
                                        </button>
                                        <p x-show="!isJitterValid()" class="pl-3 help has-text-danger">
                                            Min and Max need to be >= 0, and Min must be <= Max
                                        </p>
                                    </div>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="addOperation()"
                                                x-text="schedule ? 'Schedule' : 'Start'"></button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'showOperationDetails'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Operation Details</p>
                        </header>
                        <section class="modal-card-body">
                            <table>
                                <col width="35%">
                                <col width="65%">
                                <tbody>
                                    <tr>
                                        <td>
                                            <label class="label">Operation Name</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.name"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Adversary</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.adversary.name"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Fact Source</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.source.name"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Group</label>
                                        </td>
                                        <td>
                                            <span x-text="(selectedOperation.group ? selectedOperation.group : 'all')"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Planner</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.planner.name"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Obfuscator</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.obfuscator"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Autonomous</label>
                                        </td>
                                        <td>
                                            <span x-text="(selectedOperation.autonomous === 0 ? 'manual' : 'autonomous')"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Parser</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.use_learning_parsers"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Auto Close</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.auto_close"></span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <label class="label">Jitter</label>
                                        </td>
                                        <td>
                                            <span x-text="selectedOperation.jitter"></span>
                                        </td>
                                    </tr>
                                </tbody>
                                
                            </table>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left"></div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>
                
                <template x-if="openModal === 'addLink'">
                    <div class="modal-card wide" x-init="getAbilities()">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Add New Potential Link</p>
                        </header>
                        <section class="modal-card-body" x-show="!selectedPotentialLink.ability_id">
                            <form>
                                <div class="field is-horizontal">
                                    <div class="field-label is-small">
                                        <label class="label">Agent</label>
                                    </div>
                                    <div class="field-body">
                                        <div class="field">
                                            <div class="control">
                                                <div class="select is-small is-fullwidth">
                                                    <select id="link-agent" x-model="selectedAgentIndex" x-on:change="getAgent(selectedAgent.paw); potentialLink.agent = selectedAgent">
                                                        <option default disabled value="">Choose an agent</option>
                                                        <template x-for="(agent, index) in selectedOperation.host_group" :key="agent.paw">
                                                            <option :value="index" x-bind:selected="index === 0" x-text="agent.display_name + '-' + agent.paw"></option>
                                                        </template>
                                                    </select>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="field is-horizontal">
                                    <div class="field-label is-small">
                                        <label class="label">Executor</label>
                                    </div>
                                    <div class="field-body">
                                        <div class="field">
                                            <div class="control">
                                                <div class="select is-small is-fullwidth">
                                                    <select id="link-exec" x-model="potentialLink.executor" x-on:change="filterAbilities(abilities)">
                                                        <option value="" disabled>Select an executor</option>
                                                        <template x-for="(exec, index) of selectedAgentExecutors" :key="exec.executor">
                                                            <option x-text="exec.display" :value="exec.executor"></option>
                                                        </template>
                                                    </select>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="p-3"></div>
                                <div class="field is-horizontal">
                                    <div class="field-label is-small">
                                        <label class="label"><span class="icon is-small"><em class="fas fa-search"></em></span></label>
                                    </div>
                                    <div class="field-body">
                                        <div class="field">
                                            <div class="control">
                                                <input class="input is-small" x-model="potentialLinkSearchQuery" placeholder="Search for a link..." x-on:keyup="filterAbilities(abilities)">
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="field is-horizontal">
                                    <div class="field-label is-small">
                                        <label class="label">Tactic</label>
                                    </div>
                                    <div class="field-body">
                                        <div class="field">
                                            <div class="control">
                                                <div class="select is-small is-fullwidth">
                                                    <select id="link-tactic" x-model="potentialLink.tactic" x-on:change="filterAbilities(abilities)">
                                                        <option default value="">All tactics</option>
                                                        <template x-for="tactic in tacticFiltersList" :key="tactic">
                                                            <option x-text="tactic"></option>
                                                        </template>
                                                    </select>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="field is-horizontal">
                                    <div class="field-label is-small">
                                        <label class="label">Technique</label>
                                    </div>
                                    <div class="field-body">
                                        <div class="field">
                                            <div class="control">
                                                <div class="select is-small is-fullwidth">
                                                    <select id="link-technique" x-model="potentialLink.technique" x-on:change="filterAbilities(abilities)">
                                                        <option default value="">All techniques</option>
                                                        <template x-for="technique in techniqueFiltersList" :key="technique">
                                                            <option x-text="technique"></option>
                                                        </template>
                                                    </select>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </form>
                            <hr>
                            <div class="is-flex is-justify-content-space-between mb-2">
                                <strong x-show="filteredAbilitiesList.length">Select a potential link</strong>
                                <p x-text="`${filteredAbilitiesList.length} potential link${((filteredAbilitiesList.length === 1) ? '' : 's')}`"></p>
                            </div>
                            <template x-for="ability in filteredAbilitiesList" :key="ability.ability_id">
                                <div class="box mb-2 mr-2 p-3 op-ability" @click="selectPotentialLink(ability)">
                                    <p style="width: 90%">
                                        <span class="has-text-weight-bold" x-text="ability.name"></span>
                                        <span x-text="`(${ability.technique_id})`"></span>
                                    </p>
                                    <p class="help mb-0" x-text="ability.description" style="width: 90%; white-space: pre-line;"></p>
                                    <span class="icon is-large ability-icon"><em class="fas fa-lg fa-arrow-right"></em></span>
                                </div>
                            </template>
                            <em x-show="showNotRepeatableText" class="has-text-grey-light is-pulled-right is-size-7">Note: Repeated links are not available for this operation</em>
                        </section>
                        <section class="modal-card-body " x-show="selectedPotentialLink.ability_id">
                            <strong x-text="selectedPotentialLink.name" class="mb-2 is-size-4"></strong>
                            <span x-text="`(${selectedPotentialLink.technique_id})`"></span>
                            <p x-text="selectedPotentialLink.description" style="white-space: pre-line;"></p>
                            <hr>
                            <p class="has-text-centered has-text-weight-bold">Fact Templates</p>
                            <p class="help" x-show="Object.keys(selectedPotentialLinkFacts).length">
                                This link needs facts in order to run properly. Select one value for each fact to add one potential link, otherwise, select multiple
                                values and a potential link will be added for each possible combination.
                            </p>
                            <p class="help" x-show="!Object.keys(selectedPotentialLinkFacts).length">
                                This link has no fact templates.
                            </p>
                            <template x-for="factName in Object.keys(selectedPotentialLinkFacts)" :key="factName">
                                <div class="block">
                                    <span class="icon-text">
                                        <label class="label" x-text="factName"></label>
                                        <span class="icon has-text-warning"
                                              x-show="selectedPotentialLinkFacts[factName] ? selectedPotentialLinkFacts[factName].every((fact) => !fact.selected) : false"
                                              data-tooltip="There are currently empty fact templates. You can still add this link but it may not run properly.">
                                            <em class="fas fa-exclamation-triangle"></em>
                                        </span>
                                    </span>
                                    <template x-for="fact in selectedPotentialLinkFacts[factName] || null" :key="fact.value">
                                        <div>
                                            <label class="checkbox">
                                                <input type="checkbox" x-model="fact.selected" x-on:change="setPotentialLinksToAdd()">
                                                <span x-text="fact.value"></span>
                                                <span class="tag" x-text="fact.origin" data-tooltip="The origin of this fact"></span>
                                            </label>
                                        </div>
                                    </template>
                                </div>
                            </template>

                            <p class="has-text-centered has-text-weight-bold">Link Command</p>
                            <p class="help">
                                You can edit the link's command here. Editing the fact templates (<code>#{...}</code>) may result in unexpected behavior.
                            </p>
                            <textarea class="textarea is-family-monospace" x-model="potentialLinkCommand" x-on:change="setPotentialLinksToAdd()"></textarea>
                        </section>
                        <footer class="modal-card-foot" x-show="!selectedPotentialLink.ability_id">
                            <nav class="level">
                                <div class="level-left">
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null; selectPotentialLink({})">Close</button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                        <footer class="modal-card-foot" x-show="selectedPotentialLink.ability_id">
                            <nav class="level">
                                <div class="level-left">
                                    <button class="button is-small" @click="selectPotentialLink({})">
                                        <span class="icon"><em class="fas fa-arrow-left"></em></span>
                                        <span>Back</span>
                                    </button>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null; selectPotentialLink({})">Close</button>
                                    </div>
                                    <button class="button is-small" x-bind:class="{ 'is-primary': !isAddingBlankPotentialLink || !Object.keys(selectedPotentialLinkFacts).length, 'is-warning': isAddingBlankPotentialLink && Object.keys(selectedPotentialLinkFacts).length }" @click="addPotentialLinks()">
                                        <span class="icon">
                                            <em class="fas fa-plus" x-show="!isAddingBlankPotentialLink || !Object.keys(selectedPotentialLinkFacts).length"></em>
                                            <em class="fas fa-exclamation-triangle" x-show="isAddingBlankPotentialLink && Object.keys(selectedPotentialLinkFacts).length"></em>
                                        </span>
                                        <span>
                                            Add
                                            <span x-text="potentialLinksToAdd.length"></span>
                                            Potential Link<span x-show="potentialLinksToAdd.length > 1">s</span>
                                        </span>
                                    </button>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'showDownloadMenu'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Download Reports</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <label for="agent-output-field">Agent output</label>
                                    <div class="modal-form-fields" id="agent-output-field">
                                        <input id="agent-output"
                                               x-bind:disabled="selectedReportType === 'csv'"
                                               type="checkbox"
                                               class="mr-1"
                                               x-model="isAgentOutputSelected">
                                        <label for="agent-output">include agent output</label>
                                    </div>
                                </div>
                                <div>
                                    <label for="report-type">Report type</label>
                                    <div class="modal-form-fields download-buttons-container" id="report-type">
                                        <input class="mr-1" type="radio" x-model="selectedReportType"
                                               value="full-report" id="full-report">
                                        <label for="full-report">Full Report</label>
                                        <input class="mr-1" type="radio" x-model="selectedReportType"
                                               value="event-logs" id="event-logs">
                                        <label for="event-logs">Event Logs</label>
                                        <input class="mr-1" type="radio" x-model="selectedReportType"
                                               value="csv" id="csv">
                                        <label for="csv">CSV</label>
                                    </div>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button class="button is-small" @click="openModal = null">Close</button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="handleDownload()">
                                            Download
                                        </button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'deleteOperationModal' && selectedOperation">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Delete operation?</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <p>Are you sure you want to delete the operation <em
                                            x-text="selectedOperation.name"></em>?</p>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button type="button" class="button ml-2 is-small"
                                                x-on:click="openModal = null">
                                            Cancel
                                        </button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="deleteOperation(); openModal = null;">
                                            Delete
                                        </button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>

                <template x-if="openModal === 'deleteLinkModal'">
                    <div class="modal-card">
                        <header class="modal-card-head">
                            <p class="modal-card-title">Delete link?</p>
                        </header>
                        <section class="modal-card-body">
                            <div class="modal-form">
                                <div>
                                    <p>Are you sure you want to delete the link <em
                                            x-text="selectedLink.ability.name"></em>?</p>
                                </div>
                            </div>
                        </section>
                        <footer class="modal-card-foot">
                            <nav class="level">
                                <div class="level-left">
                                    <div class="level-item">
                                        <button type="button" class="button ml-2 is-small"
                                                x-on:click="openModal = null">
                                            Cancel
                                        </button>
                                    </div>
                                </div>
                                <div class="level-right">
                                    <div class="level-item">
                                        <button type="button" class="button is-primary is-small"
                                                x-on:click="updateLink(-2); openModal = null;">
                                            Delete
                                        </button>
                                    </div>
                                </div>
                            </nav>
                        </footer>
                    </div>
                </template>
            </div>
        </template>
    </div>
</div>

<script>
    function alpineOperations() {
        return {
            // CONSTANTS
            ENDPOINT: '/api/v2/operations',
            EXECUTOR_SHELLS: {
                psh: 'PS',
                sh: '$',
                zsh: '$'
            },
            LINK_STATUSES: {
                0: 'success',
                '-1': 'paused',
                1: 'failed',
                '-2': 'discarded',
                '-3': 'collect',
                '-4': 'untrusted',
                '-5': 'visible',
                124: 'timeout'
            },
            OBFUSCATORS: [],
            PLANNERS: [],
            ADVERSARIES: [],
            SOURCES: [],

            docs: '{{ usage | tojson }}'.toString().replace(/["\[\]]/g, '').split('}'),
            usage: {},
            agentGroups: [],
            selectedOperationID: '',
            selectedOperation: null,
            selectedAgentIndex: 0,
            isSelectedAdversaryRepeatable: false,
            selectedLink: null,
            selectedLinkResults: null,
            selectedLinkFacts: null,
            selectedLinkPlaintextCommand: null,
            selectedLinkCommand: null,
            linkScrollHistory: {operationID: -1, shouldScroll: true, isEnabled: true},
            selectedReportType: 'full-report',
            isAgentOutputSelected: false,
            openModal: null,
            openModalForm: {
                advanced: false
            },

            facts: [],
            jitterMin: 2,
            jitterMax: 8,

            operations: [],
            operationToStart: {},

            selectedPotentialLink: {},
            selectedPotentialLinkFacts: {},
            potentialLinksToAdd: [],
            potentialLinkSearchQuery: '',
            isAddingBlankPotentialLink: false,
            potentialLinkCommand: '',
            potentialLink: {
                agent: '',
                executor: '',
                tactic: '',
                technique: '',
            },

            tacticFiltersList: [],
            techniqueFiltersList: [],
            abilities: [],
            filteredAbilitiesList: [],
            schedule: '',
            editableCommand: null,
            addNewRow: false,
            addedTechniquesIDs: new Set(),

            get EMPTY_MANUAL_COMMAND_OBJECT() {
                return {
                    paw: '',
                    executor: {
                        name: '',
                        platform: '',
                        command: '',
                    }
                };
            },

            getUsage() {
                if (this.docs) {
                    this.docs.forEach((obj) => {
                        if (obj) {
                            let items = obj.split('{')[1].split(': ');
                            this.usage[items[0]] = items[1];
                        }
                    });
                }
            },

            get showNotRepeatableText() {
                return !this.selectedOperation?.adversary?.has_repeatable_abilities;
            },

            get selectedAgent() {
                if (!this.selectedOperation || this.selectedAgentIndex >= this.selectedOperation.host_group.length) return null;
                return this.selectedOperation.host_group[this.selectedAgentIndex];
            },

            get selectedAgentExecutors() {
                if (!this.selectedAgent) return [];
                return this.selectedAgent.executors.map((e) => {
                    let cmd = `(${e})`;
                    if (e in this.EXECUTOR_SHELLS) cmd += ` ${this.EXECUTOR_SHELLS[e]}`;
                    return {
                        executor: e,
                        display: `${cmd} > `
                    };
                });
            },

            get isOperationRunning() {
                if (!this.selectedOperation) return false;
                return !(this.selectedOperation.state === 'finished' || this.selectedOperation.state === 'cleanup' || this.selectedOperation.state === 'out_of_time');
            },

            init() {
                this.selectedOperation = { chain: [], host_group: [] };
                this.agentGroups = [];
                this.selectedOperationID = '';
                this.selectedAgentIndex = 0;
                this.isSelectedAdversaryRepeatable = false;
                this.selectedLink = null;
                this.selectedLinkResults = null;
                this.selectedLinkFacts = null;
                this.selectedLinkCommand = null;
                this.selectedReportType = 'full-report';
                this.isAgentOutputSelected = false;
                this.openModal = null;
                this.openModalForm = { advanced: false };
                this.operations = [];
                this.operationToStart = { planner: '', source: ''};
            },

            isLinkEditable(currentLink) {
                if (!currentLink) return false;
                // Link can only be editable if operation is running, and if link is paused, queued, or completed
                return this.isOperationRunning && ((currentLink.status === -1 || !(currentLink.status in this.LINK_STATUSES))
                    && !(currentLink.finish !== null || currentLink.output === 'True'));
            },

            getReadableTime(date) {
                // i.e. format 2021-08-03 19:37:08
                if (!date) return '';
                date = date.replace('T', ' ').replace('Z', '');
                let split = date.split('-');

                let hMonth = Number(split[1]) - 1;
                let hDate = Number(split[2].split(' ')[0]);
                let hTime = split[2].split(' ')[1].split(':');

                return new Date(Date.UTC(split[0], hMonth, hDate, hTime[0], hTime[1], hTime[2])).toLocaleString('en-US', { timeZoneName: 'short' });
            },

            getLastDecideTime() {
                if (!this.selectedOperation || !this.selectedOperation.chain || this.selectedOperation.chain.length === 0) return '';
                return getHumanFriendlyTimeISO8601(this.selectedOperation.chain[this.selectedOperation.chain.length - 1].decide);
            },

            // Controls whether user can add link or not--depending on whether adversary allows repeatable abilities, and ability has been added already or not
            isLinkAvailable(ability) {
                return this.selectedOperation.adversary.has_repeatable_abilities ? true : !this.addedTechniquesIDs.has(ability.technique_id);
            },

            generateAddedLinksList() {
                this.addedTechniquesIDs = new Set();
                this.selectedOperation.chain.forEach((link) => {
                    if (!this.addedTechniquesIDs.has(link.ability.technique_id)) this.addedTechniquesIDs.add(link.ability.technique_id);
                });
            },

            scrollToLastLink(linkRow, index){
              // Check if link is the last link and that we haven't just switched operations
              if (index === this.selectedOperation.chain.length - 1 && this.linkScrollHistory.shouldScroll && this.linkScrollHistory.isEnabled){
                linkRow.scrollIntoView();
              }
            },

            //
            // API CALLS
            //

            async initOperations() {
                this.getOperations();
                this.getFields();
                this.getUsage();
                this.getFacts();

                while (this.$refs.operationsHeader) {
                    await sleep(3000);
                    this.getOperation();
                    this.getFacts();
                    this.getFields();
                }
            },

            getFields() {
                Promise.all([apiV2('GET', '/api/v2/obfuscators'), apiV2('GET', '/api/v2/planners'), apiV2('GET', '/api/v2/adversaries'), apiV2('GET', '/api/v2/sources')]).then(([o, p, a, s]) => {
                    this.OBFUSCATORS = o;
                    this.PLANNERS = p;
                    this.ADVERSARIES = a.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase());
                    this.SOURCES = s;
                }).catch((error) => {
                    console.error(error);
                });
            },

            openOperationCreateModal() {
                this.resetOperationToStart();
                this.openModal = 'addOperation';
                this.getAgents();
            },

            resetOperationToStart() {
                let defaultSourceId = 'ed32b9c3-9593-4c33-b0db-e2007315096b'  // basic fact source
                if (!this.SOURCES.find((s) => s.id === defaultSourceId) && this.SOURCES[0]) {
                    defaultSourceId = this.SOURCES[0].id
                }

                this.operationToStart = {
                    name: '',
                    group: '',
                    adversary: { adversary_id: '' },
                    auto_close: 0,
                    state: 'running',
                    autonomous: 1,
                    planner: { id: this.PLANNERS[0] ? this.PLANNERS[0].id : 'aaa7c857-37a0-4c4a-85f7-4e9f7f30e31a' },
                    source: { id: defaultSourceId },
                    use_learning_parsers: 1,
                    obfuscator: 'plain-text',
                    jitter: '2/8',
                    visibility: '51',
                };
            },

            getOperations() {
                apiV2('GET', this.ENDPOINT).then((res) => {
                    this.operations = res;
                }).catch(() => {
                    toast('Error getting operations');
                });
            },

            getFacts() {
                if (!this.selectedOperationID) return;
                apiV2('GET', `/api/v2/facts/${this.selectedOperationID}`).then((facts) => {
                    this.facts = facts.found;
                }).catch(() => {
                    toast('Error getting facts');
                });
            },

            getOperation() {
                if (!this.selectedOperationID) return;

                apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}`).then((res) => {
                    this.selectedOperation = res;
                    if (this.linkScrollHistory.operationID != this.selectedOperationID){
                      this.linkScrollHistory.shouldScroll = false;
                    }else{
                      this.linkScrollHistory.shouldScroll = true;
                    }
                    this.linkScrollHistory.operationID = this.selectedOperationID;
                    this.generateAddedLinksList();
                }).catch(() => {
                    toast('Error getting operation');
                });
            },

            addOperation() {
                if (!this.operationToStart.name) {
                    toast('Error: Operation name field is empty.', false);
                } else if (!this.isJitterValid()) {
                    toast('Jitter values are invalid', false);
                } else {
                    this.operationToStart.name = sanitize(this.operationToStart.name);
                    this.operationToStart.autonomous = Number(this.operationToStart.autonomous);
                    this.operationToStart.use_learning_parsers = parseInt(this.operationToStart.use_learning_parsers, 10) === 1;
                    this.operationToStart.auto_close = parseInt(this.operationToStart.auto_close, 10) === 1;
                    this.operationToStart.jitter = `${parseInt(this.jitterMin, 10)}/${parseInt(this.jitterMax, 10)}`;
                    apiV2('POST', this.ENDPOINT, this.operationToStart).then((newOperation) => {
                        toast(`Started operation ${this.operationToStart.name}!`, true);
                        this.operations.push(newOperation);
                        this.selectedOperation = newOperation;
                        this.selectedOperationID = newOperation.id;
                        this.openModal = null;
                    }).catch(() => {
                        toast('Error adding operation');
                    });
                }
            },

            rerunOperation() {
                let { id, start, state, chain, host_group, ...newOp } = this.selectedOperation;

                let dateMatches = newOp.name.match(/[(]\d{1,2}\/\d{1,2}\/\d{2,4}, \d{1,2}:\d{2}:\d{2} [A|P]M[)]$/g);
                let stringToReplace = (dateMatches && dateMatches.length) ? dateMatches[dateMatches.length - 1] : '';
                let date = `(${new Date().toLocaleString()})`;
                newOp.name = stringToReplace ? (newOp.name.replace(stringToReplace, date)) : (`${newOp.name} ${date}`);
                newOp.name = sanitize(newOp.name);

                apiV2('POST', this.ENDPOINT, newOp).then((newOperation) => {
                    toast(`Started operation ${newOperation.name}!`, true);
                    this.operations.push(newOperation);
                    this.selectedOperation = newOperation;
                    this.selectedOperationID = newOperation.id;
                }).catch((error) => {
                    toast('Error adding operation', false);
                    console.error(error);
                });
            },

            deleteOperation() {
                apiV2('DELETE', `${this.ENDPOINT}/${this.selectedOperationID}`)
                    .then(() => {
                        this.init();
                        this.getOperations();
                        toast('Deleted operation.', true);
                    })
                    .catch(() => {
                        toast('Error deleting operation.');
                    });
            },

            getAgent(agentPaw) {
                apiV2('GET', `api/v2/agents/${agentPaw}`)
                    .then((res) => {
                        // Check if agent has been seen in the last hour
                        if ((new Date() - new Date(res.last_seen)) > 3600000) {
                            toast(`Command might not run. Is Agent #${res.paw} still alive?`);
                        } else {
                            this.potentialLink.agent = res;
                        }
                    })
                    .catch(() => {
                        toast('Error getting agent.');
                    });
            },

            getAgents() {
                apiV2('GET', 'api/v2/agents')
                    .then((res) => {
                        this.updateAgentGroups(res);
                        this.selectedAgentIndex = 0;
                    })
                    .catch(() => {
                        toast('Error getting agents.');
                    });
            },

            getAbilities() {
                apiV2('GET', '/api/v2/abilities').then((abilities) => {
                    this.abilities = abilities;
                    if (!this.potentialLink.agent && this.selectedOperation.host_group && this.selectedOperation.host_group.length > 0) {
                        this.potentialLink.agent = this.selectedOperation.host_group[0];
                        this.potentialLink.executor = this.potentialLink.agent.executors[0];
                    }
                    this.getAgent(this.potentialLink.agent.paw);
                    this.filterAbilities(abilities);
                    this.tacticFiltersList = sortAlphabetically([...new Set(abilities.flatMap((a) => a.tactic))]);
                    this.techniqueFiltersList = sortAlphabetically([...new Set(abilities.flatMap((a) => `${a.technique_id} | ${a.technique_name}`))]);
                }).catch(() => {
                    toast('Error getting abilities', false);
                });
            },

            addManualCommand(manualCommand) {
                if (!manualCommand.executor.command) {
                    toast('Enter manual command.');
                    return;
                }
                manualCommand.paw = this.selectedAgent.paw;
                manualCommand.executor.name = document.getElementById('manual-executors').selectedOptions[0].value;
                manualCommand.executor.platform = this.selectedAgent.platform;

                if (this.selectedOperation.state === 'paused') {
                    toast('Operation is currently paused, and new links might not be added.', true);
                    this.addNewRow = false;
                }
                apiV2('POST', `${this.ENDPOINT}/${this.selectedOperationID}/potential-links`, manualCommand)
                    .then((res) => {
                        toast('Added manual command.', true);
                        this.getOperation();

                        // Reset
                        this.addNewRow = false;
                        this.selectedAgentIndex = null;
                    })
                    .catch(() => toast('Error adding manual command.'));
            },

            openPotentialLinkModal() {
                this.potentialLink.tactic = '';
                this.potentialLink.technique = '';
                this.potentialLinkSearchQuery = '';
                this.filterAbilities(this.abilities);
                this.getAgents();
                this.openModal = 'addLink';
            },

            selectPotentialLink(link) {
                this.selectedPotentialLink = link;
                this.selectedPotentialLinkFacts = {};
                this.setPotentialLinksToAdd();
                if (!this.selectedPotentialLink.ability_id) return;

                const executor = link.executors.find((ex) => ex.platform === this.potentialLink.agent.platform && this.potentialLink.executor === ex.name);
                const fields = [...new Set([...executor.command.matchAll(/#{(.*?)}/gm)].map((field) => field[1]))];
                const opSource = this.SOURCES.find((s) => s.id === this.selectedOperation.source.id);
                const opSourceCollected = this.SOURCES.find((source) => source.name === this.selectedOperation.name);
                const facts = (opSource.facts.concat(opSourceCollected ? opSourceCollected.facts : [])).concat(this.facts);
                this.potentialLinkCommand = executor.command;

                fields.filter((field) => facts.find((fact) => fact.name === field)).forEach((field) => {
                    this.selectedPotentialLinkFacts[field] = []
                    facts.filter((fact) => fact.name === field).forEach((fact) => {
                        this.selectedPotentialLinkFacts[field].push({
                            value: fact.value,
                            origin: fact.origin_type,
                            selected: false
                        });
                    });
                });

                this.setPotentialLinksToAdd();
            },

            setPotentialLinksToAdd() {
                this.potentialLinksToAdd = [];

                function cartesian(args) {
                    if (!args.length) return [];
                    let r = [], max = args.length - 1;
                    function helper(arr, i) {
                        for (let j = 0; j < args[i].length; j++) {
                            let a = arr.slice(0);
                            a.push(args[i][j]);
                            (i === max) ? r.push(a) : helper(a, i + 1);
                        }
                    }
                    helper([], 0);
                    return r;
                }

                let combinations = [];
                Object.keys(this.selectedPotentialLinkFacts).forEach((factName) => {
                    combinations.push(this.selectedPotentialLinkFacts[factName].filter((fact) => fact.selected).map((fact) => `${factName}|${fact.value}`));
                });
                combinations = cartesian(combinations);

                let executor;
                if (this.selectedPotentialLink.executors) {
                    executor = this.selectedPotentialLink.executors.find((ex) => ex.platform === this.potentialLink.agent.platform && this.potentialLink.executor === ex.name);
                }

                if (!combinations.length) {
                    this.potentialLinksToAdd.push({
                        ability: this.selectedPotentialLink,
                        paw: this.potentialLink.agent.paw,
                        executor: {
                            ...executor,
                            command: this.potentialLinkCommand
                        }
                    })
                    this.isAddingBlankPotentialLink = true;
                    return;
                }

                combinations.forEach((factGroup) => {
                    let command = this.potentialLinkCommand;
                    factGroup.forEach((fact) => {
                        let split = fact.split('|');
                        command = command.replaceAll(`#{${split[0]}}`, split[1])
                    });

                    this.potentialLinksToAdd.push({
                        ability: this.selectedPotentialLink,
                        paw: this.potentialLink.agent.paw,
                        executor: {
                            ...executor,
                            command: command
                        }
                    });
                });
                this.isAddingBlankPotentialLink = false;
            },

            async addPotentialLinks() {
                if (this.selectedOperation.state === 'paused') {
                    toast('Operation is currently paused, and new links might not be added.', true);
                }

                try {
                    for (let link of this.potentialLinksToAdd) {
                        await apiV2('POST', `${this.ENDPOINT}/${this.selectedOperationID}/potential-links`, link);
                    }
                    toast(`Added ${this.potentialLinksToAdd.length} links.`, true);
                    this.getOperation();
                    this.addedTechniquesIDs.add(this.potentialLinksToAdd.map((link) => link.ability.technique_id));
                    this.openModal = false;
                    this.selectPotentialLink({});
                } catch (error) {
                    toast('Error adding potential link.');
                    console.error(error);
                }
            },

            getLink(link) {
                apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}/links/${link.id}`)
                    .then((res) => {
                        this.getLinkResults(res.output, link);
                        if (res.facts) {
                            this.selectedLinkFacts = Array.from(new Set(res.facts)).sort((a, b) => b.score - a.score);
                        }
                        this.selectedLinkCommand = res.command;
                        this.selectedLinkPlaintextCommand = res.plaintext_command;
                        this.editableCommand = res.command;
                    })
                    .catch(() => {
                        this.selectedLinkResults = null;
                        this.selectedLinkFacts = null;
                        this.selectedLinkCommand = null;
                        this.selectedLinkPlaintextCommand = null;
                        toast('Error getting link results.');
                    });
            },

            getLinkResults(output, link) {
                if (output !== 'True') {
                    this.selectedLinkResults = null;
                } else {
                    apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}/links/${link.id}/result`).then((res) => {
                        this.selectedLinkResults = JSON.parse(b64DecodeUnicode(res.result));
                    }).catch(() => console.error('Error getting link results.'));
                }
            },

            updateLink(status, command = null) {
                const updateLink = {
                    ...this.selectedLink,
                    command: this.selectedLink.command
                };
                if (command) {
                    updateLink.command = command;
                }
                updateLink.status = status;
                apiV2('PATCH', `${this.ENDPOINT}/${this.selectedOperationID}/links/${this.selectedLink.id}`, updateLink)
                    .then((res) => {
                        this.getOperation();
                        toast(`Updating link status to: ${this.LINK_STATUSES[status]}`, true);
                    })
                    .catch(() => toast('Error updating link state.'));
            },

            handleSelectAdversary(adversaryId) {
                let adversaryMatch = this.ADVERSARIES.find((a) => a.adversary_id === this.operationToStart.adversary.adversary_id);
                let lastAdversaryHadRepeatableAbilities = this.isSelectedAdversaryRepeatable;

                this.isSelectedAdversaryRepeatable = adversaryMatch.has_repeatable_abilities;
                if (this.isSelectedAdversaryRepeatable) {
                    let plannerMatch = this.PLANNERS.find((p) => p.id === this.operationToStart.planner.id);
                    if (plannerMatch && !plannerMatch.allow_repeatable_abilities) {
                        this.operationToStart.planner.id = this.PLANNERS.find((p) => p.allow_repeatable_abilities).id;
                    }
                } else if (!this.isSelectedAdversaryRepeatable && lastAdversaryHadRepeatableAbilities) {
                    this.operationToStart.planner.id = this.PLANNERS[0].id;
                }
            },

            updateOperation(field, updateValue) {
                this.selectedOperation[field] = updateValue;
                apiV2('PATCH', `${this.ENDPOINT}/${this.selectedOperationID}`, this.selectedOperation)
                    .then((res) => {
                        this.selectedOperation = res;
                        this.selectedLink = null;
                    })
                    .catch(() => {
                        toast(`Error updating operation ${field}. Operation may have already finished running.`);
                    });
            },

            updateOperationState() {
                if (this.selectedOperationID) {
                    apiV2('GET', `${this.ENDPOINT}/${this.selectedOperationID}`).then((res) => {
                        this.selectedOperation.state = res.state;
                        // toast('Go to the GameBoard plugin to see if the blue team can detect your activities.', true);
                    }).catch(() => {
                        toast('Error getting operation state');
                    });
                }
            },

            downloadInfo(formatType) {
                const endpoint = formatType === 'full-report' ? 'report' : formatType;
                apiV2('POST', `${this.ENDPOINT}/${this.selectedOperationID}/${endpoint}`, { enable_agent_output: this.isAgentOutputSelected })
                    .then((res) => {
                        this.createDownloadReport(res, `${this.selectedOperation.name}_${formatType}`);
                    })
                    .catch(() => toast(`Error generating operation ${formatType.replace('-', ' ')}`));
            },

            downloadCSV() {
                let csv = [ 'Decide,Link/Ability Name,Agent #paw,Host,pid,Command,Plaintext Command' ];

                this.selectedOperation.chain.forEach(async (link) => {
                    const rowItems = [];
                    rowItems.push(link.decide);
                    rowItems.push(link.ability.name);
                    rowItems.push(link.paw);
                    rowItems.push(link.host);
                    rowItems.push(link.pid);
                    rowItems.push(link.command);
                    rowItems.push(link.plaintext_command);
                    csv.push(rowItems.join(','));
                });
                this.createDownloadReport(new Blob([csv.join('\n')], { type: 'text/csv' }), this.selectedOperation.name, true);
            },

            handleDownload() {
                if (this.selectedReportType === 'full-report') {
                    this.downloadInfo('full-report');
                } else if (this.selectedReportType === 'event-logs') {
                    this.downloadInfo('event-logs');
                } else if (this.selectedReportType === 'csv') this.downloadCSV();
            },

            //
            // OBJECT MANIPULATION
            //

            createDownloadReport(data, fileName, isCSV = false) {
                let dataURL;

                if (!isCSV) {
                    dataURL = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(data, null, 2))}`;
                    fileName += '.json';
                } else {
                    dataURL = window.URL.createObjectURL(data);
                    fileName += '.csv';
                }

                const elem = document.createElement('a');
                elem.setAttribute('href', dataURL);
                elem.setAttribute('download', fileName);
                elem.click();
            },

            updateAgentGroups(agents) {
                if (!agents) return;
                this.agentGroups = [...new Set(agents.map((agent) => agent.group))];
            },

            isJitterValid() {
                const jitterMin = parseInt(this.jitterMin, 10);
                const jitterMax = parseInt(this.jitterMax, 10);
                return (jitterMin >= 0 && jitterMax >= 0 && jitterMin <= jitterMax);
            },

            filterAbilities(abilities) {
                this.filteredAbilitiesList = abilities.filter((ability) => {
                    let matchAgent = true,
                        matchTactic = true,
                        matchTechnique = true;
                    if (this.potentialLink.executor) matchAgent = ability.executors.some((ex) => ex.platform === this.potentialLink.agent.platform && this.potentialLink.executor === ex.name);
                    if (this.potentialLink.tactic) matchTactic = this.potentialLink.tactic === ability.tactic;
                    if (this.potentialLink.technique) matchTechnique = this.potentialLink.technique === `${ability.technique_id} | ${ability.technique_name}`;
                    matchQuery = ability.name.toLowerCase().includes(this.potentialLinkSearchQuery.toLowerCase()) || ability.description.toLowerCase().includes(this.potentialLinkSearchQuery.toLowerCase());
                    return matchAgent && matchTactic && matchTechnique && matchQuery;
                });
            },
        };
    }
</script>

<style>
    #operationsPage #select-operation {
        max-width: 800px;
        margin: 0 auto;
    }

    #operationsPage .control-buttons > .button {
        margin: 0 10px 10px 0;
    }

    #operationsPage .modal-card {
        max-height: 90vh;
    }

    #operationsPage .toggleContainer label {
        font-size: 1em !important;
    }

    #operationsPage .box.op-ability {
        position: relative;
        cursor: pointer;
        border: 1px solid transparent;
        background-color: #272727;
    }
    #operationsPage .box.op-ability:hover {
        border: 1px solid #474747;
    }
    #operationsPage .ability-icon {
        position: absolute;
        right: 0;
        top: 20%;
    }

    /*MODAL FORM STYLE*/
    #operationsPage .modal-form-fields.download-buttons-container button {
        width: fit-content;
    }

    /*END MODAL FORM STYLE*/
    #operationsPage .timeline-table .modal-card code, table code, .modal-form code {
        color: #ff8181;
        background-color: initial;
        white-space: pre-line;
    }

    #operationsPage .timeline-table {
        padding-bottom: 5em;
    }

    #operationsPage .timeline-table table tr th {
        font-weight: 400;
        font-size: 0.75rem;
        border-bottom: none;
        color: gray;
    }

    #operationsPage .tag {
        border-bottom: none;
    }

    #operationsPage .button:active, .button.is-active, .button:focus, .button.is-focused {
        color: inherit;
    }

    #operationsPage button.is-larger {
        font-size: 2.1rem;
    }

    #operationsPage button.no-style {
        background-color: transparent;
        border: none;
        box-shadow: none;
    }

    #operationsPage button.no-style.reset {
        padding: 0.5em;
        width: fit-content;
        font-size: .75em;
    }

    #operationsPage button.no-style[disabled] {
        background-color: initial !important;
    }

    #operationsPage button.no-style:hover {
        border: none;
        color: white;
        transform: scale(1.2);
    }

    #operationsPage em sub {
        font-family: sans-serif;
    }

    #operationsPage .controls-container button {
        margin: 0 2rem;
        padding: 0;
        max-height: 34px;
    }

    #operationsPage .timeline-table th:not(.decideColumn), th:not(.statusColumn) {
        text-align: left;
    }

    #operationsPage .timeline-table .decideColumn {
        color: gray;
        width: 120px;
        word-break: break-word;
        font-size: 0.75rem;
        text-align: center !important;
    }

    #operationsPage .timeline-table .infoColumn {
        width: 200px;
    }

    #operationsPage .timeline-table table tbody td {
        vertical-align: middle;
        border: none;
        height: 5.5em;
    }

    #operationsPage .timeline-table table tbody td.commandDetails textarea {
        color: #ff8181;
        background-color: #262626;
        height: 150px;
        max-width: 22ch;
        word-break: break-word;
        padding: 5px;
        border-radius: 5px;
    }

    #operationsPage .timeline-table table tbody td textarea[contenteditable] {
        width: 100%;
        height: 5em;
        margin-top: 1em;
    }

    #operationsPage .timeline-table table tbody td.commandDetails button {
        width: max-content;
    }

    #operationsPage .timeline-table table tfoot td {
        padding-top: 1em;
        border: none !important;
    }

    /* white time-line */
    #operationsPage span.linkStatus {
        justify-content: flex-start;
        display: flex;
    }

    #operationsPage span.linkStatus::before {
        width: 2px;
        height: 180px;
        background-color: white;
        content: "";
        display: inline-block;
        position: absolute;
        margin-left: 25px;
        margin-top: 40px;
    }

    /*circle for event*/
    #operationsPage span.linkStatus::after {
        position: relative;
        display: block;
        background: #161616;
        border-radius: 50%;
        height: 50px;
        width: 50px;
        content: attr(data-content);
        padding-top: 18px;
        text-align: center;
        font-size: 0.5em;
    }

    #operationsPage span.status {
        position: relative;
        top: 55px;
        z-index: 10;
        font-size: .5em;
        color: white;
        left: 15px;
        display: flex;
    }

    /*queued*/
    #operationsPage span.status-queued {
        color: #555;
    }

    #operationsPage span.status-queued::after {
        box-shadow: 0 0 0 0.2em #555;
    }

    /*success*/
    #operationsPage span.status-success {
        color: #4a9;
    }

    #operationsPage span.status-success::after {
        box-shadow: 0 0 0 0.2em #4a9;
    }

    /*failure*/
    #operationsPage span.status-failed {
        color: #c31;
    }

    #operationsPage span.status-failed::after {
        box-shadow: 0 0 0 0.2em #c31;
    }

    /*paused*/
    #operationsPage span.status-paused {
        color: #ffc500;
    }

    #operationsPage span.status-paused::after {
        box-shadow: 0 0 0 0.2em #ffc500;
    }

    /*removed*/
    #operationsPage span.status-discarded {
        color: #a05195;
    }

    #operationsPage span.status-discarded::after {
        box-shadow: 0 0 0 0.2em #a05195;
    }

    /*collected*/
    #operationsPage span.status-collect {
        color: #ffb000;
    }

    #operationsPage span.status-collect::after {
        box-shadow: 0 0 0 0.2em #ffb000;
    }

    /*untrusted*/
    #operationsPage span.status-untrusted {
        color: white;
    }

    #operationsPage span.status-untrusted::after {
        box-shadow: 0 0 0 0.2em white;
    }

    /*visible*/
    #operationsPage span.status-visible {
        color: #f012be;
    }

    #operationsPage span.status-visible::after {
        box-shadow: 0 0 0 0.2em #f012be;
    }

    /*timeout*/
    #operationsPage span.status-timeout {
        color: cornflowerblue;
    }

    #operationsPage span.status-timeout::after {
        box-shadow: 0 0 0 0.2em cornflowerblue;
    }
</style>