diff --git a/core/modules/workspace/css/workspace.toolbar.css b/core/modules/workspace/css/workspace.toolbar.css new file mode 100644 index 0000000..81ee1f9 --- /dev/null +++ b/core/modules/workspace/css/workspace.toolbar.css @@ -0,0 +1,54 @@ +/** + * @file + * Styling for Workspace module's toolbar tab. + */ + +/* Tab appearance. */ +.toolbar .toolbar-bar .workspace-toolbar-tab.toolbar-tab { + float: right; /* LTR */ + background-color: #e09600; +} +[dir="rtl"] .toolbar .toolbar-bar .workspace-toolbar-tab.toolbar-tab { + float: left; +} +.toolbar .toolbar-bar .workspace-toolbar-tab.toolbar-tab.is-live { + background-color: #77b259; +} + +.toolbar .toolbar-bar .workspace-toolbar-tab .toolbar-item { + margin: 0; +} + +.toolbar .toolbar-icon-workspace:before { + background-image: url("../icons/ffffff/workspace.svg"); +} + +/* Manage workspaces link */ +.toolbar .toolbar-tray-vertical .manage-workspaces { + text-align: right; /* LTR */ + padding: 1em; +} +[dir="rtl"] .toolbar .toolbar-tray-vertical .manage-workspaces { + text-align: left; +} +.toolbar .toolbar-tray-horizontal .manage-workspaces { + float: right; /* LTR */ +} +[dir="rtl"] .toolbar .toolbar-tray-horizontal .manage-workspaces { + float: left; +} + +/* Individual workspace links */ +.toolbar-horizontal .toolbar-tray .toolbar-menu li + li { + border-left: 1px solid #dddddd; /* LTR */ +} +[dir="rtl"] .toolbar-horizontal .toolbar-tray .toolbar-menu li + li { + border-left: 0 none; + border-right: 1px solid #dddddd; +} +.toolbar-horizontal .toolbar-tray .toolbar-menu li:last-child { + border-right: 1px solid #dddddd; /* LTR */ +} +[dir="rtl"] .toolbar-horizontal .toolbar-tray .toolbar-menu li:last-child { + border-left: 1px solid #dddddd; +} diff --git a/core/modules/workspace/icons/ffffff/workspace.svg b/core/modules/workspace/icons/ffffff/workspace.svg new file mode 100644 index 0000000..299ff26 --- /dev/null +++ b/core/modules/workspace/icons/ffffff/workspace.svg @@ -0,0 +1 @@ + diff --git a/core/modules/workspace/src/Form/WorkspaceDeployForm.php b/core/modules/workspace/src/Form/WorkspaceDeployForm.php index 3b0fa57..9f1fa79 100644 --- a/core/modules/workspace/src/Form/WorkspaceDeployForm.php +++ b/core/modules/workspace/src/Form/WorkspaceDeployForm.php @@ -74,7 +74,7 @@ public function form(array $form, FormStateInterface $form_state) { } $form['help'] = [ - '#markup' => $this->t('Deploy all %source_upstream_label content to %target_upstream_label, or update %source_upstream_label with content from %target_upstream_label.', ['%source_upstream_label' => $workspace->getLocalRepositoryHandlerPlugin()->getLabel(), '%target_upstream_label' => $workspace->getRepositoryHandlerPlugin()->getLabel()]), + '#markup' => $this->t('Deploy all %source_upstream_label content to %target_upstream_label, or refresh %source_upstream_label with content from %target_upstream_label.', ['%source_upstream_label' => $workspace->getLocalRepositoryHandlerPlugin()->getLabel(), '%target_upstream_label' => $workspace->getRepositoryHandlerPlugin()->getLabel()]), ]; return $form; @@ -94,7 +94,7 @@ public function actions(array $form, FormStateInterface $form_state) { $elements['submit']['#submit'] = ['::submitForm', '::deploy']; $elements['update'] = [ '#type' => 'submit', - '#value' => $this->t('Update from @upstream', ['@upstream' => $upstream_label]), + '#value' => $this->t('Refresh from @upstream', ['@upstream' => $upstream_label]), '#submit' => ['::submitForm', '::update'], ]; $elements['cancel'] = [ diff --git a/core/modules/workspace/workspace.info.yml b/core/modules/workspace/workspace.info.yml index 27e086e..9599e07 100644 --- a/core/modules/workspace/workspace.info.yml +++ b/core/modules/workspace/workspace.info.yml @@ -4,5 +4,6 @@ description: 'Provides the ability to have multiple workspaces on a single site version: VERSION core: 8.x package: Core (Experimental) +configure: entity.workspace.collection dependencies: - user diff --git a/core/modules/workspace/workspace.libraries.yml b/core/modules/workspace/workspace.libraries.yml new file mode 100644 index 0000000..c7aad42 --- /dev/null +++ b/core/modules/workspace/workspace.libraries.yml @@ -0,0 +1,5 @@ +drupal.workspace.toolbar: + version: VERSION + css: + theme: + css/workspace.toolbar.css: {} diff --git a/core/modules/workspace/workspace.module b/core/modules/workspace/workspace.module index 68eaabc..5040b53 100644 --- a/core/modules/workspace/workspace.module +++ b/core/modules/workspace/workspace.module @@ -5,6 +5,9 @@ * Provides full-site preview functionality for content staging. */ +use Drupal\Component\Serialization\Json; +use Drupal\Core\Cache\Cache; +use Drupal\Core\Url; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Routing\RouteMatchInterface; @@ -549,3 +552,128 @@ function workspace_rest_resource_alter(&$definitions) { unset($definitions['entity:content_workspace']); unset($definitions['entity:replication_log']); } + +/** + * Implements hook_toolbar(). + */ +function workspace_toolbar() { + $items = []; + $items['workspace'] = [ + '#cache' => [ + 'contexts' => [ + 'user.permissions', + ], + ], + ]; + + $current_user = \Drupal::currentUser(); + if (!$current_user->hasPermission('administer workspaces') + || !$current_user->hasPermission('view own workspace') + || !$current_user->hasPermission('view any workspace')) { + return $items; + } + + /** @var \Drupal\workspace\WorkspaceInterface $active_workspace */ + $active_workspace = \Drupal::service('workspace.manager')->getActiveWorkspace(TRUE); + + $configure_link = NULL; + if ($current_user->hasPermission('administer workspaces')) { + $configure_link = [ + '#type' => 'link', + '#title' => t('Manage workspaces'), + '#url' => $active_workspace->toUrl('collection'), + '#options' => ['attributes' => ['class' => ['manage-workspaces']]], + ]; + } + + $items['workspace'] = [ + '#type' => 'toolbar_item', + 'tab' => [ + '#type' => 'link', + '#title' => $active_workspace->label(), + '#url' => $active_workspace->toUrl('collection'), + '#attributes' => [ + 'title' => t('Switch workspace'), + 'class' => ['toolbar-icon', 'toolbar-icon-workspace'], + ], + ], + 'tray' => [ + '#heading' => t('Workspaces'), + 'workspaces' => workspace_renderable_links(), + 'configure' => $configure_link, + ], + '#wrapper_attributes' => [ + 'class' => ['workspace-toolbar-tab'], + ], + '#attached' => [ + 'library' => ['workspace/drupal.workspace.toolbar'], + ], + '#weight' => 500, + ]; + + // Add a special class to the wrapper if we are in the default workspace so we + // can highlight it with a different color. + if ($active_workspace->id() === WorkspaceManager::DEFAULT_WORKSPACE) { + $items['workspace']['#wrapper_attributes']['class'][] = 'is-live'; + } + + return $items; +} + +/** + * Returns an array of workspace activation form links, suitable for rendering. + * + * @return array + * A render array containing links to the workspace activation form. + */ +function workspace_renderable_links() { + $entity_type_manager = \Drupal::entityTypeManager(); + /** @var \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository */ + $entity_repository = \Drupal::service('entity.repository'); + /** @var \Drupal\workspace\WorkspaceInterface $active_workspace */ + $active_workspace = \Drupal::service('workspace.manager')->getActiveWorkspace(TRUE); + + $links = $cache_tags = []; + foreach ($entity_type_manager->getStorage('workspace')->loadMultiple() as $workspace) { + $workspace = $entity_repository->getTranslationFromContext($workspace); + + // Add the 'is-active' class for the currently active workspace. + $options = []; + if ($workspace->id() === $active_workspace->id()) { + $options['attributes']['class'][] = 'is-active'; + } + + // Get the URL of the workspace activation form and display it in a modal. + $url = Url::fromRoute('entity.workspace.activate_form', ['workspace' => $workspace->id()], $options); + if ($url->access()) { + $links[$workspace->id()] = [ + 'type' => 'link', + 'title' => $workspace->label(), + 'url' => $url, + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode([ + 'width' => 500, + ]), + ], + ]; + $cache_tags = Cache::mergeTags($cache_tags, $workspace->getCacheTags()); + } + } + + if (!empty($links)) { + $links = [ + '#theme' => 'links__toolbar_workspaces', + '#links' => $links, + '#attributes' => [ + 'class' => ['toolbar-menu'], + ], + '#cache' => [ + 'tags' => $cache_tags, + ], + ]; + } + + return $links; +}