diff --git a/ds.field_ui.inc b/ds.field_ui.inc
index 3f45468..d78ec3b 100644
--- a/ds.field_ui.inc
+++ b/ds.field_ui.inc
@@ -83,14 +83,19 @@ function ds_field_ui_create_vertical_tabs(&$form) {
     $form['#attached']['js'][] = 'misc/collapse.js';
   }
 
+  $view_mode_admin_access = user_access('admin_view_modes');
   if (isset($form['modes'])) {
-    $form['modes']['view_modes_custom']['#description'] = l(t('Manage view modes'), 'admin/structure/ds/view_modes');
+    if ($view_mode_admin_access) {
+      $form['modes']['view_modes_custom']['#description'] = l(t('Manage view modes'), 'admin/structure/ds/view_modes');
+    }
     $form['additional_settings']['modes'] = $form['modes'];
     $form['additional_settings']['modes']['#weight'] = -10;
     unset($form['modes']);
   }
   else {
-    $form['additional_settings']['modes']['view_modes_custom']['#description'] = l(t('Manage view modes'), 'admin/structure/ds/view_modes');
+    if ($view_mode_admin_access) {
+      $form['additional_settings']['modes']['view_modes_custom']['#description'] = l(t('Manage view modes'), 'admin/structure/ds/view_modes');
+    }
   }
 }
 
@@ -1002,6 +1007,87 @@ function ds_ctools_get_category($content_type) {
 }
 
 /**
+ * Handles ctools modal Add field
+ *
+ * @param $js
+ *  Whether js is used or not.
+ * @param $field_type
+ *   The name of the field type.
+ */
+function ds_ajax_add_field($js, $field_type) {
+
+  if (!$js) {
+    // We don't support degrading this from js because we're not
+    // using the server to remember the state of the table.
+    drupal_goto("admin/structure/ds/fields/" . $field_type);
+    return;
+  }
+
+  ctools_include('ajax');
+  ctools_include('modal');
+
+  module_load_include('inc', 'ds', 'ds.registry');
+
+  switch ($field_type) {
+
+    case "manage_ctools":
+      $title = t('Add a dynamic field');
+      $form_name = "ds_edit_ctools_field_form";
+      break;
+
+    case "manage_preprocess":
+      $title = t('Add a preprocess field');
+      $form_name = "ds_edit_preprocess_field_form";
+      break;
+
+    case "manage_block":
+      $title = t('Add a block field');
+      $form_name = "ds_edit_block_field_form";
+      break;
+
+    default:
+      $title = t('Add a code field');
+      $form_name = "ds_edit_custom_field_form";
+      $field_type = 'manage_custom';
+      break;
+  }
+
+  $form_state = array();
+  $form_state['build_info']['args'] = array();
+  $form_state += array(
+    'title' => $title,
+    'ajax' => TRUE,
+    're_render' => FALSE,
+  );
+
+  $output = NULL;
+  form_load_include($form_state, 'inc', 'ds', 'ds.fields');
+
+  $output = ctools_modal_form_wrapper($form_name, $form_state);
+
+  // Field is saved.
+  if ($form_state['executed']) {
+
+    $output = array();
+
+    // Do not print messages on screen.
+    if ($messages = theme('status_messages')) {
+      $output[] = ajax_command_append('#console', $messages);
+    }
+
+    // Close the modal.
+    $output[] = ctools_modal_command_dismiss();
+
+    // Call our own javascript function which will trigger a refresh of the table.
+    $output[] = ajax_command_invoke('#field-display-overview', 'dsRefreshDisplayTable');
+  }
+
+  drupal_add_http_header('Content-Type', 'application/json');
+  print ajax_render($output);
+  exit;
+}
+
+/**
  * Add the layouts fieldset on the Field UI screen.
  *
  * @param $entity_type
@@ -1435,6 +1521,7 @@ function _ds_field_ui_custom_fields($entity_type, $bundle, $view_mode, &$form, $
     '#type' => 'fieldset',
     '#title' => t('Add custom fields'),
     '#description' => t('Click on one of the buttons to create a new field. Note that these only appear if a layout has been selected.') . '<p></p>',
+    '#access' => user_access('admin_fields'),
   );
 
   // Include the CTools tools that we need.
@@ -1471,87 +1558,6 @@ function _ds_field_ui_custom_fields($entity_type, $bundle, $view_mode, &$form, $
 }
 
 /**
- * Handles ctools modal Add field
- *
- * @param $js
- *  Whether js is used or not.
- * @param $field_type
- *   The name of the field type.
- */
-function ds_ajax_add_field($js, $field_type) {
-
-  if (!$js) {
-    // We don't support degrading this from js because we're not
-    // using the server to remember the state of the table.
-    drupal_goto("admin/structure/ds/fields/" . $field_type);
-    return;
-  }
-
-  ctools_include('ajax');
-  ctools_include('modal');
-
-  module_load_include('inc', 'ds', 'ds.registry');
-
-  switch ($field_type) {
-
-    case "manage_ctools":
-      $title = t('Add a dynamic field');
-      $form_name = "ds_edit_ctools_field_form";
-      break;
-
-    case "manage_preprocess":
-      $title = t('Add a preprocess field');
-      $form_name = "ds_edit_preprocess_field_form";
-      break;
-
-    case "manage_block":
-      $title = t('Add a block field');
-      $form_name = "ds_edit_block_field_form";
-      break;
-
-    default:
-      $title = t('Add a code field');
-      $form_name = "ds_edit_custom_field_form";
-      $field_type = 'manage_custom';
-      break;
-  }
-
-  $form_state = array();
-  $form_state['build_info']['args'] = array();
-  $form_state += array(
-    'title' => $title,
-    'ajax' => TRUE,
-    're_render' => FALSE,
-  );
-
-  $output = NULL;
-  form_load_include($form_state, 'inc', 'ds', 'ds.fields');
-
-  $output = ctools_modal_form_wrapper($form_name, $form_state);
-
-  // Field is saved.
-  if ($form_state['executed']) {
-
-    $output = array();
-
-    // Do not print messages on screen.
-    if ($messages = theme('status_messages')) {
-      $output[] = ajax_command_append('#console', $messages);
-    }
-
-    // Close the modal.
-    $output[] = ctools_modal_command_dismiss();
-
-    // Call our own javascript function which will trigger a refresh of the table.
-    $output[] = ajax_command_invoke('#field-display-overview', 'dsRefreshDisplayTable');
-  }
-
-  drupal_add_http_header('Content-Type', 'application/json');
-  print ajax_render($output);
-  exit;
-}
-
-/**
  * Utility function to check if we need to save anything for this field.
  */
 function _ds_field_valid($key, $field, &$form_state) {
diff --git a/ds.registry.inc b/ds.registry.inc
index 0304db6..aa5cc7a 100644
--- a/ds.registry.inc
+++ b/ds.registry.inc
@@ -114,7 +114,7 @@ function _ds_menu() {
     'type' => MENU_CALLBACK,
   );
   $items['admin/structure/ds/fields/manage_custom'] = array(
-    'title' => 'Add a field',
+    'title' => 'Add a code field',
     'description' => 'Manage a field',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('ds_edit_custom_field_form'),
@@ -148,7 +148,7 @@ function _ds_menu() {
     'file' => 'ds.fields.inc',
     'access arguments' => array('admin_fields'),
     'type' => MENU_LOCAL_ACTION,
-    'weight' => 2,
+    'weight' => 3,
   );
   $items['admin/structure/ds/fields/delete'] = array(
     'title' => 'Delete a field',
@@ -178,7 +178,7 @@ function _ds_menu() {
       'file' => 'ds.fields.inc',
       'access arguments' => array('admin_fields'),
       'type' => MENU_LOCAL_ACTION,
-      'weight' => 3,
+      'weight' => 2,
     );
   }
 
diff --git a/modules/ds_extras/ds_extras.panels.inc b/modules/ds_extras/ds_extras.panels.inc
index d7908cd..9665703 100644
--- a/modules/ds_extras/ds_extras.panels.inc
+++ b/modules/ds_extras/ds_extras.panels.inc
@@ -141,6 +141,7 @@ function ds_panels_display_settings($form, $form_state, $entity_type, $bundle) {
   $form['#entity_type'] = $entity_type;
   $form['#bundle'] = $bundle;
 
+  $view_mode_admin_access = user_access('admin_view_modes');
   $view_modes = ds_panels_get_enabled_view_modes($entity_type, $bundle);
   if (!empty($view_modes)) {
     $form['view_modes_custom'] = array(
@@ -148,7 +149,7 @@ function ds_panels_display_settings($form, $form_state, $entity_type, $bundle) {
       '#title' => t('Use custom display settings for the following view modes'),
       '#options' => $view_modes['options'],
       '#default_value' => $view_modes['default'],
-      '#description' => l(t('Manage view modes'), 'admin/structure/ds/view_modes'),
+      '#description' => $view_mode_admin_access ? l(t('Manage view modes'), 'admin/structure/ds/view_modes') : '',
     );
     $form['modes_save'] = array(
       '#type' => 'submit',
diff --git a/tests/ds.base.test b/tests/ds.base.test
index 1286280..e4a9382 100644
--- a/tests/ds.base.test
+++ b/tests/ds.base.test
@@ -161,6 +161,27 @@ class dsBaseTest extends DrupalWebTestCase {
     $this->drupalPost($url, $edit, t('Save'));
     $this->assertText(t('The field ' . $edit['name'] . ' has been saved'), t('!name field has been saved', array('!name' => $edit['name'])));
   }
+
+  /**
+   * Create a dynamic field.
+   *
+   * @param $edit
+   *   An optional array of field properties.
+   */
+  function dsCreateDynamicField($edit = array(), $url = 'admin/structure/ds/fields/manage_ctools', $first = TRUE) {
+
+    $edit += array(
+      'name' => 'Dynamic',
+      'entities[node]' => '1',
+    );
+
+    if ($first) {
+      $edit += array('field' => 'dynamic');
+    }
+
+    $this->drupalPost($url, $edit, t('Save'));
+    $this->assertText(t('The field ' . $edit['name'] . ' has been saved'), t('!name field has been saved', array('!name' => $edit['name'])));
+  }
 }
 
 /**
@@ -174,7 +195,7 @@ class dsFieldsTests extends dsBaseTest {
   public static function getInfo() {
     return array(
       'name' => t('Fields'),
-      'description' => t('Tests for managing custom code, preprocess and block fields.'),
+      'description' => t('Tests for managing custom code, dynamic, preprocess and block fields.'),
       'group' => t('Display suite'),
     );
   }
@@ -312,6 +333,48 @@ class dsFieldsTests extends dsBaseTest {
     $this->assertNoRaw('fields[submitted][weight]', t('Submitted field not found on node article.'));
   }
 
+  /**
+   * Test dynamic fields.
+   */
+  function testDSDynamicFields() {
+
+    $edit = array(
+      'name' => 'Dynamic',
+      'field' => 'dynamic',
+      'entities[node]' => '1',
+    );
+
+    $this->dsCreateDynamicField($edit);
+
+    // Create the same and assert it already exists.
+    $this->drupalPost('admin/structure/ds/fields/manage_ctools', $edit, t('Save'));
+    $this->assertText(t('The machine-readable name is already in use. It must be unique.'), t('Submitted already exists.'));
+
+    $this->dsSelectLayout();
+
+    // Assert it's found on the Field UI for article.
+    $this->drupalGet('admin/structure/types/manage/article/display');
+    $this->assertRaw('fields[dynamic][weight]', t('Submitted found on node article.'));
+
+    // Assert it's not found on the Field UI for article.
+    $this->drupalGet('admin/config/people/accounts/display');
+    $this->assertNoRaw('fields[dynamic][weight]', t('Dynamic not found on user.'));
+
+    // Update testing label
+    $edit = array(
+      'name' => 'Uber dynamic',
+    );
+    $this->drupalPost('admin/structure/ds/fields/manage_ctools/dynamic', $edit, t('Save'));
+    $this->assertText(t('The field Uber dynamic has been saved'), t('Dynamic label updated'));
+
+    // Remove a field.
+    $this->drupalPost('admin/structure/ds/fields/delete/dynamic', array(), t('Delete'));
+    $this->assertText(t('The field Uber dynamic has been deleted'), t('Submitted removed'));
+
+    // Assert the field is gone at the manage display screen.
+    $this->drupalGet('admin/structure/types/manage/article/display');
+    $this->assertNoRaw('fields[dynamic][weight]', t('Dynamic field not found on node article.'));
+  }
 }
 
 /**
@@ -389,7 +452,7 @@ class dsLayoutsStylesTests extends dsBaseTest {
   }
 
   /**
-   * Test selecting layouts, empty regions, classes, region to block and basic fields.
+   * Test selecting layouts, empty regions, classes, region to block and fields.
    */
   function testDStestLayouts() {
 
@@ -397,9 +460,10 @@ class dsLayoutsStylesTests extends dsBaseTest {
     $this->drupalGet('admin/structure/types/manage/article/display');
     $this->assertNoRaw('ds_3col_stacked_equal_width', 'ds_3col_stacked_equal_width not available');
 
-    // Create code, preprocess block field.
+    // Create code, dynamic, preprocess block field.
     $this->dsCreateCodeField();
     $this->dsCreateBlockField();
+    $this->dsCreateDynamicField();
     $this->dsCreatePreprocessField();
 
     $layout = array(
@@ -424,6 +488,8 @@ class dsLayoutsStylesTests extends dsBaseTest {
       'fields[test_field][region]' => 'left',
       'fields[test_block_field][region]' => 'left',
       'fields[submitted][region]' => 'left',
+      'fields[dynamic][region]' => 'left',
+      'fields[ds_extras_extra_test_field][region]' => 'header',
     );
 
     // Setup first layout.
@@ -438,12 +504,14 @@ class dsLayoutsStylesTests extends dsBaseTest {
 
     // Lookup settings and verify.
     $data = unserialize(db_query("SELECT settings FROM {ds_layout_settings} WHERE entity_type = 'node' AND bundle = 'article' AND view_mode = 'default'")->fetchField());
+    $this->assertTrue(in_array('ds_extras_extra_test_field', $data['regions']['header']), t('Extra field is in header'));
     $this->assertTrue(in_array('post_date', $data['regions']['header']), t('Post date is in header'));
     $this->assertTrue(in_array('test_field', $data['regions']['left']), t('Test field is in left'));
     $this->assertTrue(in_array('author', $data['regions']['left']), t('Author is in left'));
     $this->assertTrue(in_array('links', $data['regions']['left']), t('Links is in left'));
     $this->assertTrue(in_array('test_block_field', $data['regions']['left']), t('Test block field is in left'));
     $this->assertTrue(in_array('submitted', $data['regions']['left']), t('Submitted field is in left'));
+    $this->assertTrue(in_array('dynamic', $data['regions']['left']), t('Dynamic field is in left'));
     $this->assertTrue(in_array('body', $data['regions']['right']), t('Body is in right'));
     $this->assertTrue(in_array('comments', $data['regions']['footer']), t('Comments is in footer'));
     $this->assertTrue(in_array('class_name_1', $data['classes']['header']), t('Class name 1 is in header'));
@@ -451,6 +519,25 @@ class dsLayoutsStylesTests extends dsBaseTest {
     $this->assertTrue(empty($data['classes']['right']), t('Right has classes'));
     $this->assertTrue(in_array('class_name_2', $data['classes']['footer']), t('Class name 2 is in header'));
 
+    // Extra save for the dynamic field.
+    $field_settings = ds_get_field_settings('node', 'article', 'default');
+    $formatter_settings = array(
+      'show_title' => 0,
+      'title_wrapper' => '',
+      'ctools' => 'a:3:{s:4:"conf";a:3:{s:7:"context";s:25:"argument_entity_id:node_1";s:14:"override_title";i:0;s:19:"override_title_text";s:0:"";}s:4:"type";s:14:"node_type_desc";s:7:"subtype";s:14:"node_type_desc";}',
+    );
+    $field_settings['dynamic']['formatter_settings'] = $formatter_settings;
+    $record = new stdClass();
+    $record->id = 'node|article|default';
+    $record->entity_type = 'node';
+    $record->bundle = 'article';
+    $record->view_mode = 'default';
+    $record->settings = $field_settings;
+    drupal_write_record('ds_field_settings', $record, array('id'));
+    cache_clear_all('ds_fields', 'cache');
+    cache_clear_all('ds_field_settings', 'cache');
+
+
     // Create a article node and verify settings.
     $settings = array(
       'type' => 'article',
@@ -472,6 +559,8 @@ class dsLayoutsStylesTests extends dsBaseTest {
     $this->assertRaw('field-name-test-block-field', t('Custom block field found'));
     $this->assertRaw('<h2>Recent content</h2>', t('Custom block field found'));
     $this->assertRaw('Submitted by', t('Submitted field found'));
+    $this->assertText('Use articles for time-sensitive content like news, press releases or blog posts.', t('Dynamic field found'));
+    $this->assertText('This is an extra field made available through "Extra fields" functionality.');
 
     // Test empty regions checkbox.
     $fields = array(
diff --git a/tests/ds_test.module b/tests/ds_test.module
index 052eb1b..31dd35f 100644
--- a/tests/ds_test.module
+++ b/tests/ds_test.module
@@ -14,6 +14,18 @@ function ds_test_install() {
   variable_set('ds_extras_hide_page_title', TRUE);
   variable_set('ds_extras_field_template', TRUE);
   variable_set('ds_extras_revision_view_mode', TRUE);
+  variable_set('ds_extras_fields_extra', TRUE);
+  variable_set('ds_extras_fields_extra_list', 'node|article|ds_extras_extra_test_field');
+}
+
+/**
+ * Implements hook_node_view().
+ */
+function ds_test_node_view($node, $view_mode, $langcode) {
+  $node->content['ds_extras_extra_test_field'] = array(
+    '#markup' => 'This is an extra field made available through "Extra fields" functionality.',
+    '#weight' => 10,
+  );
 }
 
 /**
