Преглед изворни кода

Merge pull request #26 from tripal/first-steps-merger

Make package more cohesive: Step 1
Lacey-Anne Sanderson пре 5 година
родитељ
комит
cee1732198

Разлика између датотеке није приказан због своје велике величине
+ 317 - 211
composer.lock


+ 110 - 3
tripal_jbrowse_mgmt/includes/tripal_jbrowse_mgmt.api.inc

@@ -398,12 +398,20 @@ function tripal_jbrowse_mgmt_copy_file($source, $destination) {
  */
 function tripal_jbrowse_mgmt_build_http_query($instance) {
   $path = tripal_jbrowse_mgmt_make_slug($instance->title);
-  $tracks = tripal_jbrowse_mgmt_get_tracks($instance);
+  $added_tracks = tripal_jbrowse_mgmt_get_tracks($instance);
+  $properties = tripal_jbrowse_mgmt_get_instance_properties($instance->id);
+
+  // Determine the tracks to display.
   $tracks_path = '';
-  if (!empty($tracks)) {
+  // If the start-tracks property is set then use that directly.
+  if (isset($properties['start-tracks'])) {
+    $tracks_path = $properties['start-tracks'];
+  }
+  // Otherwise, show all tracks that were added using this module.
+  elseif (!empty($added_tracks)) {
     $tracks_path = implode(',', array_map(function ($track) {
       return tripal_jbrowse_mgmt_make_slug($track->label);
-    }, $tracks));
+    }, $added_tracks));
   }
 
   $settings = tripal_jbrowse_mgmt_get_settings();
@@ -413,6 +421,13 @@ function tripal_jbrowse_mgmt_build_http_query($instance) {
     'data' => "$data_path/$path/data",
     'tracks' => $tracks_path,
   ];
+
+  // Now we need to add start location if it's set.
+  if (isset($properties['start-loc'])) {
+    $query_params['loc'] = $properties['start-loc'];
+  }
+
+  return $query_params;
 }
 
 /**
@@ -533,3 +548,95 @@ function tripal_jbrowse_mgmt_get_track_types() {
     'XYPlot',
   ];
 }
+
+/**
+ * Save properties for a given instance.
+ *
+ * @param $id
+ *   The instance ID that properties should be associated with.
+ * @param $data
+ *   An array of properties where each is
+ *   key: property_type, value: property value.
+ */
+function tripal_jbrowse_mgmt_save_instance_properties($id, $data) {
+
+  // For each property...
+  foreach ($data as $type => $value) {
+    tripal_jbrowse_mgmt_save_instance_property($id, $type, $value);
+  }
+
+}
+
+/**
+ * Save the details for a specific property of a given instance.
+ *
+ * @param $id
+ *   The instance ID that properties should be associated with.
+ * @param $type
+ *   The name of the property type to be saved.
+ * @param $value
+ *   The value of the property to be saved.
+ */
+function tripal_jbrowse_mgmt_save_instance_property($id, $type, $value) {
+
+  // Check to see if the property already exists.
+  $result = db_select('tripal_jbrowse_mgmt_instanceprop', 'p')
+    ->fields('p', ['value'])
+    ->condition('instance_id', $id)
+    ->condition('property_type', $type)
+    ->execute()->fetchObject();
+
+  // If the property doesn't already exist then insert it.
+  if (empty($result)) {
+    return db_insert('tripal_jbrowse_mgmt_instanceprop')
+      ->fields([
+        'instance_id' => $id,
+        'property_type' => $type,
+        'value' => $value,
+      ])->execute();
+  }
+  // Otherwise, we need to update it.
+  else {
+    return db_update('tripal_jbrowse_mgmt_instanceprop')
+      ->fields([
+        'value' => $value,
+      ])
+      ->condition('instance_id', $id)
+      ->condition('property_type', $type)
+      ->execute();
+  }
+}
+
+/**
+ * Retrieves the value for a given instance property.
+ *
+ * @param $id
+ *   The instance ID.
+ * @param $type
+ *   The name of the property type.
+ * @return
+ *   The value of the property for a given instance.
+ */
+function tripal_jbrowse_mgmt_get_instance_property($id, $type) {
+  return db_select('tripal_jbrowse_mgmt_instanceprop', 'p')
+    ->fields('p', ['value'])
+    ->condition('instance_id', $id)
+    ->condition('property_type', $type)
+    ->execute()->fetchField();
+}
+
+/**
+ * Retrieves all properties for a given instance.
+ *
+ * @param $id
+ *   The instance ID.
+ * @return
+ *   An array of properties for the specified instance
+ *   where the key: property type and value: property value.
+ */
+function tripal_jbrowse_mgmt_get_instance_properties($id) {
+  return db_select('tripal_jbrowse_mgmt_instanceprop', 'p')
+    ->fields('p', ['property_type', 'value'])
+    ->condition('instance_id', $id)
+    ->execute()->fetchAllKeyed(0,1);
+}

+ 194 - 61
tripal_jbrowse_mgmt/includes/tripal_jbrowse_mgmt_add.form.inc

@@ -3,13 +3,15 @@
 function tripal_jbrowse_mgmt_add_form($form, &$form_state) {
   $settings = tripal_jbrowse_mgmt_get_settings();
 
-  if (empty(array_values($settings))) {
+  // Ensure the module is configured.
+  if (empty(array_filter($settings))) {
     $form['incomplete'] = [
       '#type' => 'item',
-      '#prefix' => '<div style="color: red;">',
+      '#prefix' => '<div class="messages error">',
       '#markup' => t(
-        'You have not configured the module yet. Please visit the 
-                      settings page and submit the form before continuing.'
+        'You have not configured the module yet. Please visit the
+            <a href="@url">settings page</a> and submit the form before continuing.',
+        ['@url' => url('admin/tripal/extension/tripal_jbrowse/management/configure')]
       ),
       '#suffix' => '</div>',
     ];
@@ -17,6 +19,21 @@ function tripal_jbrowse_mgmt_add_form($form, &$form_state) {
     return $form;
   }
 
+  // Check to see if this is an edit form.
+  $edit_form = FALSE;
+  if (isset($form_state['build_info']['args'][0]) AND is_numeric($form_state['build_info']['args'][0])) {
+    $instance_id = $form_state['build_info']['args'][0];
+    $result = tripal_jbrowse_mgmt_get_instances(['id' => $instance_id]);
+    if (!empty($result)) {
+      $instance = $result[0];
+      $edit_form = TRUE;
+    }
+    else {
+      drupal_set_message('Unable to access the instance you would like to edit.', 'error');
+      return $form;
+    }
+  }
+
   $organisms = tripal_jbrowse_mgmt_get_organisms_list();
   $mapped_organisms = [];
   foreach ($organisms as $organism) {
@@ -25,12 +42,14 @@ function tripal_jbrowse_mgmt_add_form($form, &$form_state) {
     );
   }
 
+  $form_description = 'Create a new JBrowse instance for a given organism. Submitting this form
+  creates all the necessary files for a new JBrowse instance.';
+  if ($edit_form) {
+    $form_description = 'Edit details regarding the current JBrowse instance.';
+  }
   $form['description_of_form'] = [
     '#type' => 'item',
-    '#markup' => t(
-      'Create a new JBrowse instance for a given organism. Submitting this form 
-      creates all the necessary files for a new JBrowse instance.'
-    ),
+    '#markup' => t($form_description),
   ];
 
   $form['organism'] = [
@@ -39,12 +58,14 @@ function tripal_jbrowse_mgmt_add_form($form, &$form_state) {
     '#type' => 'select',
     '#options' => $mapped_organisms,
     '#required' => TRUE,
+    '#default_value' => ($edit_form) ? $instance->organism_id : NULL,
   ];
 
   $form['description'] = [
     '#title' => t('Description'),
     '#description' => t('Optional description for the instance.'),
     '#type' => 'textarea',
+    '#default_value' => ($edit_form) ? $instance->description : NULL,
   ];
 
   $form['data'] = [
@@ -64,6 +85,7 @@ function tripal_jbrowse_mgmt_add_form($form, &$form_state) {
   $form['data']['ref_seq_file'] = [
     '#type' => 'file',
     '#title' => t('Reference Sequence FASTA File'),
+    '#disabled' => ($edit_form) ? TRUE : FALSE,
   ];
 
   $form['data']['ref_seq_path'] = [
@@ -72,11 +94,70 @@ function tripal_jbrowse_mgmt_add_form($form, &$form_state) {
     '#description' => t(
       'This path will be ignored if a file is provided above. Ex: sites/default/files/file.fasta or /data/file.fasta'
     ),
+    '#disabled' => ($edit_form) ? TRUE : FALSE,
+  ];
+
+  $form['page'] = [
+    '#type' => 'fieldset',
+    '#tree' => TRUE,
+    '#title' => 'Instance Page Settings',
+    '#description' => 'The following settings pertain to link directing users to this instance (either embedded or the original).',
+  ];
+
+  $form['page']['start-loc'] = [
+    '#type' => 'textfield',
+    '#title' => 'Start Location',
+    '#description' => "<p>The initial genomic position which will be visible in
+      the viewing field. Possible input strings are:</p>\r\n
+    <strong>\"Chromosome\": \"start point\"..\"end point\"</strong>\r\n<p>A
+      chromosome name/ID followed by “:”, starting position, “..” and end
+      position of the genome to be viewed in the browser is used as an input.
+      Chromosome ID can be either a string or a mix of string and numbers.
+      “CHR” to indicate chromosome may or may not be used. Strings are not
+      case-sensitive. If the chromosome ID is found in the database reference
+      sequence (RefSeq), the chromosome will be shown from the starting
+      position to the end position given in URL.</p>\r\n
+      <pre>     ctgA:100..200</pre>\r\n
+      <p>Chromosome ctgA will be displayed from position 100 to 200.</p>\r\n
+    OR <strong>start point\"..\"end point</strong>\r\n<p>A string of
+      numerical value, “..” and another numerical value is given with the loc
+      option. JBrowse navigates through the currently selected chromosome from
+      the first numerical value, start point, to the second numerical value,
+      end point.</p>\r\n<pre>     200..600</pre>\r\n<p>Displays position 200
+      to 600 of the current chromosome.</p>\r\n
+    OR <strong>center base</strong>\r\n<p>If only one numerical value is given
+      as an input, JBrowse treats the input as the center position. Then an
+      arbitrary region of the currently selected gene is displayed in the
+      viewing field with the given input position as basepair position on
+      which to center the view.</p>\r\n
+    OR <strong>feature name/ID</strong>\r\n<p>If a string or a mix of string
+      and numbers are entered as an input, JBrowse treats the input as a
+      feature name/ID of a gene. If the ID exists in the database RefSeq,
+      JBrowser displays an arbitrary region of the feature from the the
+      position 0, starting position of the gene, to a certain end point.</p>\r\n
+      <pre>     ctgA</pre>\r\n<p>Displays an arbitrary region from the ctgA
+      reference.</p>",
+    '#default_value' => ($edit_form) ? tripal_jbrowse_mgmt_get_instance_property($instance_id, 'start-loc') : NULL,
+  ];
+
+  $form['page']['start-tracks'] = [
+    '#type' => 'textarea',
+    '#rows' => 2,
+    '#title' => 'Tracks to Display',
+    '#description' => "<p>A comma-delimited strings containing track names,
+      each of which should correspond to the \"label\" element of the track
+      information dictionaries that are currently viewed in the viewing field.</p>\r\n
+      <pre>     DNA,knownGene,ccdsGene,snp131,pgWatson,simpleRepeat</pre>",
+    '#default_value' => ($edit_form) ? tripal_jbrowse_mgmt_get_instance_property($instance_id, 'start-tracks') : NULL,
   ];
 
+  $button = 'Create New Instance';
+  if ($edit_form) {
+    $button = 'Save Changes';
+  }
   $form['submit'] = [
     '#type' => 'submit',
-    '#value' => 'Create New Instance',
+    '#value' => $button,
   ];
 
   return $form;
@@ -91,37 +172,49 @@ function tripal_jbrowse_mgmt_add_form($form, &$form_state) {
 function tripal_jbrowse_mgmt_add_form_validate($form, &$form_state) {
   $values = $form_state['values'];
   $organism = isset($values['organism']) ? $values['organism'] : NULL;
-  $file = $_FILES['files']['tmp_name']['ref_seq_file'];
-  $local_file = isset($values['ref_seq_path']) ? $values['ref_seq_path'] : NULL;
 
-  if (empty($file) && empty($local_file)) {
-    form_set_error(
-      'ref_seq_file',
-      'Please provide a local file path or upload a new file.'
-    );
+  // Check if this is an add or edit form.
+  $edit_form = FALSE;
+  if (isset($form_state['build_info']['args'][0]) AND is_numeric($form_state['build_info']['args'][0])) {
+    $instance_id = $form_state['build_info']['args'][0];
+    $edit_form = TRUE;
   }
-  elseif (empty($file) && !empty($local_file)) {
-    if (!file_exists($local_file)) {
-      form_set_error('ref_seq_path', 'The file path provided does not exist.');
+
+  if (!$edit_form) {
+    $file = $_FILES['files']['tmp_name']['ref_seq_file'];
+    $local_file = isset($values['ref_seq_path']) ? $values['ref_seq_path'] : NULL;
+
+    if (empty($file) && empty($local_file)) {
+      form_set_error(
+        'ref_seq_file',
+        'Please provide a local file path or upload a new file.'
+      );
     }
-  }
-  else {
-    $uploaded = tripal_jbrowse_mgmt_upload_file('ref_seq_file');
-    if (!$uploaded) {
-      form_set_error('ref_seq_file', 'Unable to upload file');
+    elseif (empty($file) && !empty($local_file)) {
+      if (!file_exists($local_file)) {
+        form_set_error('ref_seq_path', 'The file path provided does not exist.');
+      }
     }
     else {
-      $uploaded = tripal_jbrowse_mgmt_move_file($uploaded);
-      $form_state['values']['uploaded_file'] = $uploaded;
+      $uploaded = tripal_jbrowse_mgmt_upload_file('ref_seq_file');
+      if (!$uploaded) {
+        form_set_error('ref_seq_file', 'Unable to upload file');
+      }
+      else {
+        $uploaded = tripal_jbrowse_mgmt_move_file($uploaded);
+        $form_state['values']['uploaded_file'] = $uploaded;
+      }
     }
   }
 
   $instances = tripal_jbrowse_mgmt_get_instances(['organism_id' => $organism]);
   if (!empty($instances)) {
-    form_set_error(
-      'organism',
-      'A JBrowse instance for the selected organism already exists. You can edit the instance from the instances page.'
-    );
+    if (!$edit_form OR ($edit_form AND $instances[0]->id != $instance_id)) {
+      form_set_error(
+        'organism',
+        'A JBrowse instance for the selected organism already exists. You can edit the instance from the instances page.'
+      );
+    }
   }
 
   $organism = db_select('chado.organism', 'CO')
@@ -148,44 +241,84 @@ function tripal_jbrowse_mgmt_add_form_submit($form, &$form_state) {
   $organism_id = $values['organism'];
   $description = isset($values['description']) ? $values['description'] : '';
 
-  if (empty($values['uploaded_file'])) {
-    $file = $values['ref_seq_path'];
-  }
-  else {
-    $file = $values['uploaded_file'];
+  // Check if this is an add or edit form.
+  $edit_form = FALSE;
+  if (isset($form_state['build_info']['args'][0]) AND is_numeric($form_state['build_info']['args'][0])) {
+    $instance_id = $form_state['build_info']['args'][0];
+    $edit_form = TRUE;
   }
 
-  $organism = db_select('chado.organism', 'CO')
-    ->fields('CO')
-    ->condition('organism_id', $organism_id)
-    ->execute()
-    ->fetchObject();
+  if ($edit_form) {
+
+    $organism = db_select('chado.organism', 'CO')
+      ->fields('CO')
+      ->condition('organism_id', $organism_id)
+      ->execute()
+      ->fetchObject();
+
+    $title = tripal_jbrowse_mgmt_construct_organism_name($organism);
 
-  $instance_id = tripal_jbrowse_mgmt_create_instance(
-    [
+    $data = [
       'organism_id' => $organism_id,
-      'title' => tripal_jbrowse_mgmt_construct_organism_name($organism),
+      'title' => $title,
       'description' => $description,
-      'created_at' => time(),
-      'file' => $file,
-    ]
-  );
+    ];
+    $success = tripal_jbrowse_mgmt_update_instance($instance_id, $data);
+
+    if ($success) {
+      drupal_set_message("Successfully updated $title JBrowse instance.");
+      $form_state['redirect'] = 'admin/tripal/extension/tripal_jbrowse/management/instances';
+    }
+    else {
+      drupal_set_message('Failed to update the current instance!', 'error');
+    }
+  }
+  else {
+    if (empty($values['uploaded_file'])) {
+      $file = $values['ref_seq_path'];
+    }
+    else {
+      $file = $values['uploaded_file'];
+    }
+
+    $organism = db_select('chado.organism', 'CO')
+      ->fields('CO')
+      ->condition('organism_id', $organism_id)
+      ->execute()
+      ->fetchObject();
 
-  if ($instance_id) {
-    drupal_set_message('Instance created successfully!');
-    $name = 'Create JBrowse instance for ';
-    $name .= tripal_jbrowse_mgmt_construct_organism_name($organism);
-
-    tripal_add_job(
-      $name,
-      'tripal_jbrowse_mgmt',
-      'tripal_jbrowse_mgmt_create_instance_files',
-      [$instance_id],
-      $user->uid
+    $instance_id = tripal_jbrowse_mgmt_create_instance(
+      [
+        'organism_id' => $organism_id,
+        'title' => tripal_jbrowse_mgmt_construct_organism_name($organism),
+        'description' => $description,
+        'created_at' => time(),
+        'file' => $file,
+      ]
     );
-    drupal_goto("admin/tripal/extension/tripal_jbrowse/management/instances/$instance_id");
-    return $form;
+
+    if ($instance_id) {
+      drupal_set_message('Instance created successfully!');
+      $name = 'Create JBrowse instance for ';
+      $name .= tripal_jbrowse_mgmt_construct_organism_name($organism);
+
+      tripal_add_job(
+        $name,
+        'tripal_jbrowse_mgmt',
+        'tripal_jbrowse_mgmt_create_instance_files',
+        [$instance_id],
+        $user->uid
+      );
+      $form_state['redirect'] = "admin/tripal/extension/tripal_jbrowse/management/instances/$instance_id";
+    }
+    else {
+      drupal_set_message('Failed to create instance!', 'error');
+    }
   }
 
-  drupal_set_message('Failed to create instance!');
+  // Now save the instance properties.
+  tripal_jbrowse_mgmt_save_instance_properties(
+    $instance_id,
+    $form_state['values']['page']
+  );
 }

+ 4 - 4
tripal_jbrowse_mgmt/includes/tripal_jbrowse_mgmt_configure.form.inc

@@ -8,13 +8,13 @@
  * @return mixed
  */
 function tripal_jbrowse_mgmt_configure_form($form, &$form_state) {
+
+  $message = '<p>Before filling out this form, ensure you have downloaded and installed JBrowse on your server. At this time, JBrowse needs to be on the same server as this Tripal site. <br /><strong>This form allows you to configure the location of JBrowse.</strong></p>';
+
   $form['message'] = [
     '#type' => 'markup',
     '#prefix' => '<p>',
-    '#markup' => t(
-      'This form allows administrators to control
-      where JBrowse lives on the server.'
-    ),
+    '#markup' => t($message),
     '#suffix' => '</p>',
   ];
 

+ 8 - 0
tripal_jbrowse_mgmt/includes/tripal_jbrowse_mgmt_instance.page.inc

@@ -18,6 +18,14 @@ function tripal_jbrowse_mgmt_instance_page($instance_id) {
 
   drupal_set_title("Manage $instance->title JBrowse");
 
+  $breadcrumb = array();
+  $breadcrumb[] = l('Home', '');
+  $breadcrumb[] = l('Administration', 'admin');
+  $breadcrumb[] = l('Tripal', 'admin/tripal');
+  $breadcrumb[] = l('Extensions', 'admin/tripal/extension');
+  $breadcrumb[] = l('Tripal JBrowse', 'admin/tripal/extension/tripal_jbrowse/management');
+  drupal_set_breadcrumb($breadcrumb);
+
   $content = [];
 
   $content['instance_table'] = [

+ 9 - 0
tripal_jbrowse_mgmt/includes/tripal_jbrowse_mgmt_json_editor.form.inc

@@ -19,6 +19,15 @@ function tripal_jbrowse_mgmt_json_editor_form($form, &$form_state, $track_id) {
 
   drupal_set_title('Edit Track: ' . $track->label);
 
+  $breadcrumb = array();
+  $breadcrumb[] = l('Home', '');
+  $breadcrumb[] = l('Administration', 'admin');
+  $breadcrumb[] = l('Tripal', 'admin/tripal');
+  $breadcrumb[] = l('Extensions', 'admin/tripal/extension');
+  $breadcrumb[] = l('Tripal JBrowse', 'admin/tripal/extension/tripal_jbrowse/management');
+  $breadcrumb[] = l('Instance', 'admin/tripal/extension/tripal_jbrowse/management/instances/'.$track->instance_id);
+  drupal_set_breadcrumb($breadcrumb);
+
   $instance = tripal_jbrowse_mgmt_get_instance($track->instance_id);
   $json = tripal_jbrowse_mgmt_get_json($instance);
   $form_state['track_json'] = $json;

+ 16 - 4
tripal_jbrowse_mgmt/includes/tripal_jbrowse_mgmt_list.page.inc

@@ -8,6 +8,14 @@ function tripal_jbrowse_mgmt_instances_page() {
   $instances = tripal_jbrowse_mgmt_get_instances();
   $settings = tripal_jbrowse_mgmt_get_settings();
 
+  // Ensure people set settings before adding an instance!
+  if (empty($settings['data_dir'])) {
+    drupal_set_message(t(
+      'The <a href="@url">Location of your JBrowse</a> is required before creating an instance.',
+        ['@url' => url('admin/tripal/extension/tripal_jbrowse/management/configure')]),
+      'error');
+  }
+
   $content = [];
 
   if (empty($instances)) {
@@ -23,9 +31,9 @@ function tripal_jbrowse_mgmt_instances_page() {
     'Organism',
     'Submitter',
     'Description',
-    'Manage',
+    'Tracks',
     'Launch',
-    'Delete',
+    'Instance',
   ];
 
   $rows = [];
@@ -41,9 +49,13 @@ function tripal_jbrowse_mgmt_instances_page() {
       l(
         'Launch',
         $settings['link'],
-        ['query' => tripal_jbrowse_mgmt_build_http_query($instance)]
+        [
+          'query' => tripal_jbrowse_mgmt_build_http_query($instance),
+          'attributes' => ['target' => '_blank'],
+        ]
       ),
-      l('Delete Instance', 'admin/tripal/extension/tripal_jbrowse/management/instances/'.$instance->id.'/delete'),
+      l('Edit', 'admin/tripal/extension/tripal_jbrowse/management/instances/'.$instance->id.'/edit') . ' <br /> ' .
+      l('Delete', 'admin/tripal/extension/tripal_jbrowse/management/instances/'.$instance->id.'/delete'),
 
     ];
   }

+ 28 - 0
tripal_jbrowse_mgmt/tripal_jbrowse_mgmt.install

@@ -98,5 +98,33 @@ function tripal_jbrowse_mgmt_schema() {
     ],
   ];
 
+  $schema['tripal_jbrowse_mgmt_instanceprop'] = [
+    'description' => 'JBrowse Instance Metadata.',
+    'fields' => [
+      'instance_id' => [
+        'type' => 'int',
+        'not null' => TRUE,
+      ],
+      'property_type' => [
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+      ],
+      'value' => [
+        'type' => 'text',
+      ],
+    ]
+  ];
+
   return $schema;
 }
+
+/**
+ * Create instance metadata table.
+ */
+function tripal_jbrowse_mgmt_update_7001(&$sandbox) {
+  $schema = tripal_jbrowse_mgmt_schema();
+  $name = "tripal_jbrowse_mgmt_instanceprop";
+  $table = $schema[$name];
+  db_create_table($name, $table);
+}

+ 21 - 1
tripal_jbrowse_mgmt/tripal_jbrowse_mgmt.module

@@ -26,6 +26,16 @@ function tripal_jbrowse_mgmt_menu() {
     'type' => MENU_NORMAL_ITEM,
   ];
 
+  $items['admin/tripal/extension/tripal_jbrowse/management/instances'] = [
+    'title' => 'List Instances',
+    'description' => 'List JBrowse settings',
+    'page callback' => 'tripal_jbrowse_mgmt_instances_page',
+    'page arguments' => ['tripal_jbrowse_mgmt_configure_form'],
+    'access arguments' => ['administer tripal_jbrowse_mgmt'],
+    'file' => 'includes/tripal_jbrowse_mgmt_list.page.inc',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+  ];
+
   $items['admin/tripal/extension/tripal_jbrowse/management/configure'] = [
     'title' => 'Settings',
     'description' => 'List and create JBrowse instances.',
@@ -56,8 +66,18 @@ function tripal_jbrowse_mgmt_menu() {
     'type' => MENU_CALLBACK,
   ];
 
+  $items['admin/tripal/extension/tripal_jbrowse/management/instances/%/edit'] = [
+    'title' => 'Edit Instance',
+    'description' => 'Edit metadata for existing JBrowse instances.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => ['tripal_jbrowse_mgmt_add_form', 6],
+    'access arguments' => ['administer tripal_jbrowse_mgmt'],
+    'file' => 'includes/tripal_jbrowse_mgmt_add.form.inc',
+    'type' => MENU_LOCAL_ACTION,
+  ];
+
   $items['admin/tripal/extension/tripal_jbrowse/management/instances/%/delete'] = [
-    'title' => 'Delete an instance',
+    'title' => 'Delete Instance',
     'description' => 'Confirm deleting an instance.',
     'page callback' => 'drupal_get_form',
     'page arguments' => ['tripal_jbrowse_mgmt_delete_instance_form', 6],

Неке датотеке нису приказане због велике количине промена