From 8989f2d439b74bc10e5a7a6a685cea56783b5078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 31 Jul 2023 13:36:18 +0200 Subject: [PATCH] Add lookbook --- Gemfile | 3 + Gemfile.lock | 31 +- app/assets/images/icon_logo.svg | 56 +++ app/assets/images/icon_logo_white.svg | 6 + app/helpers/frontend_asset_helper.rb | 6 + app/views/layouts/component_preview.html.erb | 38 ++ config/initializers/lookbook.rb | 45 ++ config/initializers/view_component.rb | 2 + config/routes.rb | 4 + frontend/angular.json | 4 + frontend/src/global_styles/content/_user.lsg | 26 -- .../src/global_styles/content/_widget_box.lsg | 108 ----- frontend/src/global_styles/content/_wiki.lsg | 358 ---------------- .../work_packages/tabs/_activities.lsg | 389 ------------------ frontend/src/global_styles/fonts/_index.lsg | 8 - frontend/src/global_styles/fonts/_lato.lsg | 20 - .../fonts/_openproject_icon_font.lsg | 304 -------------- frontend/src/global_styles/layout/_index.sass | 3 + .../src/global_styles/layout/_toolbar.lsg | 143 ------- .../layout/_viewcomponent_previews.sass | 3 + frontend/src/spot.scss | 9 + .../patches/lookbook_tree_node_inflector.rb | 47 +++ spec/components/docs/01-how-to-use.md.erb | 24 ++ spec/components/docs/02-semantics.erb | 29 ++ .../docs/styles/01-typography.md.erb | 195 +++++++++ spec/components/docs/styles/02-colors.md.erb | 237 +++++++++++ spec/components/docs/styles/03-focus.md.erb | 9 + spec/components/docs/styles/04-icons.md.erb | 102 +++++ .../previews/advanced_filters_preview.rb | 4 + .../advanced_filters_preview/default.html.erb | 10 +- .../previews/toolbar_component_preview.rb | 12 + .../default.html.erb | 21 + .../with_form_elements.html.erb | 38 ++ .../with_labelled_form_elements.html.erb | 36 ++ .../default.html.erb | 11 + .../previews/widget_component_preview.rb | 7 + .../widget_component_preview/default.html.erb | 100 +++++ .../work_package_list_to_pdf_spec.rb | 227 ---------- .../pdf_export/work_package_to_pdf_spec.rb | 112 ----- spec/support/work_packages/pdf_export.rb | 12 - 40 files changed, 1071 insertions(+), 1728 deletions(-) create mode 100644 app/assets/images/icon_logo.svg create mode 100644 app/assets/images/icon_logo_white.svg create mode 100644 app/views/layouts/component_preview.html.erb create mode 100644 config/initializers/lookbook.rb delete mode 100644 frontend/src/global_styles/content/_user.lsg delete mode 100644 frontend/src/global_styles/content/_widget_box.lsg delete mode 100644 frontend/src/global_styles/content/_wiki.lsg delete mode 100644 frontend/src/global_styles/content/work_packages/tabs/_activities.lsg delete mode 100644 frontend/src/global_styles/fonts/_index.lsg delete mode 100644 frontend/src/global_styles/fonts/_lato.lsg delete mode 100644 frontend/src/global_styles/fonts/_openproject_icon_font.lsg delete mode 100644 frontend/src/global_styles/layout/_toolbar.lsg create mode 100644 frontend/src/global_styles/layout/_viewcomponent_previews.sass create mode 100644 frontend/src/spot.scss create mode 100644 lib/open_project/patches/lookbook_tree_node_inflector.rb create mode 100644 spec/components/docs/01-how-to-use.md.erb create mode 100644 spec/components/docs/02-semantics.erb create mode 100644 spec/components/docs/styles/01-typography.md.erb create mode 100644 spec/components/docs/styles/02-colors.md.erb create mode 100644 spec/components/docs/styles/03-focus.md.erb create mode 100644 spec/components/docs/styles/04-icons.md.erb create mode 100644 spec/components/previews/advanced_filters_preview.rb rename frontend/src/global_styles/content/_advanced_filters.lsg => spec/components/previews/advanced_filters_preview/default.html.erb (97%) create mode 100644 spec/components/previews/toolbar_component_preview.rb create mode 100644 spec/components/previews/toolbar_component_preview/default.html.erb create mode 100644 spec/components/previews/toolbar_component_preview/with_form_elements.html.erb create mode 100644 spec/components/previews/toolbar_component_preview/with_labelled_form_elements.html.erb create mode 100644 spec/components/previews/tooltip_component_preview/default.html.erb create mode 100644 spec/components/previews/widget_component_preview.rb create mode 100644 spec/components/previews/widget_component_preview/default.html.erb delete mode 100644 spec/models/work_packages/pdf_export/work_package_list_to_pdf_spec.rb delete mode 100644 spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb delete mode 100644 spec/support/work_packages/pdf_export.rb diff --git a/Gemfile b/Gemfile index 3022b1c5d52..237aca80985 100644 --- a/Gemfile +++ b/Gemfile @@ -279,6 +279,9 @@ group :development do gem 'livingstyleguide', '~> 2.1.0' gem 'sassc-rails' + # Lookbook + gem 'lookbook', '~> 2.0.3' + gem 'colored2' # git hooks manager diff --git a/Gemfile.lock b/Gemfile.lock index 420cda757a2..d78d67c8ec8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -216,7 +216,6 @@ PATH GEM remote: https://rubygems.org/ specs: - Ascii85 (1.1.0) actioncable (7.0.6) actionpack (= 7.0.6) activesupport (= 7.0.6) @@ -306,7 +305,6 @@ GEM addressable (2.8.4) public_suffix (>= 2.0.2, < 6.0) aes_key_wrap (1.1.0) - afm (0.2.2) airbrake (13.0.3) airbrake-ruby (~> 6.0) airbrake-ruby (6.2.1) @@ -383,6 +381,8 @@ GEM cuprite (0.14.3) capybara (~> 3.0) ferrum (~> 0.13.0) + css_parser (1.14.0) + addressable daemons (1.4.1) dalli (3.2.5) date (3.3.3) @@ -532,12 +532,13 @@ GEM gravatar_image_tag (1.2.0) hana (1.3.7) hashdiff (1.0.1) - hashery (2.1.2) hashie (3.6.0) html-pipeline (2.14.3) activesupport (>= 2) nokogiri (>= 1.4) + htmlbeautifier (1.4.2) htmldiff (0.0.1) + htmlentities (4.3.4) http-accept (1.7.0) http-cookie (1.0.5) domain_name (~> 0.5) @@ -603,6 +604,18 @@ GEM loofah (2.21.3) crass (~> 1.0.2) nokogiri (>= 1.12.0) + lookbook (2.0.3) + activemodel + css_parser + htmlbeautifier (~> 1.3) + htmlentities (~> 4.3.4) + marcel (~> 1.0) + railties (>= 5.0) + redcarpet (~> 3.5) + rouge (>= 3.26, < 5.0) + view_component (>= 2.0) + yard (~> 0.9.25) + zeitwerk (~> 2.5) mail (2.8.1) mini_mime (>= 0.1.1) net-imap @@ -679,14 +692,6 @@ GEM ast (~> 2.4.1) racc pdf-core (0.9.0) - pdf-inspector (1.3.0) - pdf-reader (>= 1.0, < 3.0.a) - pdf-reader (2.11.0) - Ascii85 (~> 1.0) - afm (~> 0.2.1) - hashery (~> 2.0) - ruby-rc4 - ttfunk pg (1.5.3) plaintext (0.3.4) activesupport (> 2.2.1) @@ -873,7 +878,6 @@ GEM ruby-ole (1.2.12.2) ruby-prof (1.6.3) ruby-progressbar (1.13.0) - ruby-rc4 (0.1.5) ruby-saml (1.15.0) nokogiri (>= 1.13.10) rexml @@ -995,6 +999,7 @@ GEM activerecord (>= 4.2) xpath (3.2.0) nokogiri (~> 1.8) + yard (0.9.34) zeitwerk (2.6.8) PLATFORMS @@ -1070,6 +1075,7 @@ DEPENDENCIES listen (~> 3.8.0) livingstyleguide (~> 2.1.0) lograge (~> 0.12.0) + lookbook (~> 2.0.3) mail (= 2.8.1) matrix (~> 0.4.2) md_to_pdf! @@ -1111,7 +1117,6 @@ DEPENDENCIES ox paper_trail (~> 12.3) parallel_tests (~> 4.0) - pdf-inspector (~> 1.2) pg (~> 1.5.0) plaintext (~> 0.3.2) prawn (~> 2.2) diff --git a/app/assets/images/icon_logo.svg b/app/assets/images/icon_logo.svg new file mode 100644 index 00000000000..8cfeda1fe4f --- /dev/null +++ b/app/assets/images/icon_logo.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/app/assets/images/icon_logo_white.svg b/app/assets/images/icon_logo_white.svg new file mode 100644 index 00000000000..8cec02cbf05 --- /dev/null +++ b/app/assets/images/icon_logo_white.svg @@ -0,0 +1,6 @@ + + + + diff --git a/app/helpers/frontend_asset_helper.rb b/app/helpers/frontend_asset_helper.rb index a19b69c3da7..664c7c88d29 100644 --- a/app/helpers/frontend_asset_helper.rb +++ b/app/helpers/frontend_asset_helper.rb @@ -54,6 +54,12 @@ module FrontendAssetHelper end end + def include_spot_assets + capture do + concat stylesheet_link_tag variable_asset_path("spot.css"), media: :all, skip_pipeline: true + end + end + private def angular_cli_asset(path) diff --git a/app/views/layouts/component_preview.html.erb b/app/views/layouts/component_preview.html.erb new file mode 100644 index 00000000000..161be9fab86 --- /dev/null +++ b/app/views/layouts/component_preview.html.erb @@ -0,0 +1,38 @@ +<%#-- copyright +OpenProject is an open source project management software. +Copyright (C) 2012-2023 the OpenProject GmbH + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 3. + +OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +Copyright (C) 2006-2013 Jean-Philippe Lang +Copyright (C) 2010-2013 the ChiliProject Team + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +See COPYRIGHT and LICENSE files for more details. + +++#%> + + + <%= include_frontend_assets %> + + +
+ <%= yield %> +
+ + diff --git a/config/initializers/lookbook.rb b/config/initializers/lookbook.rb new file mode 100644 index 00000000000..673f8be96e5 --- /dev/null +++ b/config/initializers/lookbook.rb @@ -0,0 +1,45 @@ +OpenProject::Application.configure do + next unless Rails.env.development? + + config.lookbook.project_name = "OpenProject Lookbook" + config.lookbook.project_logo = Rails.root.join('app/assets/images/icon_logo_white.svg').read + config.lookbook.ui_favicon = Rails.root.join('app/assets/images/icon_logo.svg').read + config.lookbook.page_paths = [Rails.root.join("spec/components/docs/").to_s] + # Show notes first, all other panels next + config.lookbook.component_paths << Primer::ViewComponents::Engine.root.join("app", "components").to_s + config.view_component.preview_paths << Primer::ViewComponents::Engine.root.join("previews").to_s + config.lookbook.preview_inspector.drawer_panels = [:notes, "*"] + config.lookbook.ui_theme = "blue" + + SecureHeaders::Configuration.named_append(:lookbook) do + { + script_src: %w('unsafe-eval' 'unsafe-inline') # rubocop:disable Lint/PercentStringArray + } + end + + # rubocop:disable Lint/ConstantDefinitionInBlock + module LookbookCspExtender + extend ActiveSupport::Concern + + included do + before_action do + use_content_security_policy_named_append :lookbook + end + end + end + # rubocop:enable Lint/ConstantDefinitionInBlock + + Rails.application.reloader.to_prepare do + [ + Lookbook::ApplicationController, + Lookbook::PreviewController, + Lookbook::PreviewsController, + Lookbook::PageController, + Lookbook::PagesController, + Lookbook::InspectorController, + Lookbook::EmbedsController + ].each do |controller| + controller.include LookbookCspExtender + end + end +end diff --git a/config/initializers/view_component.rb b/config/initializers/view_component.rb index 087ebd47e6e..fc77b9d988f 100644 --- a/config/initializers/view_component.rb +++ b/config/initializers/view_component.rb @@ -1,5 +1,7 @@ OpenProject::Application.configure do config.view_component.generate.preview_path = Rails.root.join("spec/components/previews").to_s config.view_component.preview_paths << Rails.root.join("spec/components/previews").to_s + config.view_component.generate.preview = true + config.view_component.default_preview_layout = "component_preview" end diff --git a/config/routes.rb b/config/routes.rb index 1b53e7197d7..87f11ea3831 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -603,4 +603,8 @@ OpenProject::Application.routes.draw do # Routes for design related documentation and examples pages get '/design/styleguide' => redirect('/assets/styleguide.html') + + if Rails.env.development? + mount Lookbook::Engine, at: "/design/lookbook" + end end diff --git a/frontend/angular.json b/frontend/angular.json index 9340820e72a..e22366fab42 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -48,6 +48,10 @@ "src/assets" ], "styles": [ + { + "input": "src/spot.scss", + "bundleName": "spot" + }, "src/styles.scss", "node_modules/codemirror/lib/codemirror.css", "node_modules/jquery-ui/themes/base/core.css", diff --git a/frontend/src/global_styles/content/_user.lsg b/frontend/src/global_styles/content/_user.lsg deleted file mode 100644 index deda13d9883..00000000000 --- a/frontend/src/global_styles/content/_user.lsg +++ /dev/null @@ -1,26 +0,0 @@ -# User Avatars - -``` - -Standard:
- -

-Standard Mini:
- -

-Default:
-
OA
-

-Default Medium:
-
OA
-

-Default Mini:
-
OA
-

-Gravatar:
- -

-Gravatar Mini:
- - -``` diff --git a/frontend/src/global_styles/content/_widget_box.lsg b/frontend/src/global_styles/content/_widget_box.lsg deleted file mode 100644 index 3cafdd2a184..00000000000 --- a/frontend/src/global_styles/content/_widget_box.lsg +++ /dev/null @@ -1,108 +0,0 @@ -# Widget Boxes - -``` -@full-width - -
-
- - -
-

-
-

Widget Box

-
-

-

This widget box can be used to display content belonging to one subject.

- -
- - -
-

-
-

Widget Box 2

-
-

- -
- - -
-

-
-

Widget Box 3

-
-

-
-

- Lorem ipsum dolor sit amet, his ei propriae suscipit. - Sit in atqui accumsan ponderum, eum ut luptatum lobortis, has ei tota illud detraxit. -

-
- -
- - -
-

-
-

Widget Box 4

-
-

-
    -
  • Enum1
  • -
  • Enum2
  • -
  • Enum3
  • -
- -
- -
-
-``` diff --git a/frontend/src/global_styles/content/_wiki.lsg b/frontend/src/global_styles/content/_wiki.lsg deleted file mode 100644 index d8fbd25e410..00000000000 --- a/frontend/src/global_styles/content/_wiki.lsg +++ /dev/null @@ -1,358 +0,0 @@ -# Wiki - -Wiki-syntax is used for most textarea-fields within OpenProject. The users have several options to style text. - -## Container - -``` -
- -
-``` - -## Paragraph - -``` -
-

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit sed cum quam obcaecati eius nisi tenetur tempora odio minus nulla rerum hic, itaque nam dolorum vel fuga quibusdam, praesentium unde!

- -

Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

- -

Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.

- -

Right aligned - Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.

- -

Centered - Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.

-
-``` - -## Headings - -``` -
-

- Headline H1 - -

- -

- Headline H2 - -

- -

- Headline H3 - -

- -

- Headline H4 - -

- -
- Headline H5 -
- -
- Headline H6 -
-
-``` - -Note: Only headings to level ***three*** are supported in the wiki toolbar at the moment. Up to level ***four***, an anchor link is added. - -## Table of contents - -``` -
-
- - Table of Contents - -
- -
-
-
-``` - - -Note: Only headings to level ***four*** are considered in the table of contents. - - -## Font styles - -``` -
-

- Strong -

-

- Emphasis -

-

- Inserted -

-

- Deleted -

-

- StrongEmphasis -

-

- Bold -

-

- Italic -

-

- Citation -

-

- Superscript -

-

- Subscript -

-
-``` - -## Inline code - -``` -
- - function Y(f) { - var p = function(h) { - return function(x) { - return f(h(h))(x); - }; - }; - return p(p); - } - -
-``` - -## Preformatted Text - -``` -
-
-  This     is      very
-
-          formatted
-              text
-  
-
-``` - -## Unordered List - -``` -
- -
-``` - -## Ordered List - -``` -
-
    -
  1. Item
  2. -
  3. Item -
      -
    1. Subitem
    2. -
    3. SubItem -
        -
      1. Subsubitem
      2. -
      3. SubsubItem
      4. -
      5. SubsubItem
      6. -
      -
    4. -
    5. SubItem
    6. -
    -
  4. -
  5. Item
  6. -
-
-``` - -## Blockquote - -``` -
-
-

- The good news is that you're going to live. The bad news is that he is here to kill you. -

-
-
-``` - -## Link - -``` -
-

External link

-

Internal link

-

Wiki link

-

Version link

-

Message link

-

Project link

-

Changeset link

-

Attachment link

-

Source download link

-

Source link

-
-``` - -Links to work packages come in various alternatives: - -* only the ID - -``` -
-

#56

-
-``` - -* ID with a description - -``` -
-

Bug #56 on hold: Work Package link without description 2015-03-27 – 2015-04-30

-
-``` - -* ID with description, assignee and responsible and additionally parts of the description - -``` -
-

Bug #56 on hold: Work Package link with description 2015-03-27 – 2015-04-30

-
Responsible: Ulices Volkman
Assignee: Danika O'Keefe
-

Accedo asporto cicuta cribro canto totam molestias quis. Speculum arma desolo nam volo. Vorago explicabo aut arx. Adficio voluptates qui voluptas. Crur annus consequatur cedo vestrum comminor. Demum sollers bis arcesso dolores agnitio defaeco curso. Copia adversus via appono damno ut territo sed.

-
-``` - -## Image - -``` - - -
-

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit sed cum quam obcaecati eius nisi tenetur tempora odio minus nulla rerum hic, itaque nam dolorum vel fuga quibusdam, praesentium unde!

- -
- -
- -

Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

-
-``` - -## Table - -``` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse
molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet,
consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer
adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci
tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
-
-``` diff --git a/frontend/src/global_styles/content/work_packages/tabs/_activities.lsg b/frontend/src/global_styles/content/work_packages/tabs/_activities.lsg deleted file mode 100644 index a05beb038a1..00000000000 --- a/frontend/src/global_styles/content/work_packages/tabs/_activities.lsg +++ /dev/null @@ -1,389 +0,0 @@ -# Work Packages - [Details Pane] - Activities - -``` -
-
-

- March 19, 2014 - - Show activities with comments only - -

-
- Avatar - - OpenProject Admin - - - updated on - - 03/19/2014 - 4:38 PM - - -
- - #1 - -
- - -
-
-
- - - -
    -
  • - - Custom Integer - changed from - 12442234 - to - 34 - -
  • -
-
-
-
-
-

- April 30, 2014 -

-
- Avatar - - OpenProject Admin - - - updated on - - 04/30/2014 - 9:40 AM - - -
- - #2 - -
- - -
-
-
- - - -
    -
  • - - Type - changed from - Support - to - Bug - -
  • -
-
-
-
-
-

- July 11, 2014 -

-
- Avatar - - OpenProject Admin - - - updated on - - 07/11/2014 - 4:27 PM - - -
- - #3 - -
- - -
-
-
- - -

This is an example wiki text.

-
-
-
-
-
-
-
- Avatar - - OpenProject Admin - - - updated on - - 07/11/2014 - 4:27 PM - - -
- - #4 - -
- - -
-
-
- - - -
    -
  • - - Description - set (Details) - -
  • -
-
-
-
-
-

- August 21, 2014 -

-
- Avatar - - OpenProject Admin - - - updated on - - 08/21/2014 - 11:03 AM - - -
- - #5 - -
- - -
-
-
- - - -
    -
  • - - Parent - set to - molestias officia beatae aut et sunt ut labore - -
  • -
-
-
-
-
-
- Avatar - - OpenProject Admin - - - updated on - - 08/21/2014 - 11:05 AM - - -
- - #6 - -
- - -
-
-
- - - -
    -
  • - - Parent - deleted ( - molestias officia beatae aut et sunt ut labore - ) - -
  • -
-
-
-
-
-

- September 2, 2014 -

-
- Avatar - - OpenProject Admin - - - updated on - - 09/02/2014 - 8:50 AM - - -
- - #12 - -
- - -
-
-
- - - -
    -
  • - - Subject - changed from - Nothing important - to - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed felis metus, lobortis eget nisi id, scelerisque sagittis eros. Duis eget tempor risus, id sagittis nisi. In accumsan sapien sed scelerisque mattis. Sed bibendum condimentum magna eget vestibulum. Etiam bibendum, justo vitae efficitur placerat, justo lorem bibendum eros, et mattis diam diam eget urna. Aenean id magna pharetra, auctor dui ut, ultrices turpis. Duis eu massa non libero dictum vestibulum et consectetur diam. Sed varius nisl leo, vitae auctor velit imperdiet in. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse at odio lorem. In at iaculis dui, a convallis nibh. Vivamus rhoncus arcu quis purus euismod rutrum. Morbi a metus vitae metus finibus venenatis. - -
  • -
-
-
-
-
-
- Avatar - - OpenProject Admin - - - updated on - - 09/02/2014 - 8:51 AM - - -
- - #13 - -
- - -
-
-
- - - -
    -
  • - - Custom User - set to - Zena Labadie - -
  • -
  • - - Custom Description - changed from - QUAS - to - QUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUAS QUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUASQUAS - -
  • -
-
-
-
-
-

- September 12, 2014 -

-
- Avatar - - OpenProject Admin - - - updated on - - 09/12/2014 - 8:49 AM - - -
- - #14 - -
- - -
-
-
- - - -
    -
  • - - Description - changed (Details) - -
  • -
  • - - Assignee - set to - Deron Feil - -
  • -
  • - - Responsible - set to - Zena Labadie - -
  • -
-
-
-
-``` diff --git a/frontend/src/global_styles/fonts/_index.lsg b/frontend/src/global_styles/fonts/_index.lsg deleted file mode 100644 index 99cc225054f..00000000000 --- a/frontend/src/global_styles/fonts/_index.lsg +++ /dev/null @@ -1,8 +0,0 @@ -# Typography - -Typography is divided into content and UI, depending on where the styles are applied. - -Content refers to user generated information, such as wiki-syntax based entries, e.g. the description of a work package - -UI is everything relating to the application itself. - diff --git a/frontend/src/global_styles/fonts/_lato.lsg b/frontend/src/global_styles/fonts/_lato.lsg deleted file mode 100644 index eb0f71857ed..00000000000 --- a/frontend/src/global_styles/fonts/_lato.lsg +++ /dev/null @@ -1,20 +0,0 @@ -# Fonts - -## Lato - -*Lato* for headlines: - -~~~ -@font-example 32px Lato -ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ -~~~ - -*Lato* for normal/small text: - -~~~ -@font-example bold 14px Lato -~~~ - -~~~ -@font-example 14px Lato -~~~ diff --git a/frontend/src/global_styles/fonts/_openproject_icon_font.lsg b/frontend/src/global_styles/fonts/_openproject_icon_font.lsg deleted file mode 100644 index 8e538fb35df..00000000000 --- a/frontend/src/global_styles/fonts/_openproject_icon_font.lsg +++ /dev/null @@ -1,304 +0,0 @@ -## OpenProject Icon Font - -*OpenProject Icon Font* for icons: - - diff --git a/frontend/src/global_styles/layout/_index.sass b/frontend/src/global_styles/layout/_index.sass index 83a5a6a4891..f038ab076f3 100644 --- a/frontend/src/global_styles/layout/_index.sass +++ b/frontend/src/global_styles/layout/_index.sass @@ -48,3 +48,6 @@ // Print layout @import print + +// View component preview styles +@import viewcomponent_previews diff --git a/frontend/src/global_styles/layout/_toolbar.lsg b/frontend/src/global_styles/layout/_toolbar.lsg deleted file mode 100644 index daa8f28f23c..00000000000 --- a/frontend/src/global_styles/layout/_toolbar.lsg +++ /dev/null @@ -1,143 +0,0 @@ -# Toolbar - -A toolbar that can and should be used for actions on the current view. Initially designed for the Work package list, this can be reused throughout the application. - -## Standard Button Bar - -``` -@full-width -
-
-
-

Title of the page

-
- -
-
-``` - -## Toolbar with form elements - -``` -@full-width -
-
-
-

Dragonball Z characters

-
-
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - - - Add - -
  • -
-
-

now with extremely long subtitle: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste consequatur doloribus suscipit nemo temporibus deserunt alias incidunt doloremque officia rerum, nobis fuga, recusandae voluptatibus voluptatem tenetur repellendus itaque et. Eum.

-
-``` - -## Toolbar with affix form elements - -``` -@full-width -
-
-
-

Checkout information

-
-
    -
  • -
    - git clone -
    - -
  • -
  • - -
    - Read + Write -
    -
  • -
-
-
-``` - -## Toolbar with labelled form elements - -``` -@full-width -
-
-
-

Dragonball Z characters

-
-
    -
  • -
    - -
    - -
  • -
  • -
    - -
    - -
  • -
-
-

now with extremely long subtitle: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste consequatur doloribus suscipit nemo temporibus deserunt alias incidunt doloremque officia rerum, nobis fuga, recusandae voluptatibus voluptatem tenetur repellendus itaque et. Eum.

-
-``` diff --git a/frontend/src/global_styles/layout/_viewcomponent_previews.sass b/frontend/src/global_styles/layout/_viewcomponent_previews.sass new file mode 100644 index 00000000000..a403a62ca0c --- /dev/null +++ b/frontend/src/global_styles/layout/_viewcomponent_previews.sass @@ -0,0 +1,3 @@ +.viewcomponent-preview + &--content + margin: 1rem diff --git a/frontend/src/spot.scss b/frontend/src/spot.scss new file mode 100644 index 00000000000..d20d5913082 --- /dev/null +++ b/frontend/src/spot.scss @@ -0,0 +1,9 @@ +// SPOT variables +@import "src/assets/sass/_helpers.sass"; + +// Fonts +@import "src/global_styles/fonts/_index.sass"; + +// SPOT styles +@import "app/spot/styles/sass/common"; +@import "app/spot/styles/sass/components"; diff --git a/lib/open_project/patches/lookbook_tree_node_inflector.rb b/lib/open_project/patches/lookbook_tree_node_inflector.rb new file mode 100644 index 00000000000..4b77799bb5f --- /dev/null +++ b/lib/open_project/patches/lookbook_tree_node_inflector.rb @@ -0,0 +1,47 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2023 the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +module OpenProject + module Patches + ## + # Allow directory labels in lookbook to be inflected + module LookbookTreeNodeInflector + def label + return name if name == 'OpenProject' + + super + end + end + end +end + +if Rails.env.development? + OpenProject::Patches.patch_gem_version 'lookbook', '2.0.3' do + Lookbook::TreeNode.prepend OpenProject::Patches::LookbookTreeNodeInflector + end +end diff --git a/spec/components/docs/01-how-to-use.md.erb b/spec/components/docs/01-how-to-use.md.erb new file mode 100644 index 00000000000..63acef64e9a --- /dev/null +++ b/spec/components/docs/01-how-to-use.md.erb @@ -0,0 +1,24 @@ +--- +title: Using this resource +--- + +We use this lookbook to document the use and adaptation of the [Primer Design System](https://primer.style/) at [OpenProject](https://www.openproject.org). +You will find defined styles, components and patterns in the relevant sections. + +## Approach + +OpenProject is a complex, powerful tool. One of its key strengths is its customisability and its ability to adapt to a range of different needs. This includes complex filtering options, custom types and statuses, custom fields and a wide range of options to configure views and work package forms. + +Nevertheless, it is very important that OpenProject be intuitive for new users who might not necessarily need that complexity, or indeed be overwhelmed by it. + +Our design approach aims to strike the right balance between powerful and accessible with a two-tiered approach: apply sane defaults and present the most common options, and allow advanced users the option (via an additional click) to customise and fine-tune. + +## The UX of Open Source + +As an open source project with a considerably long history and a large number of contributors, different parts of OpenProject have evolved at different paces, sometimes with completely different technology. Similar components are sometimes implemented somewhat differently in different parts of the software, and there are even multiple implementations of the same basic design. + +This is quite normal for a large open-source project that has not had a dedicated design team for most of its conception. + +One of the goals of the design system is to introduce more coherence and introduce a more modern design language. Whilst we would naturally prefer to be able to update everything at the same time and push the new design system to the entire software, we recognise the need for a more pragmatic approach. The design system will be rolled out in phases, with a careful study of the consequences of updating each component or pattern, and the potential dependencies that will be affected. + +_We recognise that UI/UX has not always been the highest priority for open-source projects. This is somewhat understandable given how open source projects have relatively fewer design resources dedicated to it than commercial products. Our goal is to do our part to improve that situation as much as we can and document our process._ diff --git a/spec/components/docs/02-semantics.erb b/spec/components/docs/02-semantics.erb new file mode 100644 index 00000000000..fd970a4f7d1 --- /dev/null +++ b/spec/components/docs/02-semantics.erb @@ -0,0 +1,29 @@ +--- +title: Semantics +--- + +When describing components, we use certain words in very particular ways: + +### Disabled + +_Disabled_ is when no interaction is possible. A disabled element can itself have multiple states: a checkbox can be checked and disabled, a switch can be ON and disabled, a dropdown might have a value but but disabled. + +The opposite of disabled is _enabled_. All elements are described in their enabled state unless explicitly mentioned. + +### Focused and active + +Focus simply refers to when an element has the current object in DOM that has the input focus. In OpenProject, elements that are focused generally have a blue outline. + +The opposite of _in focus_ (or focused) is _not in focus_ (or focused). + +_Active_ is a similar state as focused, but not entirely the same. For example, in the date picker, the start date can be "active" (meaning that clicking on a date in the mini-calendar will change the start date) but not in focus (because the mouse has clicked outside of the field). + +The opposite of active is _inactive_. + +### Checked and on + +Checkboxes can be _checked_ (true) or _unchecked_ (false) + +Radio options can also be "checked" (as in, in a set of three options, only one can be checked) despite this not being the technically correct word. This isi to to distinguish it from "selected" (which refers to selecting an element or an area with the cursor). + +Switches can be _ON_ (true) or _OFF_ (false). diff --git a/spec/components/docs/styles/01-typography.md.erb b/spec/components/docs/styles/01-typography.md.erb new file mode 100644 index 00000000000..f6fade140af --- /dev/null +++ b/spec/components/docs/styles/01-typography.md.erb @@ -0,0 +1,195 @@ +--- +title: Typography +--- + +<%= include_spot_assets %> + +OpenProject uses the "[Lato Sans](https://github.com/latofonts/lato-source)" typeface created by Adam Twardoch, Botio Nikoltchev, and Łukasz Dziedzic (released with the [SIL Open Font license](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL)). + +There are 7 sizes, each with between three and eight variations. + +## Considerations + +A few things to keep in mind: + +### Black text + +“Black” text in OpenProject does not use the standard black HEX code (#000000); instead, black is defined as Grey-1 (#333333). + +### Line height + +The default line height is 16px, which corresponds to 1 REM with our Spacing baseline. + +For each style, line height is specified with a slash. For example, for Header Small Bold, 24/32 represents 1.5 REM font size and 2 REM line height. + +## Header Big + +This is a larger header than the default, used in rare occasions where a header is needed for a containing element to a page. To be used only if absolutely necessary. Prefer "Header small" as much as possible. + +So far, zero recorded use. Might get removed if this style is not used in until mid-2022. + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ + + +## Header Small + +This is the default type used for page headers. "Bold" is default and is almost always preferred, unless there is a need to use regular to distinguish additional or supporting information. + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ + + +## Subheader Big + +Very rarely used. Used if we need a header small than the regular header but still distinct from body text. + +So far, zero recorded use. Might get removed if this style is not used in until mid-2022. + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ + + +## Subheader Small + +Very rarely used. Used if we need a header small than the regular header but still distinct from body text. + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ + + +## Subheader Extra Small + +This is really an alias of _Body Small/Bold_ when this style is used as a header (in some modals) instead of body text. + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ + + +## Body Big + +Used occasionally (where?) + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ +## Body Small + +This is the default style for most text on OpenProject. This goes for labels but also input text. By far the most used style style in the application. + +The regular version is used, among other places, on: +- Button text +- Drop down select +- Text fields +- Table text +- Card: work package title +- Sidebar element + +The bold version is used in: + +- Table headers +- Calendar header +- Sidebar header + +**Example** + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ +## Caption + +The caption is used for indications and auxiliary information that usually adds context to a view, but are not primary elements. They are also used on elements where space is limited (like the date information on Team planner or Board cards). + +The regular version is used, among other places, in: + +- Chips +- Toast text +- Tooltips +- Card: project name and ID + +The bold version is used in: + +- Sidebar tabs + +**Example** + +
+

+ Aa +
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ +
+ abcdefghijklmnopqrstuvwxyz +
+ 0123456789 ! ? & / ( ) € $ £ ¥ ¢ = @ ; : , . +

+
+ diff --git a/spec/components/docs/styles/02-colors.md.erb b/spec/components/docs/styles/02-colors.md.erb new file mode 100644 index 00000000000..547e5416614 --- /dev/null +++ b/spec/components/docs/styles/02-colors.md.erb @@ -0,0 +1,237 @@ +--- +title: Colors +--- + +**Note**: This section concerns the OP colors in use, and is about to change/consolidated with Primer color modes + +Because OpenProject can be customised with custom colour schemes, our foundation library only describe the colour palette of the default OpenProject theme. + +Colours are organised in this format: **Category/_name_**. + +There there are six categories: + +- **Basic** +- **Main** +- **Accent** +- **Danger** +- **Indication** +- **Feedback** + +## Basic + +The basic colour set include eight shades of gray used mostly for basic text and backgrounds. The shades do not have additional semantic significance are are simply a continuum between **Basic/_Black_** and **Basic/_White_**. + +The choice of which gray to use depends on the colourspace. + +Note: **Basic/_Gray-1_** is the default colour for "black" text. Pure black (_Basic/Black_) is generally not used in OpenProject. + +> Code example here (Black, Gray-1, Gray-2, Gray-3, Gray-4, Gray-5, Gray-6, White) + +## Main + +The **Main/** colourset is a set of three shades of the OpenProject blue. + +**Main/_Main_** + +> Example + +This is the primary blue used for all main interactions and action buttons, including text links. + +It is also used in the background of the header. + +**Main/_Main Dark_** + +> Example + +This darker version of the main blue is mainly used: + +- to communicate state information (a hover or a pressed state of a button, for example) +- when the use of **Main/_Main_** does not provide enough contrast (for a border colour, for example) + +**Main/_Main Light_** + +> Example + +This lighter version of the main blue is used: + +- to communicate state information (hover on dop-down list or indicating selected toggle element, for example) +- as a background colour of interactive elements (tooltip, toast or information banners) + +## Accent + +> Example + +The **Accent/** colourset is a set of three shades of green that is used to accent certain special functions. This colour should be used sparingly, so that when it is used, it draws the user’s eye. + +**Accent/_Accent_** + +> Example + +This is the primary accent green, used for example in the default state of an accent button. + +**Accent/_Accent Dark_** + +> Example + +This darker version is mainly used: + +- to communicate state information (a hover or a pressed state of a button, for example) +- when the use of **Accent/Main** does not provide enough contrast (for a border colour, for example) + + +**Accent/_Accent Light_** + +> Example + +This lighter version of the main green is used: + +- to communicate state information (hover on dop-down list or indicating selected toggle element, for example) +- as a background colour of interactive elements (tooltip, toast or information banners) + +## Danger + +The **Danger/** colourset is a set of three shades of red used to communicate potential danger to the user, or to warn them of a problem. + +It should also be used to indicate potential destructive actions (actions like delete account or delete user) and exceptionally also used to indicate information (like in a notification badge) when the Indication/ colours cannot be used. + +**Danger/_Danger_** + +> Example + +This is the primary danger red, used for example in the default state of an accent button. + +**Danger/_Danger Dark_** + +> Example + +This darker version is mainly used: + +- to communicate state information (a hover or a pressed state of a button, for example) +- when the use of **Danger/Danger** does not provide enough contrast (for a border colour, for example) + +**Danger/_Danger Light_** + +> Example + +This darker version of the main danger red is used: + +- to communicate state information (hover on dop-down list or indicating selected toggle element, for example) +- as a background colour of interactive elements (tooltip, toast or information banners) + +## Indication + +Indication colours are used to indicate certain special states. + +**Indication/_Flagged_** + +> Example + +This colour is used when “flagging” work packages. It is a teal colour meant to be distinct from **Indication/_Attention_**. + +**Indication/_Current date_** + +> Example + +This colour is used to indicate the current date (today) in a calendar. + +**Indication/_Enterprise_** + +> Example + +This colour is used to indicate that a certain feature or module requires the Enterprise plan to use. + +**Indication/Focus** + +> Example + +This is the colour used to indicate which element has keyboard focus. + +## Feedback + +The **Feedback/**- colors are used to communicate for user feedback: + +- Error +- Warning +- Info +- Success + +Each of these has two versions (Dark and Light), the dark one usually used for the foreground text and icons and the light one for the background. + +These are typically used in toast messages. + +**Feedback/_Error_** + +> Example, Error Light and Dark + +This colour indicates that a response that is different from what the user would have expected. The user flow is usually interrupted when they see an error of this type. + +**Feedback/_Warning_** + +> Example, Warning Light and Dark + +The warning is information that suggests something requires attention (and that could cause a problem), but that no error has been caused, and that the expected user flow can continue. + +**Feedback/_Info_** + +> Example, Info Light and Dark + +This colour is used to indicate additional information that could be of interest to the user. (Like a toast that says “Loading...”, indicating something is happening in the background) + +**Feedback/_Success_** + +> Example, Success Light and Dark + +This colour indicates that the requested user action was successful. It should be used sparingly and only when such a feedback is absolutely required. + +
+ +<% +tokens = JSON.parse File.read(Rails.root.join('frontend/src/app/spot/styles/tokens/dist/tokens.json')) +tokens.select { |k, v| k.start_with?('spot-color-') }.each do |name, value| + %> + +
+
+
<%= name %>
+
<%= value %>
+
+<% end %> + +
+ + diff --git a/spec/components/docs/styles/03-focus.md.erb b/spec/components/docs/styles/03-focus.md.erb new file mode 100644 index 00000000000..6d0139ca20a --- /dev/null +++ b/spec/components/docs/styles/03-focus.md.erb @@ -0,0 +1,9 @@ +--- +title: Focus state +--- + +Focus state in OpenProject is represented by a 2-pixel outline with colour _Indication/Focus_ around the focused element. + +> Example of some elements with the focus state simulated + +**Note**: _Active_ is a similar state as focused, but not entirely the same. For example, in the date picker, the start date can be "active" (meaning that clicking on a date in the mini-calendar will change the start date) but not in focus (because the mouse pointer has clicked outside of the field and the focus is technically outside the field). diff --git a/spec/components/docs/styles/04-icons.md.erb b/spec/components/docs/styles/04-icons.md.erb new file mode 100644 index 00000000000..f2605ccea17 --- /dev/null +++ b/spec/components/docs/styles/04-icons.md.erb @@ -0,0 +1,102 @@ +--- +title: Icons +--- + +<%= include_spot_assets %> + +# Icons + +> Note: This page concerns OP icons and is about to be migrated to reference Primer icons + +Icons are used as visual indicators or small illustrations. They provide additional context when necessary. + + + + + + + +## Design notes + +Icons should generally not be used on its own without a label, especially on interactive elements, where their function might be ambiguous. + +There are notable examples: if the meaning of the button is abundantly clear without a label and space is limited (or repetitive elements), an icon-only interactive element is possible (for example, the "Mark as read" button on each notification element). + +However, icon-only buttons or links should never be used for critical primary functions like Save, Confirm, Remove and Delete. + +## Usage + +Icons are a CSS class only. To use them, apply the `spot-icon` BEM block on a generic inline element like `span`. + +## Options + +There are four pre-defined dimensions for icons: 12×12, 16×16, 20×20 and 24×24. + +The default size is 16×16. + + + + + This is a spot-link + + + +## Available icons + +<% +icons = JSON.parse File.read(Rails.root.join('frontend/src/app/spot/icon-font/icons.json')) +%> + +
+<% icons.each do |name| %> +
+
+ +
+
<%= name %>
+
+<% end %> +
+ + diff --git a/spec/components/previews/advanced_filters_preview.rb b/spec/components/previews/advanced_filters_preview.rb new file mode 100644 index 00000000000..ca95982c69e --- /dev/null +++ b/spec/components/previews/advanced_filters_preview.rb @@ -0,0 +1,4 @@ +# @logical_path OpenProject +class AdvancedFiltersPreview < Lookbook::Preview + def default; end +end diff --git a/frontend/src/global_styles/content/_advanced_filters.lsg b/spec/components/previews/advanced_filters_preview/default.html.erb similarity index 97% rename from frontend/src/global_styles/content/_advanced_filters.lsg rename to spec/components/previews/advanced_filters_preview/default.html.erb index d44da69818e..081891fa21e 100644 --- a/frontend/src/global_styles/content/_advanced_filters.lsg +++ b/spec/components/previews/advanced_filters_preview/default.html.erb @@ -1,8 +1,3 @@ -# Advanced filters - -``` -@full-width -
Selected filters
    @@ -121,7 +116,7 @@
- +
@@ -150,7 +145,7 @@
- +
@@ -340,4 +335,3 @@ -``` diff --git a/spec/components/previews/toolbar_component_preview.rb b/spec/components/previews/toolbar_component_preview.rb new file mode 100644 index 00000000000..e0b04266598 --- /dev/null +++ b/spec/components/previews/toolbar_component_preview.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# @logical_path OpenProject +class ToolbarComponentPreview < Lookbook::Preview + # A toolbar that can and should be used for actions on the current view. + # Initially designed for the Work package list, this can be reused throughout the application. + def default; end + + def with_form_elements; end + + def with_labelled_form_elements; end +end diff --git a/spec/components/previews/toolbar_component_preview/default.html.erb b/spec/components/previews/toolbar_component_preview/default.html.erb new file mode 100644 index 00000000000..635b2c7cb56 --- /dev/null +++ b/spec/components/previews/toolbar_component_preview/default.html.erb @@ -0,0 +1,21 @@ +
+
+
+

Title of the page

+
+ +
+
diff --git a/spec/components/previews/toolbar_component_preview/with_form_elements.html.erb b/spec/components/previews/toolbar_component_preview/with_form_elements.html.erb new file mode 100644 index 00000000000..d206baf2600 --- /dev/null +++ b/spec/components/previews/toolbar_component_preview/with_form_elements.html.erb @@ -0,0 +1,38 @@ +
+
+
+

Dragonball Z characters

+
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + + + Add + +
  • +
+
+

now with extremely long subtitle: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste consequatur doloribus suscipit nemo temporibus deserunt alias incidunt doloremque officia rerum, nobis fuga, recusandae voluptatibus voluptatem tenetur repellendus itaque et. Eum.

+
diff --git a/spec/components/previews/toolbar_component_preview/with_labelled_form_elements.html.erb b/spec/components/previews/toolbar_component_preview/with_labelled_form_elements.html.erb new file mode 100644 index 00000000000..982dd29c8c1 --- /dev/null +++ b/spec/components/previews/toolbar_component_preview/with_labelled_form_elements.html.erb @@ -0,0 +1,36 @@ +
+
+
+

Dragonball Z characters

+
+
    +
  • +
    + +
    + +
  • +
  • +
    + +
    + +
  • +
+
+

now with extremely long subtitle: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste consequatur doloribus suscipit nemo temporibus deserunt alias incidunt doloremque officia rerum, nobis fuga, recusandae voluptatibus voluptatem tenetur repellendus itaque et. Eum.

+
diff --git a/spec/components/previews/tooltip_component_preview/default.html.erb b/spec/components/previews/tooltip_component_preview/default.html.erb new file mode 100644 index 00000000000..493fa633b41 --- /dev/null +++ b/spec/components/previews/tooltip_component_preview/default.html.erb @@ -0,0 +1,11 @@ +<%= render TooltipComponent.new do |component| %> + <% component.with_trigger do %> + Hover me to see the tooltip + <% end %> + + <% component.with_body do %> + + Content of the tooltip + + <% end %> +<% end %> diff --git a/spec/components/previews/widget_component_preview.rb b/spec/components/previews/widget_component_preview.rb new file mode 100644 index 00000000000..a2f6238a21b --- /dev/null +++ b/spec/components/previews/widget_component_preview.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# @logical_path OpenProject +# @label Widget boxes +class WidgetComponentPreview < Lookbook::Preview + def default; end +end diff --git a/spec/components/previews/widget_component_preview/default.html.erb b/spec/components/previews/widget_component_preview/default.html.erb new file mode 100644 index 00000000000..9970042f875 --- /dev/null +++ b/spec/components/previews/widget_component_preview/default.html.erb @@ -0,0 +1,100 @@ +
+ + +
+

+
+

Widget Box

+
+

+

This widget box can be used to display content belonging to one subject.

+ +
+ + +
+

+
+

Widget Box 2

+
+

+ +
+ + +
+

+
+

Widget Box 3

+
+

+
+

+ Lorem ipsum dolor sit amet, his ei propriae suscipit. + Sit in atqui accumsan ponderum, eum ut luptatum lobortis, has ei tota illud detraxit. +

+
+ +
+ + +
+

+
+

Widget Box 4

+
+

+
    +
  • Enum1
  • +
  • Enum2
  • +
  • Enum3
  • +
+ +
+ +
diff --git a/spec/models/work_packages/pdf_export/work_package_list_to_pdf_spec.rb b/spec/models/work_packages/pdf_export/work_package_list_to_pdf_spec.rb deleted file mode 100644 index 8c4c5e5275f..00000000000 --- a/spec/models/work_packages/pdf_export/work_package_list_to_pdf_spec.rb +++ /dev/null @@ -1,227 +0,0 @@ -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) 2012-2023 the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -require 'spec_helper' - -RSpec.describe WorkPackage::PDFExport::WorkPackageListToPdf do - include Redmine::I18n - include PDFExportSpecUtils - let(:type_standard) { create(:type_standard) } - let(:type_bug) { create(:type_bug) } - let(:project) { create(:project, name: 'Foo Bla. Report No. 4/2021 with/for Case 42', types: [type_standard, type_bug]) } - let(:user) do - create(:user, - member_in_project: project, - member_with_permissions: %w[view_work_packages export_work_packages]) - end - let(:export_time) { DateTime.new(2023, 6, 30, 23, 59) } - let(:export_time_formatted) { format_time(export_time, true) } - let(:work_package_parent) do - create(:work_package, - project:, - type: type_standard, - subject: 'Work package 1', - story_points: 1, - description: 'This is a description') - end - let(:work_package_child) do - create(:work_package, - project:, - parent: work_package_parent, - type: type_bug, - subject: 'Work package 2', - story_points: 2, - description: 'This is work package 2') - end - let(:work_packages) do - [work_package_parent, work_package_child] - end - let(:query_attributes) { {} } - let!(:query) do - build(:query, user:, project:, **query_attributes).tap do |q| - q.column_names = column_names - q.sort_criteria = [%w[id asc]] - end - end - let(:column_titles) { column_names.map { |name| column_title(name) } } - let(:options) { {} } - let(:export) do - login_as(user) - work_packages - described_class.new(query, options) - end - let(:export_pdf) do - Timecop.freeze(export_time) do - export.export! - end - end - let(:column_names) { %i[id subject status story_points] } - - def work_packages_sum - work_package_parent.story_points + work_package_child.story_points - end - - def work_package_columns(work_package) - [work_package.id.to_s, work_package.subject, work_package.status.name, work_package.story_points.to_s] - end - - def work_package_details(work_package, index) - ["#{index}.", work_package.subject, - column_title(:id), work_package.id.to_s, - column_title(:status), work_package.status.name, - column_title(:story_points), work_package.story_points.to_s, - label_title(:description), work_package.description] - end - - subject(:pdf) do - PDF::Inspector::Text.analyze(File.read(export_pdf.content.path)) - end - - describe 'with a request for a PDF table' do - it 'contains correct data' do - expect(pdf.strings).to eq([ - query.name, - *column_titles, - *work_package_columns(work_package_parent), - *work_package_columns(work_package_child), - '1/1', export_time_formatted, query.name - ]) - end - end - - describe 'with a request for a PDF table grouped' do - let(:query_attributes) { { group_by: 'type' } } - - it 'contains correct data' do - expect(pdf.strings).to eq([ - query.name, - work_package_parent.type.name, - *column_titles, - *work_package_columns(work_package_parent), - work_package_child.type.name, - *column_titles, - *work_package_columns(work_package_child), - '1/1', export_time_formatted, query.name - ]) - end - end - - describe 'with a request for a PDF table grouped with sums' do - let(:query_attributes) { { group_by: 'type', display_sums: true } } - - it 'contains correct data' do - expect(pdf.strings).to eq([ - query.name, - work_package_parent.type.name, - *column_titles, - *work_package_columns(work_package_parent), - I18n.t('js.label_sum'), work_package_parent.story_points.to_s, - work_package_child.type.name, - *column_titles, - *work_package_columns(work_package_child), - I18n.t('js.label_sum'), work_package_child.story_points.to_s, - '1/1', export_time_formatted, query.name - ]) - end - end - - describe 'with a request for a PDF Report' do - let(:options) { { show_report: true } } - - it 'contains correct data' do - expect(pdf.strings).to eq([ - query.name, - '1.', '2', work_package_parent.subject, - '2.', '2', work_package_child.subject, - '1/2', export_time_formatted, query.name, - *work_package_details(work_package_parent, "1"), - *work_package_details(work_package_child, "2"), - '2/2', export_time_formatted, query.name - ]) - end - end - - describe 'with a request for a PDF Report with hierarchies' do - let(:options) { { show_report: true } } - let(:query_attributes) { { show_hierarchies: true } } - - it 'contains correct data' do - expect(pdf.strings).to eq([ - query.name, - '1.', '2', work_package_parent.subject, - '1.1.', '2', work_package_child.subject, - '1/2', export_time_formatted, query.name, - *work_package_details(work_package_parent, '1'), - *work_package_details(work_package_child, '1.1'), - '2/2', export_time_formatted, query.name - ]) - end - end - - describe 'with a request for a PDF Report with sums' do - let(:options) { { show_report: true } } - let(:query_attributes) { { display_sums: true } } - - it 'contains correct data' do - expect(pdf.strings).to eq([ - query.name, - '1.', '2', work_package_parent.subject, - '2.', '2', work_package_child.subject, - '1/2', export_time_formatted, query.name, - I18n.t('js.work_packages.tabs.overview'), - column_title(:story_points), - I18n.t('js.label_sum'), work_packages_sum.to_s, - *work_package_details(work_package_parent, "1"), - *work_package_details(work_package_child, "2"), - '2/2', export_time_formatted, query.name - ]) - end - end - - describe 'with a request for a PDF Report grouped with sums' do - let(:options) { { show_report: true } } - let(:query_attributes) { { display_sums: true, group_by: 'type' } } - - it 'contains correct data' do - expect(pdf.strings).to eq([ - query.name, - '1.', '2', work_package_parent.subject, - '2.', '2', work_package_child.subject, - '1/2', export_time_formatted, query.name, - I18n.t('js.work_packages.tabs.overview'), - column_title(:type), column_title(:story_points), - work_package_parent.type.name, work_package_parent.story_points.to_s, - work_package_child.type.name, work_package_child.story_points.to_s, - I18n.t('js.label_sum'), work_packages_sum.to_s, - *work_package_details(work_package_parent, "1"), - *work_package_details(work_package_child, "2"), - '2/2', export_time_formatted, query.name - ]) - end - end -end diff --git a/spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb b/spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb deleted file mode 100644 index 15541fb6439..00000000000 --- a/spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb +++ /dev/null @@ -1,112 +0,0 @@ -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) 2012-2023 the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -require 'spec_helper' - -RSpec.describe WorkPackage::PDFExport::WorkPackageToPdf do - include Redmine::I18n - include PDFExportSpecUtils - let(:type) { create(:type_bug) } - let(:project) { create(:project, name: 'Foo Bla. Report No. 4/2021 with/for Case 42', types: [type]) } - let(:user) do - create(:user, - member_in_project: project, - member_with_permissions: %w[view_work_packages export_work_packages]) - end - let(:export_time) { DateTime.new(2023, 6, 30, 23, 59) } - let(:export_time_formatted) { format_time(export_time, true) } - let(:image_path) { Rails.root.join("spec/fixtures/files/image.png") } - let(:image_attachment) { Attachment.new author: user, file: File.open(image_path) } - let(:attachments) { [image_attachment] } - let(:work_package) do - description = <<~DESCRIPTION - **Lorem** _ipsum_ ~~dolor~~ `sit` [amet](https://example.com/), consetetur sadipscing elitr. - @OpenProject Admin - ![](/api/v3/attachments/#{image_attachment.id}/content) -

-

-
- "foobar" -
-
Image Caption
-
-

-

Foo

- DESCRIPTION - create(:work_package, - project:, - type:, - subject: 'Work package 1', - story_points: 1, - description:).tap do |wp| - allow(wp) - .to receive(:attachments) - .and_return attachments - end - end - let(:options) { {} } - let(:export) do - login_as(user) - described_class.new(work_package, options) - end - let(:export_pdf) do - Timecop.freeze(export_time) do - export.export! - end - end - - subject(:pdf) do - content = export_pdf.content - # File.binwrite('WorkPackageToPdf-test-preview.pdf', content) - { strings: PDF::Inspector::Text.analyze(content).strings, - images: PDF::Inspector::XObject.analyze(content).page_xobjects.flat_map do |o| - o.values.select { |v| v.hash[:Subtype] == :Image } - end } - end - - describe 'with a request for a PDF' do - it 'contains correct data' do - expect(pdf[:strings]).to eq([ - "#{type.name} ##{work_package.id} - #{work_package.subject}", - column_title(:id), work_package.id.to_s, - column_title(:updated_at), export_time_formatted, - column_title(:type), type.name, - column_title(:created_at), export_time_formatted, - column_title(:status), work_package.status.name, - column_title(:priority), work_package.priority.name, - label_title(:description), - 'Lorem', ' ', 'ipsum', ' ', 'dolor', ' ', 'sit', ' ', - 'amet', ', consetetur sadipscing elitr.', ' ', '@OpenProject Admin', - 'Image Caption', - 'Foo', - '1', export_time_formatted, project.name - ]) - expect(pdf[:images].length).to eq(2) - end - end -end diff --git a/spec/support/work_packages/pdf_export.rb b/spec/support/work_packages/pdf_export.rb deleted file mode 100644 index 2d7c266098b..00000000000 --- a/spec/support/work_packages/pdf_export.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' -require 'pdf/inspector' - -module PDFExportSpecUtils - def column_title(column_name) - label_title(column_name).upcase - end - - def label_title(column_name) - WorkPackage.human_attribute_name(column_name) - end -end