card-mod-layout 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/card/layout.rb +93 -0
- data/lib/card/layout/card_layout.rb +42 -0
- data/lib/card/layout/code_layout.rb +9 -0
- data/lib/card/layout/proc_layout.rb +9 -0
- data/lib/card/layout/unknown_layout.rb +20 -0
- data/set/abstract/account_dropdown.rb +25 -0
- data/set/abstract/pointer/html_views.rb +5 -0
- data/set/all/alert.rb +23 -0
- data/set/all/layouts.rb +34 -0
- data/set/all/modal.rb +119 -0
- data/set/all/modal/modal_dialog.haml +12 -0
- data/set/all/navbar_links.rb +68 -0
- data/set/all/overlay.rb +104 -0
- data/set/all/overlay/overlay_header.haml +0 -0
- data/set/all/process_layout.rb +77 -0
- data/set/all/tabs.rb +51 -0
- data/set/right/enabled_roles.rb +61 -0
- data/set/right/enabled_roles/role_checkbox.haml +4 -0
- data/set/right/head.rb +17 -0
- data/set/self/account_links.rb +99 -0
- data/set/self/alerts.rb +5 -0
- data/set/self/dropdown_divider.rb +9 -0
- data/set/self/foot.rb +6 -0
- data/set/self/head.rb +26 -0
- data/set/self/layout.rb +3 -0
- data/set/self/navbox.rb +33 -0
- data/set/self/sidebar.rb +5 -0
- data/set/type/html.rb +14 -0
- data/set/type/layout_type.rb +16 -0
- metadata +117 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: 88a1f8fda8a7de79162a23970453a1d65fa854e5756bf2440097b6f8e095105f
         | 
| 4 | 
            +
              data.tar.gz: 74e33218406078b293233db999cecf6c05e0c978a22cf160b21073cb152e684d
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 0cfe4f2e146fb804b486a603eac29d7bf19443e16642e08c1b94d0d9531e7527e97159cfbd6a82f7e8ecb568d3e479d6fdedb93ef6f609b1ae4e3c1aca57009a
         | 
| 7 | 
            +
              data.tar.gz: 98df05daff1504932be99d4e439d862c6f1fa7d87e3104968202edf39203bf846c443b47443ff19c1efce17897eb7653660729e4b336eeeacc5f684ab0445d23
         | 
    
        data/lib/card/layout.rb
    ADDED
    
    | @@ -0,0 +1,93 @@ | |
| 1 | 
            +
            class Card
         | 
| 2 | 
            +
              class Layout
         | 
| 3 | 
            +
                class << self
         | 
| 4 | 
            +
                  def render layout, format
         | 
| 5 | 
            +
                    layout_class(layout).new(layout, format).render
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def layout_class layout
         | 
| 9 | 
            +
                    if layout.respond_to? :call
         | 
| 10 | 
            +
                      Card::Layout::ProcLayout
         | 
| 11 | 
            +
                    elsif card_layout? layout
         | 
| 12 | 
            +
                      Card::Layout::CardLayout
         | 
| 13 | 
            +
                    elsif code_layout? layout
         | 
| 14 | 
            +
                      Card::Layout::CodeLayout
         | 
| 15 | 
            +
                    else
         | 
| 16 | 
            +
                      Card::Layout::UnknownLayout
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def card_layout? name
         | 
| 21 | 
            +
                    Card.fetch_type_id(name).in? [Card::LayoutTypeID, Card::HtmlID, Card::BasicID]
         | 
| 22 | 
            +
                  rescue ArgumentError, Card::Error::CodenameNotFound => _e
         | 
| 23 | 
            +
                    false
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def code_layout? name
         | 
| 27 | 
            +
                    built_in_layouts_hash.key? name.to_sym
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def register_layout new_layout
         | 
| 31 | 
            +
                    key = layout_key new_layout
         | 
| 32 | 
            +
                    return if layouts[key]
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    layouts[key] = block_given? ? yield : {}
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def deregister_layout layout_name
         | 
| 38 | 
            +
                    layouts.delete layout_key(layout_name)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def layout_key name
         | 
| 42 | 
            +
                    return name if name.is_a? Symbol
         | 
| 43 | 
            +
                    name.to_name.key.to_sym
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def register_built_in_layout new_layout, opts
         | 
| 47 | 
            +
                    register_layout(new_layout) { opts.present? ? opts : nil }
         | 
| 48 | 
            +
                    built_in_layouts_hash[new_layout] = true
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def built_in_layouts_hash
         | 
| 52 | 
            +
                    @built_in_layouts ||= {}
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  def built_in_layouts
         | 
| 56 | 
            +
                    built_in_layouts_hash.keys
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  def layouts
         | 
| 60 | 
            +
                    @layouts ||= {}
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  def clear_cache
         | 
| 64 | 
            +
                    @built_in_layouts = @layouts = nil
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def main_nest_opts layout_name, format
         | 
| 68 | 
            +
                    key = layout_key layout_name
         | 
| 69 | 
            +
                    opts = layouts[key] || register_layout_with_nest(layout_name, format)
         | 
| 70 | 
            +
                    opts.clone
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  def register_layout_with_nest layout_name, format
         | 
| 74 | 
            +
                    register_layout(layout_name) do
         | 
| 75 | 
            +
                      layout_class(layout_name).new(layout_name, format).fetch_main_nest_opts
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                def initialize layout, format
         | 
| 81 | 
            +
                  @layout = layout
         | 
| 82 | 
            +
                  @format = format
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                def fetch_main_nest_opts
         | 
| 86 | 
            +
                  {}
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                def main_nest_opts
         | 
| 90 | 
            +
                  self.class.main_nest_opts @layout, @format
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
            end
         | 
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            class Card
         | 
| 2 | 
            +
              class Layout
         | 
| 3 | 
            +
                # Layout based on a card's content
         | 
| 4 | 
            +
                class CardLayout < Layout
         | 
| 5 | 
            +
                  def layout_card
         | 
| 6 | 
            +
                    @layout_card ||= Card.quick_fetch @layout
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def render
         | 
| 10 | 
            +
                    @format.process_content layout_card.content, chunk_list: :references
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def fetch_main_nest_opts
         | 
| 14 | 
            +
                    find_main_nest_chunk&.options ||
         | 
| 15 | 
            +
                      raise(Card::Error, "no main nest found in layout \"#{@layout}\"")
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  MAIN_NESTING_LIMIT = 5
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def find_main_nest_chunk card=layout_card, depth=0
         | 
| 21 | 
            +
                    content = Card::Content.new(card.content, @format, chunk_list: :nest_only)
         | 
| 22 | 
            +
                    return unless content.each_chunk.count.positive?
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    main_chunk(content) || go_deeper(content, depth)
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def go_deeper content, depth
         | 
| 28 | 
            +
                    return if depth > MAIN_NESTING_LIMIT
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    content.each_chunk do |chunk|
         | 
| 31 | 
            +
                      main_chunk = find_main_nest_chunk chunk.referee_card, depth + 1
         | 
| 32 | 
            +
                      return main_chunk if main_chunk
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                    nil
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def main_chunk content
         | 
| 38 | 
            +
                    content.each_chunk.find(&:main?)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            class Card
         | 
| 2 | 
            +
              class Layout
         | 
| 3 | 
            +
                class UnknownLayout < Layout
         | 
| 4 | 
            +
                  SCOPE = "mod.core.format.html_format".freeze
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def render
         | 
| 7 | 
            +
                    @format.output [header, text]
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def header
         | 
| 11 | 
            +
                    @format.content_tag(:h1, @format.tr(:unknown_layout, scope: SCOPE, name: @layout))
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def text
         | 
| 15 | 
            +
                    @format.tr(:available_layouts, scope: SCOPE,
         | 
| 16 | 
            +
                                                   available_layouts: self.class.built_in_layouts)
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              def link_to_mycard
         | 
| 3 | 
            +
                link_to_card Auth.current.name, nil,
         | 
| 4 | 
            +
                             id: "my-card-link", class: "nav-link #{classy('my-card')}"
         | 
| 5 | 
            +
              end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              def account_dropdown &render_role_item
         | 
| 8 | 
            +
                split_button link_to_mycard, nil do
         | 
| 9 | 
            +
                  [
         | 
| 10 | 
            +
                    link_to_card([Auth.current, :account_settings], "Account"),
         | 
| 11 | 
            +
                    (["Roles", role_items(&render_role_item)] if special_roles?)
         | 
| 12 | 
            +
                  ]
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def special_roles?
         | 
| 17 | 
            +
                Auth.current_roles.size > 1
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def role_items
         | 
| 21 | 
            +
                Auth.current_roles.map do |role_name|
         | 
| 22 | 
            +
                  yield role_name
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
    
        data/set/all/alert.rb
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              # alert_types: 'success', 'info', 'warning', 'danger'
         | 
| 3 | 
            +
              def alert alert_type, dismissable=false, disappear=false, args={}
         | 
| 4 | 
            +
                add_class args, alert_classes(alert_type, dismissable, disappear)
         | 
| 5 | 
            +
                wrap_with :div, args.merge(role: "alert") do
         | 
| 6 | 
            +
                  [(alert_close_button if dismissable), output(yield)]
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def alert_classes alert_type, dismissable, disappear
         | 
| 11 | 
            +
                classes = ["alert", "alert-#{alert_type}"]
         | 
| 12 | 
            +
                classes << "alert-dismissible " if dismissable
         | 
| 13 | 
            +
                classes << "_disappear" if disappear
         | 
| 14 | 
            +
                classy classes
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def alert_close_button
         | 
| 18 | 
            +
                wrap_with :button, type: "button", "data-dismiss": "alert",
         | 
| 19 | 
            +
                                   class: "close", "aria-label": "Close" do
         | 
| 20 | 
            +
                  wrap_with :span, "×", "aria-hidden" => true
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
    
        data/set/all/layouts.rb
    ADDED
    
    | @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              attr_reader :interior
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              def layout_nest
         | 
| 5 | 
            +
                wrap_main { interior }
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              layout :pre do  # {{_main|raw}}
         | 
| 9 | 
            +
                wrap_with :pre do
         | 
| 10 | 
            +
                  layout_nest
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              layout :simple do
         | 
| 15 | 
            +
                layout_nest
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              layout :no_side do # {{_main|open}}
         | 
| 19 | 
            +
                <<-HTML.strip_heredoc
         | 
| 20 | 
            +
                  <header>#{nest :header, view: :core}</header>
         | 
| 21 | 
            +
                  <article>#{layout_nest}</article>
         | 
| 22 | 
            +
                  <footer>{nest :footer, view: :core}</footer>
         | 
| 23 | 
            +
                HTML
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              layout :default do
         | 
| 27 | 
            +
                <<-HTML.strip_heredoc
         | 
| 28 | 
            +
                  <header>#{nest :header, view: :core}</header>
         | 
| 29 | 
            +
                  <article>#{layout_nest}</article>
         | 
| 30 | 
            +
                  <aside>#{nest :sidebar, view: :core}</aside>
         | 
| 31 | 
            +
                  <footer>{nest :footer, view: :core}</footer>
         | 
| 32 | 
            +
                HTML
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
    
        data/set/all/modal.rb
    ADDED
    
    | @@ -0,0 +1,119 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              MODAL_SIZE = { small: "sm", medium: nil, large: "lg", full: "full" }.freeze
         | 
| 3 | 
            +
              MODAL_CLOSE_OPTS = { "data-dismiss": "modal",
         | 
| 4 | 
            +
                                   "data-cy": "close-modal" }.freeze
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              wrapper :modal do |opts={}|
         | 
| 7 | 
            +
                haml :modal_dialog, body: interior,
         | 
| 8 | 
            +
                                    classes: modal_dialog_classes(opts),
         | 
| 9 | 
            +
                                    title: normalize_modal_option(:title, opts),
         | 
| 10 | 
            +
                                    menu: normalize_modal_option(:menu, opts),
         | 
| 11 | 
            +
                                    footer: normalize_modal_option(:footer, opts)
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def normalize_modal_option key, opts
         | 
| 15 | 
            +
                val = opts[key]
         | 
| 16 | 
            +
                return render("modal_#{key}") unless val
         | 
| 17 | 
            +
                cast_model_option val
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def cast_model_option val
         | 
| 21 | 
            +
                case val
         | 
| 22 | 
            +
                when Symbol
         | 
| 23 | 
            +
                  cast_model_option_symbol val
         | 
| 24 | 
            +
                when Proc
         | 
| 25 | 
            +
                  val.call(self)
         | 
| 26 | 
            +
                else
         | 
| 27 | 
            +
                  val
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              def cast_model_option_symbol val
         | 
| 32 | 
            +
                respond_to?(val) ? send(val) : val
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              view :modal, wrap: :modal do
         | 
| 36 | 
            +
                ""
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              def show_in_modal_link link_text, body
         | 
| 40 | 
            +
                link_to_view :modal, link_text, "data-modal-body": body, "data-slotter-mode": "modal"
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def modal_close_button link_text="Close", opts={}
         | 
| 44 | 
            +
                classes = opts.delete(:class)
         | 
| 45 | 
            +
                button_opts = opts.merge(MODAL_CLOSE_OPTS)
         | 
| 46 | 
            +
                add_class button_opts, classes if classes
         | 
| 47 | 
            +
                button_tag link_text, button_opts
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              def modal_submit_button opts={}
         | 
| 51 | 
            +
                add_class opts, "submit-button _close-modal"
         | 
| 52 | 
            +
                submit_button opts
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              view :modal_menu, unknown: true, wrap: :modal_menu do
         | 
| 56 | 
            +
                [close_modal_window, pop_out_modal_window]
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              wrapper :modal_menu, :div, class: "modal-menu ml-auto"
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              view :modal_title, unknown: true do
         | 
| 62 | 
            +
                ""
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              view :modal_footer, unknown: true do
         | 
| 66 | 
            +
                button_tag "Close",
         | 
| 67 | 
            +
                           class: "btn-xs _close-modal float-right",
         | 
| 68 | 
            +
                           "data-dismiss" => "modal"
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              view :modal_link do
         | 
| 72 | 
            +
                modal_link _render_title, size: voo.size
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              def modal_link text=nil, opts={}
         | 
| 76 | 
            +
                opts = modal_link_opts(opts)
         | 
| 77 | 
            +
                opts[:path][:layout] ||= :modal
         | 
| 78 | 
            +
                link_to text, opts
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              def modal_link_opts opts
         | 
| 82 | 
            +
                add_class opts, "slotter"
         | 
| 83 | 
            +
                opts.reverse_merge! path: {},
         | 
| 84 | 
            +
                                    "data-slotter-mode": "modal",
         | 
| 85 | 
            +
                                    "data-modal-class": modal_dialog_classes(opts),
         | 
| 86 | 
            +
                                    remote: true
         | 
| 87 | 
            +
                opts
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              def modal_dialog_classes opts
         | 
| 91 | 
            +
                classes = [classy("modal-dialog")]
         | 
| 92 | 
            +
                return classes unless opts.present?
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                add_modal_size_class classes, opts[:size]
         | 
| 95 | 
            +
                classes << "modal-dialog-centered" if opts[:vertically_centered]
         | 
| 96 | 
            +
                classes.join " "
         | 
| 97 | 
            +
              end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
              def add_modal_size_class classes, size
         | 
| 100 | 
            +
                size = normalize_modal_size_class size
         | 
| 101 | 
            +
                return if size == :medium || size.blank?
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                classes << "modal-#{MODAL_SIZE[size]}"
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
              def normalize_modal_size_class size
         | 
| 107 | 
            +
                size.in?(MODAL_SIZE.keys) ? size : cast_model_option(size)
         | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
              def close_modal_window
         | 
| 111 | 
            +
                link_to icon_tag(:close), path: "",
         | 
| 112 | 
            +
                                          class: "_close-modal close",
         | 
| 113 | 
            +
                                          "data-dismiss": "modal"
         | 
| 114 | 
            +
              end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
              def pop_out_modal_window
         | 
| 117 | 
            +
                link_to icon_tag(:new_window), path: {}, class: "pop-out-modal close"
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
            end
         | 
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            #modal-container.modal.fade._modal-slot{role: "dialog", "data-backdrop": "static"}
         | 
| 2 | 
            +
              -# .modal-dialog
         | 
| 3 | 
            +
              %div{class: classes}
         | 
| 4 | 
            +
                .modal-content
         | 
| 5 | 
            +
                  .modal-header.clearfix
         | 
| 6 | 
            +
                    = title
         | 
| 7 | 
            +
                    = menu
         | 
| 8 | 
            +
                  .modal-body
         | 
| 9 | 
            +
                    = body
         | 
| 10 | 
            +
                  - if footer.present?
         | 
| 11 | 
            +
                    .modal-footer
         | 
| 12 | 
            +
                      = footer
         | 
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              view :navbar_links, perms: :none do
         | 
| 3 | 
            +
                wrap_with :ul, class: "navbar-nav" do
         | 
| 4 | 
            +
                  navbar_items
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              # Iterates over all nests and links and renders them as bootstrap navbar items.
         | 
| 9 | 
            +
              # Items that are pointer cards become dropdowns
         | 
| 10 | 
            +
              def navbar_items view: :nav_item, link_class: "nav-link"
         | 
| 11 | 
            +
                process_content nil, chunk_list: :references do |chunk|
         | 
| 12 | 
            +
                  case chunk
         | 
| 13 | 
            +
                  when Card::Content::Chunk::Link
         | 
| 14 | 
            +
                    navbar_link_chunk chunk, view, link_class
         | 
| 15 | 
            +
                  when Card::Content::Chunk::Nest
         | 
| 16 | 
            +
                    navbar_nest_chunk chunk, view
         | 
| 17 | 
            +
                  else
         | 
| 18 | 
            +
                    chunk.process_chunk
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              # overridden in Abstact::Pointer to render dropdown
         | 
| 24 | 
            +
              view :nav_item do
         | 
| 25 | 
            +
                wrap_with_nav_item link_view(class: "nav-link")
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def wrap_with_nav_item content
         | 
| 29 | 
            +
                wrap_with(:li, content, class: "nav-item")
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              view :nav_link_in_dropdown do
         | 
| 33 | 
            +
                link_to_card card, render_title, class: "dropdown-item"
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def nav_dropdown
         | 
| 37 | 
            +
                wrap_with(:li, class: "nav-item dropdown") do
         | 
| 38 | 
            +
                  [
         | 
| 39 | 
            +
                    dropdown_toggle_link,
         | 
| 40 | 
            +
                    dropdown_menu
         | 
| 41 | 
            +
                  ]
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def dropdown_toggle_link
         | 
| 46 | 
            +
                link_to(render_title, href: "#", class: "nav-link dropdown-toggle",
         | 
| 47 | 
            +
                                      "data-toggle": "dropdown")
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              def dropdown_menu
         | 
| 51 | 
            +
                wrap_with :div, dropdown_menu_items, class: "dropdown-menu"
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def dropdown_menu_items
         | 
| 55 | 
            +
                navbar_items view: :nav_link_in_dropdown, link_class: "dropdown-item"
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              private
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              def navbar_link_chunk chunk, view, link_class
         | 
| 61 | 
            +
                link = chunk.render_link view: view, explicit_link_opts: { class: link_class }
         | 
| 62 | 
            +
                chunk.explicit_link? && view == :nav_item ? wrap_with_nav_item(link) : link
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              def navbar_nest_chunk chunk, view
         | 
| 66 | 
            +
                content_nest chunk.options.merge view: view
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
    
        data/set/all/overlay.rb
    ADDED
    
    | @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              OVERLAY_CLOSE_OPTS = { class: "_close-overlay btn-sm",
         | 
| 3 | 
            +
                                     "data-dismiss": "overlay",
         | 
| 4 | 
            +
                                     type: "button" }.freeze
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              wrapper :overlay do |opts|
         | 
| 7 | 
            +
                class_up "card-slot", "_overlay d0-card-overlay bg-body"
         | 
| 8 | 
            +
                @content_body = true
         | 
| 9 | 
            +
                voo.hide! :menu
         | 
| 10 | 
            +
                overlay_frame true, overlay_header(opts[:title]), opts[:slot] do
         | 
| 11 | 
            +
                  interior
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              view :overlay_header, unknown: true do
         | 
| 16 | 
            +
                overlay_header
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              view :overlay_title do
         | 
| 20 | 
            +
                _render_title
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              view :overlay_menu do
         | 
| 24 | 
            +
                wrap_with :div, class: "btn-group btn-group-sm align-self-start ml-auto" do
         | 
| 25 | 
            +
                  [render_overlay_help_link, slotify_overlay_link, close_overlay_link]
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              view :overlay_help_link, cache: :never, unknown: true do
         | 
| 30 | 
            +
                opts = help_popover_opts
         | 
| 31 | 
            +
                add_open_guide_opts opts
         | 
| 32 | 
            +
                overlay_menu_link "question-circle", opts
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              def add_open_guide_opts opts
         | 
| 36 | 
            +
                return unless card.guide_card
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                slot_selector = ".bridge-sidebar > ._overlay-container-placeholder > .card-slot"
         | 
| 39 | 
            +
                opts.merge! remote: true,
         | 
| 40 | 
            +
                            href: path(mark: card, view: :overlay_guide),
         | 
| 41 | 
            +
                            "data-slot-selector": slot_selector,
         | 
| 42 | 
            +
                            "data-slotter-mode": "overlay"
         | 
| 43 | 
            +
                add_class opts, "slotter"
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              def slotify_overlay_link
         | 
| 47 | 
            +
                overlay_menu_link "external-link-square", card: card
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              def close_overlay_link
         | 
| 51 | 
            +
                overlay_menu_link :close, path: "#", "data-dismiss": "overlay"
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def overlay_close_button link_text="Close", opts={}
         | 
| 55 | 
            +
                classes = opts.delete(:class)
         | 
| 56 | 
            +
                button_opts = opts.merge(OVERLAY_CLOSE_OPTS)
         | 
| 57 | 
            +
                add_class button_opts, classes if classes
         | 
| 58 | 
            +
                button_tag link_text, button_opts
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              def overlay_delete_button
         | 
| 62 | 
            +
                opts = { no_success: true }.merge OVERLAY_CLOSE_OPTS
         | 
| 63 | 
            +
                delete_button opts
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              def overlay_save_and_close_button
         | 
| 67 | 
            +
                submit_button text: "Save and Close", class: "_close-on-success",
         | 
| 68 | 
            +
                              "data-cy": "submit-overlay"
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              def overlay_menu_link icon, args={}
         | 
| 72 | 
            +
                add_class args, "border-light text-dark p-1 ml-1"
         | 
| 73 | 
            +
                button_link fa_icon(icon, class: "fa-lg"), args.merge(btn_type: "outline-secondary")
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              def overlay_header title=nil
         | 
| 77 | 
            +
                title ||= _render_overlay_title
         | 
| 78 | 
            +
                class_up "d0-card-header", "bg-body"
         | 
| 79 | 
            +
                class_up "d0-card-header-title", "d-flex"
         | 
| 80 | 
            +
                header_wrap [title, _render_overlay_menu]
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              def overlay_frame slot=true, header=render_overlay_header, slot_opts=nil
         | 
| 84 | 
            +
                slot_opts ||= {}
         | 
| 85 | 
            +
                overlay_framer slot, header, slot_opts do
         | 
| 86 | 
            +
                  wrap_body { yield }
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              def haml_overlay_frame slot=true, header=render_overlay_header
         | 
| 91 | 
            +
                overlay_framer slot, header, {} do
         | 
| 92 | 
            +
                  haml_wrap_body { yield }
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              private
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              def overlay_framer slot, header, slot_opts
         | 
| 99 | 
            +
                class_up "card-slot", "_overlay"
         | 
| 100 | 
            +
                with_frame slot, header, slot_opts do
         | 
| 101 | 
            +
                  yield
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
            end
         | 
| 
            File without changes
         | 
| @@ -0,0 +1,77 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              # TODO: use CodeFile cards for these
         | 
| 3 | 
            +
              # builtin layouts allow for rescue / testing
         | 
| 4 | 
            +
              # HTML_LAYOUTS = Mod::Loader.load_layouts(:html).merge "none" => "{{_main}}"
         | 
| 5 | 
            +
              # HAML_LAYOUTS = Mod::Loader.load_layouts(:haml)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              def show_with_page_layout view, args
         | 
| 8 | 
            +
                main!
         | 
| 9 | 
            +
                args = main_render_args view, args
         | 
| 10 | 
            +
                if explicit_modal_wrapper?(view) && page_layout.to_sym != :modal
         | 
| 11 | 
            +
                  render_outside_of_layout view, args
         | 
| 12 | 
            +
                else
         | 
| 13 | 
            +
                  render_with_layout view, page_layout, args
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def main_render_args view, args
         | 
| 18 | 
            +
                args[:view] = view if view
         | 
| 19 | 
            +
                args[:main] = true
         | 
| 20 | 
            +
                args[:main_view] = true
         | 
| 21 | 
            +
                args
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def page_layout
         | 
| 25 | 
            +
                params[:layout] || layout_name_from_rule || :default
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def render_with_layout view, layout, args={}
         | 
| 29 | 
            +
                view_opts = Layout.main_nest_opts(layout, self)
         | 
| 30 | 
            +
                view ||= view_opts.delete(:view) || default_nest_view
         | 
| 31 | 
            +
                view_opts[:home_view] = view
         | 
| 32 | 
            +
                view_opts[:layout] = layout
         | 
| 33 | 
            +
                render! view, view_opts.reverse_merge(args)
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def render_outside_of_layout view, args
         | 
| 37 | 
            +
                body = render_with_layout(nil, page_layout, {})
         | 
| 38 | 
            +
                modal = render!(view, args)
         | 
| 39 | 
            +
                if body.include?("</body>")
         | 
| 40 | 
            +
                  # a bit hacky
         | 
| 41 | 
            +
                  # the problem is that the body tag has to be in the layout
         | 
| 42 | 
            +
                  # so that you can add layout css classes like <body class="right-sidebar">
         | 
| 43 | 
            +
                  body.sub!("</body>", "#{modal}</body>")
         | 
| 44 | 
            +
                else
         | 
| 45 | 
            +
                  body += modal
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
                body
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              def show_layout?
         | 
| 51 | 
            +
                !Env.ajax? || params[:layout]
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def explicit_modal_wrapper? view
         | 
| 55 | 
            +
                return unless view_setting(:wrap, view)
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                wrapper_names(view_setting(:wrap, view)).any? { |n| n == :modal || n == :bridge }
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              def wrapper_names wrappers
         | 
| 61 | 
            +
                case wrappers
         | 
| 62 | 
            +
                when Hash  then wrappers.keys
         | 
| 63 | 
            +
                when Array then wrapper_names_from_array wrappers
         | 
| 64 | 
            +
                else            [wrappers]
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              def layout_name_from_rule
         | 
| 69 | 
            +
                card.rule_card(:layout)&.try :item_name
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              private
         | 
| 73 | 
            +
             | 
| 74 | 
            +
              def wrapper_names_from_array wrapper_array
         | 
| 75 | 
            +
                wrapper_array.map { |w| w.is_a?(Array) ? w.first : w }
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
            end
         | 
    
        data/set/all/tabs.rb
    ADDED
    
    | @@ -0,0 +1,51 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              view :tabs do
         | 
| 3 | 
            +
                construct_tabs "tabs"
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def construct_tabs tab_type
         | 
| 7 | 
            +
                tabs = { active: {}, paths: {} }
         | 
| 8 | 
            +
                voo.items[:view] ||= :content
         | 
| 9 | 
            +
                card.each_item_name_with_options(_render_raw) do |name, options|
         | 
| 10 | 
            +
                  construct_tab tabs, name, options
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
                tabs tabs[:paths], tabs[:active][:name], tab_type: tab_type, load: :lazy do
         | 
| 13 | 
            +
                  tabs[:active][:content]
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def construct_tab tabs, name, explicit_options
         | 
| 18 | 
            +
                tab_options = item_view_options explicit_options
         | 
| 19 | 
            +
                tabs[:paths][name] = {
         | 
| 20 | 
            +
                  title: nest(name, view: :title, title: tab_options[:title]),
         | 
| 21 | 
            +
                  path: nest_path(name, tab_options).html_safe
         | 
| 22 | 
            +
                }
         | 
| 23 | 
            +
                return unless tabs[:active].empty?
         | 
| 24 | 
            +
                tabs[:active] = { name: name, content: nest(name, tab_options) }
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              # def tab_title title, name
         | 
| 28 | 
            +
              #   return name unless title
         | 
| 29 | 
            +
              #   name.to_name.title title, @context_names
         | 
| 30 | 
            +
              # end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              view :pills do
         | 
| 33 | 
            +
                construct_tabs "pills"
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              view :tabs_static do
         | 
| 37 | 
            +
                construct_static_tabs "tabs"
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              view :pills_static do
         | 
| 41 | 
            +
                construct_static_tabs "pills"
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              def construct_static_tabs tab_type
         | 
| 45 | 
            +
                tabs = {}
         | 
| 46 | 
            +
                card.item_cards.each do |item|
         | 
| 47 | 
            +
                  tabs[item.name] = nest item, item_view_options(args)
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
                tabs tabs, nil, tab_type: tab_type
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
            end
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            include_set Abstract::AccountDropdown
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            def ok_to_read
         | 
| 4 | 
            +
              true
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            def ok_to_update
         | 
| 8 | 
            +
              left_id == Auth.current_id
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            def ok_to_create
         | 
| 12 | 
            +
              left_id == Auth.current_id
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            def ensure_roles
         | 
| 16 | 
            +
              self.content = Auth.current_roles.to_pointer_content if content.blank?
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            event :validate_role_enabling, :validate, on: :save do
         | 
| 20 | 
            +
              illegal_roles = item_names - Auth.current_roles
         | 
| 21 | 
            +
              return if illegal_roles.empty?
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              errors.add :content, "illegal roles: #{illegal_roles.to_sentence}" # LOCALIZE
         | 
| 24 | 
            +
            end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            event :clear_roles_cache, :prepare_to_store, before: :store_in_session do
         | 
| 27 | 
            +
              clear_roles
         | 
| 28 | 
            +
              Auth.update_always_cache Auth.as_id, nil
         | 
| 29 | 
            +
            end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            format :html do
         | 
| 32 | 
            +
              # permission change compared to super
         | 
| 33 | 
            +
              view :edit_inline, perms: :none, unknown: true, cache: :never, wrap: :slot do
         | 
| 34 | 
            +
                super()
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              def input_type
         | 
| 38 | 
            +
                :checkbox
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              def edit_success
         | 
| 42 | 
            +
                { reload: true }
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def hidden_form_tags _action, opts
         | 
| 46 | 
            +
                "#{super} #{hidden_tags card: { type_id: SessionID }}"
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def checkbox_input
         | 
| 50 | 
            +
                card.ensure_roles
         | 
| 51 | 
            +
                wrap_with :div, class: "pointer-checkbox-list" do
         | 
| 52 | 
            +
                  account_dropdown(&method(:role_item_checkbox))
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              def role_item_checkbox role_name
         | 
| 57 | 
            +
                haml :role_checkbox, id: "pointer-checkbox-#{role_name.to_name.key}",
         | 
| 58 | 
            +
                                     checked: card.item_names.include?(role_name),
         | 
| 59 | 
            +
                                     option_name: role_name
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
            end
         | 
    
        data/set/right/head.rb
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            def ok_to_read
         | 
| 2 | 
            +
              true
         | 
| 3 | 
            +
            end
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            format :html do
         | 
| 6 | 
            +
              view :head_content do
         | 
| 7 | 
            +
                process_content render_raw
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              view :one_line_content do
         | 
| 11 | 
            +
                raw_one_line_content
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              view :core do
         | 
| 15 | 
            +
                process_content ::CodeRay.scan(render_raw, :html).div
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,99 @@ | |
| 1 | 
            +
            include_set Abstract::AccountDropdown
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            def ok_to_read
         | 
| 4 | 
            +
              true
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            format :html do
         | 
| 8 | 
            +
              view :core, cache: :never do
         | 
| 9 | 
            +
                status_class = Auth.signed_in? ? "logged-in" : "logged-out"
         | 
| 10 | 
            +
                wrap_with :div, id: "logging", class: status_class do
         | 
| 11 | 
            +
                  navbar_items.join "\n"
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def navbar_items
         | 
| 16 | 
            +
                # removed invite for now
         | 
| 17 | 
            +
                links =
         | 
| 18 | 
            +
                  %i[my_card sign_out sign_up sign_in].map do |link_view|
         | 
| 19 | 
            +
                    render(link_view)
         | 
| 20 | 
            +
                  end.compact
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                links.map do |link|
         | 
| 23 | 
            +
                  wrap_with_nav_item link
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              def self.link_options opts={}
         | 
| 28 | 
            +
                options = { denial: :blank, cache: :never }.merge opts
         | 
| 29 | 
            +
                options[:perms] = ->(r) { yield r } if block_given?
         | 
| 30 | 
            +
                options.clone
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              view :sign_up, link_options(&:show_signup_link?) do
         | 
| 34 | 
            +
                link_to_card :signup, account_link_text(:sign_up),
         | 
| 35 | 
            +
                             class: nav_link_class("signup-link"),
         | 
| 36 | 
            +
                             path: { action: :new, mark: :signup }
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              view(:sign_in, link_options { !Auth.signed_in? }) do
         | 
| 40 | 
            +
                link_to_card :signin, account_link_text(:sign_in),
         | 
| 41 | 
            +
                             class: nav_link_class("signin-link")
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              view(:sign_out, link_options { Auth.signed_in? }) do
         | 
| 45 | 
            +
                link_to_card :signin, account_link_text(:sign_out),
         | 
| 46 | 
            +
                             class: nav_link_class("signout-link"),
         | 
| 47 | 
            +
                             path: { action: :delete }
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              view :invite, link_options(&:show_invite_link?) do
         | 
| 51 | 
            +
                link_to_card :signup, account_link_text(:invite),
         | 
| 52 | 
            +
                             class: nav_link_class("invite-link"),
         | 
| 53 | 
            +
                             path: { action: :new, mark: :signup }
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              view(:my_card, link_options { Auth.signed_in? }) do
         | 
| 57 | 
            +
                can_disable_roles? ? interactive_roles_dropdown : simple_roles_dropdown
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              def interactive_roles_dropdown
         | 
| 61 | 
            +
                nest(enabled_roles_card,
         | 
| 62 | 
            +
                     view: :edit_inline, hide: %i[edit_inline_buttons name_formgroup])
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              def simple_roles_dropdown
         | 
| 66 | 
            +
                account_dropdown(&method(:link_to_card))
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              def enabled_roles_card
         | 
| 70 | 
            +
                Auth.current.fetch :enabled_roles, new: { type_id: SessionID }
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              def role_list
         | 
| 74 | 
            +
                Auth.current_roles.map(&method(:link_to_card))
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              def can_disable_roles?
         | 
| 78 | 
            +
                Auth.current_roles.size > 1 &&
         | 
| 79 | 
            +
                  Card::Codename.exists?(:enabled_roles) # workaround for broken migrations
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              def account_link_text purpose
         | 
| 83 | 
            +
                voo.title ||
         | 
| 84 | 
            +
                  I18n.t(purpose, scope: "mod.card-mod-account.set.self.account_links")
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              def nav_link_class type
         | 
| 88 | 
            +
                "nav-link #{classy(type)}"
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              def show_signup_link?
         | 
| 92 | 
            +
                !Auth.signed_in? && Card.new(type_id: SignupID).ok?(:create)
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              def show_invite_link?
         | 
| 96 | 
            +
                Auth.signed_in? &&
         | 
| 97 | 
            +
                  Card.new(type_id: Card.default_accounted_type_id).ok?(:create)
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
            end
         | 
    
        data/set/self/alerts.rb
    ADDED
    
    
    
        data/set/self/foot.rb
    ADDED
    
    
    
        data/set/self/head.rb
    ADDED
    
    | @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            setting_opts group: :webpage, position: 1, rule_type_editable: false,
         | 
| 2 | 
            +
                         short_help_text: "head tag content",
         | 
| 3 | 
            +
                         help_text: "head tag content"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            format :html do
         | 
| 6 | 
            +
              # when *head is rendered in the main body of a page, we escape the HTML
         | 
| 7 | 
            +
              # otherwise (most typically in the head tag, of course), we render the
         | 
| 8 | 
            +
              # HTML unescaped
         | 
| 9 | 
            +
              view :core, cache: :never do
         | 
| 10 | 
            +
                escape_in_main do
         | 
| 11 | 
            +
                  nest root.card, view: :head
         | 
| 12 | 
            +
                  # note that the head tag for each card is different
         | 
| 13 | 
            +
                  # (different title, different style rules, etc)
         | 
| 14 | 
            +
                  # so we don't cache the core of *head, but we _do_ cache some
         | 
| 15 | 
            +
                  # views within each head (see all/head.rb)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              view :input do
         | 
| 20 | 
            +
                "Content can't be edited."
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def escape_in_main
         | 
| 24 | 
            +
                main? ? (h yield) : yield
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
    
        data/set/self/layout.rb
    ADDED
    
    
    
        data/set/self/navbox.rb
    ADDED
    
    | @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              view :navbox, cache: :never do
         | 
| 3 | 
            +
                select_tag "query[keyword]", "", class: "_navbox navbox form-control w-100",
         | 
| 4 | 
            +
                                                 placeholder: navbar_placeholder
         | 
| 5 | 
            +
              end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              view :navbar do
         | 
| 8 | 
            +
                # FIXME: not bootstrap class here.
         | 
| 9 | 
            +
                class_up "navbox-form", "form-inline"
         | 
| 10 | 
            +
                render_core
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              view :core do
         | 
| 14 | 
            +
                form_tag path(mark: :search), method: "get", role: "search",
         | 
| 15 | 
            +
                                              class: classy("navbox-form", "nodblclick") do
         | 
| 16 | 
            +
                  wrap_with :div, class: "form-group w-100" do
         | 
| 17 | 
            +
                    render_navbox
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              # def initial_options
         | 
| 23 | 
            +
              #   return "" unless (keyword = params.dig :query, :keyword)
         | 
| 24 | 
            +
              #   options_for_select [keyword]
         | 
| 25 | 
            +
              # end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              # TODO: the more natural placeholder would be the content of the navbox card, no?
         | 
| 28 | 
            +
              # Also, the forced division of "raw" and "core" should probably be replaced
         | 
| 29 | 
            +
              # with a single haml template (for core view)
         | 
| 30 | 
            +
              def navbar_placeholder
         | 
| 31 | 
            +
                @placeholder ||= Card[:navbox, "*placeholder"]&.content || "Search"
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
    
        data/set/self/sidebar.rb
    ADDED
    
    
    
        data/set/type/html.rb
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            format :html do
         | 
| 2 | 
            +
              # deprecated; here to support old "*main menu" html cards in existing decks
         | 
| 3 | 
            +
              view :navbar_links, perms: :none do
         | 
| 4 | 
            +
                wrap_with :ul, class: "navbar-nav" do
         | 
| 5 | 
            +
                  item_links.map do |link|
         | 
| 6 | 
            +
                    wrap_with(:li, class: "nav-item") { link }
         | 
| 7 | 
            +
                  end.join "\n"
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              def item_links _args={}
         | 
| 12 | 
            +
                raw(render_core).split(/[,\n]/)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # -*- encoding : utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            include_set Type::Html
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            event :update_layout_registry, :finalize, on: :update do
         | 
| 6 | 
            +
              Card::Layout.deregister_layout name
         | 
| 7 | 
            +
              Card::Layout.register_layout_with_nest name, format
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            format :html do
         | 
| 11 | 
            +
              view :core do
         | 
| 12 | 
            +
                with_nest_mode :template do
         | 
| 13 | 
            +
                  process_content ::CodeRay.scan(_render_raw, :html).div
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,117 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: card-mod-layout
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.11.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Ethan McCutchen
         | 
| 8 | 
            +
            - Philipp Kühl
         | 
| 9 | 
            +
            - Gerry Gleason
         | 
| 10 | 
            +
            autorequire:
         | 
| 11 | 
            +
            bindir: bin
         | 
| 12 | 
            +
            cert_chain: []
         | 
| 13 | 
            +
            date: 2020-12-24 00:00:00.000000000 Z
         | 
| 14 | 
            +
            dependencies:
         | 
| 15 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 16 | 
            +
              name: card
         | 
| 17 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 18 | 
            +
                requirements:
         | 
| 19 | 
            +
                - - '='
         | 
| 20 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            +
                    version: 1.101.0
         | 
| 22 | 
            +
              type: :runtime
         | 
| 23 | 
            +
              prerelease: false
         | 
| 24 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 25 | 
            +
                requirements:
         | 
| 26 | 
            +
                - - '='
         | 
| 27 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 28 | 
            +
                    version: 1.101.0
         | 
| 29 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 30 | 
            +
              name: card-mod-account
         | 
| 31 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 32 | 
            +
                requirements:
         | 
| 33 | 
            +
                - - '='
         | 
| 34 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 35 | 
            +
                    version: 0.11.0
         | 
| 36 | 
            +
              type: :runtime
         | 
| 37 | 
            +
              prerelease: false
         | 
| 38 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 39 | 
            +
                requirements:
         | 
| 40 | 
            +
                - - '='
         | 
| 41 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 42 | 
            +
                    version: 0.11.0
         | 
| 43 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 44 | 
            +
              name: card-mod-session
         | 
| 45 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 46 | 
            +
                requirements:
         | 
| 47 | 
            +
                - - '='
         | 
| 48 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 49 | 
            +
                    version: 0.11.0
         | 
| 50 | 
            +
              type: :runtime
         | 
| 51 | 
            +
              prerelease: false
         | 
| 52 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 53 | 
            +
                requirements:
         | 
| 54 | 
            +
                - - '='
         | 
| 55 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 56 | 
            +
                    version: 0.11.0
         | 
| 57 | 
            +
            description: ''
         | 
| 58 | 
            +
            email:
         | 
| 59 | 
            +
            - info@decko.org
         | 
| 60 | 
            +
            executables: []
         | 
| 61 | 
            +
            extensions: []
         | 
| 62 | 
            +
            extra_rdoc_files: []
         | 
| 63 | 
            +
            files:
         | 
| 64 | 
            +
            - lib/card/layout.rb
         | 
| 65 | 
            +
            - lib/card/layout/card_layout.rb
         | 
| 66 | 
            +
            - lib/card/layout/code_layout.rb
         | 
| 67 | 
            +
            - lib/card/layout/proc_layout.rb
         | 
| 68 | 
            +
            - lib/card/layout/unknown_layout.rb
         | 
| 69 | 
            +
            - set/abstract/account_dropdown.rb
         | 
| 70 | 
            +
            - set/abstract/pointer/html_views.rb
         | 
| 71 | 
            +
            - set/all/alert.rb
         | 
| 72 | 
            +
            - set/all/layouts.rb
         | 
| 73 | 
            +
            - set/all/modal.rb
         | 
| 74 | 
            +
            - set/all/modal/modal_dialog.haml
         | 
| 75 | 
            +
            - set/all/navbar_links.rb
         | 
| 76 | 
            +
            - set/all/overlay.rb
         | 
| 77 | 
            +
            - set/all/overlay/overlay_header.haml
         | 
| 78 | 
            +
            - set/all/process_layout.rb
         | 
| 79 | 
            +
            - set/all/tabs.rb
         | 
| 80 | 
            +
            - set/right/enabled_roles.rb
         | 
| 81 | 
            +
            - set/right/enabled_roles/role_checkbox.haml
         | 
| 82 | 
            +
            - set/right/head.rb
         | 
| 83 | 
            +
            - set/self/account_links.rb
         | 
| 84 | 
            +
            - set/self/alerts.rb
         | 
| 85 | 
            +
            - set/self/dropdown_divider.rb
         | 
| 86 | 
            +
            - set/self/foot.rb
         | 
| 87 | 
            +
            - set/self/head.rb
         | 
| 88 | 
            +
            - set/self/layout.rb
         | 
| 89 | 
            +
            - set/self/navbox.rb
         | 
| 90 | 
            +
            - set/self/sidebar.rb
         | 
| 91 | 
            +
            - set/type/html.rb
         | 
| 92 | 
            +
            - set/type/layout_type.rb
         | 
| 93 | 
            +
            homepage: http://decko.org
         | 
| 94 | 
            +
            licenses:
         | 
| 95 | 
            +
            - GPL-3.0
         | 
| 96 | 
            +
            metadata:
         | 
| 97 | 
            +
              card-mod: layout
         | 
| 98 | 
            +
            post_install_message:
         | 
| 99 | 
            +
            rdoc_options: []
         | 
| 100 | 
            +
            require_paths:
         | 
| 101 | 
            +
            - lib
         | 
| 102 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 103 | 
            +
              requirements:
         | 
| 104 | 
            +
              - - ">="
         | 
| 105 | 
            +
                - !ruby/object:Gem::Version
         | 
| 106 | 
            +
                  version: '2.5'
         | 
| 107 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 108 | 
            +
              requirements:
         | 
| 109 | 
            +
              - - ">="
         | 
| 110 | 
            +
                - !ruby/object:Gem::Version
         | 
| 111 | 
            +
                  version: '0'
         | 
| 112 | 
            +
            requirements: []
         | 
| 113 | 
            +
            rubygems_version: 3.0.3
         | 
| 114 | 
            +
            signing_key:
         | 
| 115 | 
            +
            specification_version: 4
         | 
| 116 | 
            +
            summary: decko layouts
         | 
| 117 | 
            +
            test_files: []
         |