Browse Source

Introduce Initial and naive tagging.

No permissions, limits, validation, ownership etc. yet.
feature/tags
Bèr Kessels 10 months ago
parent
commit
60f8e0897c

+ 32
- 6
app/aggregates/member.rb View File

@@ -1,6 +1,8 @@
# frozen_string_literal: true

require_relative 'mixins/attributes'
require_relative 'member/tag'

require 'lib/aggregate_equality'

module Aggregates
@@ -13,6 +15,11 @@ module Aggregates
include AggregateEquality
include Attributes

def initialize(id, events)
@tags = []
super(id, events)
end

apply MemberAdded do |event|
username = event.body['username']
write_attributes(
@@ -34,6 +41,10 @@ module Aggregates
write_attributes(event.body.slice('name'))
end

apply MemberTagAdded do |event|
@tags << Tag.new(event.body['tag'])
end

def add_member(payload)
apply_event(MemberAdded, aggregate_id: id, body: payload)
self
@@ -60,8 +71,22 @@ module Aggregates
self
end

def add_tag(payload)
body = payload.slice('author_id', 'tag')
apply_event(MemberTagAdded, aggregate_id: id, body: body)
self
end

attr_reader :id

def active?
attributes.fetch(:added, false)
end

def null?
false
end

def member_id
id
end
@@ -74,10 +99,6 @@ module Aggregates
attributes[:name]
end

def active?
attributes.fetch(:added, false)
end

def handle
attributes[:handle]
end
@@ -90,8 +111,13 @@ module Aggregates
id
end

def null?
false
# TODO: implement per-author tags
def tags_for(_member)
tags
end

private

attr_reader :tags
end
end

+ 24
- 0
app/aggregates/member/tag.rb View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Aggregates
class Member
##
# A +Tag+ is an attribute on a +Member+. Each member has 0-N tags. Each tag
# has 0-N members
class Tag
attr_reader :name

def initialize(name)
@name = name
end

def slug
name.downcase
end

def by?(_expected_author)
true
end
end
end
end

+ 24
- 0
app/commands/profile/tag.rb View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Commands
module Profile
module Tag
##
# Command to add a Tag
class Command < ApplicationCommand
end

##
# Handler for Profile::Tag::Command
class CommandHandler < ApplicationCommandHandler
def aggregate_class
Aggregates::Member
end

def aggregate_method
:add_tag
end
end
end
end
end

+ 1
- 1
app/commands/profile/update.rb View File

@@ -10,7 +10,7 @@ module Commands
class Command < ApplicationCommand
end

# Handler for Confirm::Command
# Handler for Profile::Update::Command
class CommandHandler < ApplicationCommandHandler
##
# Overridden from ApplicationCommandHandler because we want

+ 5
- 0
app/events/member_tag_added.rb View File

@@ -0,0 +1,5 @@
# frozen_string_literal: true

##
# A Member was Tagged
MemberTagAdded = Class.new(EventSourcery::Event)

+ 51
- 0
app/web/controllers/web/tags_controller.rb View File

@@ -0,0 +1,51 @@
# frozen_string_literal: true

module Web
##
# Handles viewing of tags-edit page and adding new tags to a member
class TagsController < WebController
include LoadHelpers

# TODO: DRY with ProfilesController
get '/m/:handle/tags' do
raise NotFound, 'Member with that handle not found' if profile.null?

erb(:profile_tags, layout: :layout_member, locals: { profile: profile })
end

post '/tags' do
requires_authorization

Commands.handle(
'Profile',
'Tag',
post_params.merge(
aggregate_id: profile.id,
author_id: member_id
)
)

# TODO: raise if no profile handle given
# TODO: remove the hardcoded tag.
flash[:success] = "#{profile.handle} was tagged as \"#{post_params['tag']}\""
redirect "/m/#{profile.handle}"
end

private

def profile
@profile ||= decorate(
load(
Aggregates::Member,
Projections::Members::Query.aggregate_id_for(params[:handle]),
),
ViewModels::Profile,
ViewModels::Profile::NullProfile
)
end

def post_params
params.slice('tag')
end
end
end

+ 6
- 2
app/web/views/profile.erb View File

@@ -8,7 +8,7 @@
</div>
<div class="level is-mobile">
<div class="level-left">
<h1 class="title is-5"><%= profile.name %></h1>
<h1 class="title is-5"><%= profile.name %></h1><br />
<%= profile.handle %>
</div>
<p class="buttons level-right">
@@ -32,10 +32,14 @@
<p class="bio"><%= profile.bio %></p>

<section class="tags">
<a class="button" href="/m/<%= profile.handle %>/tags">
<a class="button tag is-primary is-medium" href="/m/<%= profile.handle %>/tags">
<span class="icon is-small">
<i class="mdi mdi-plus"></i>
</span>
</a>

<%- profile.tags_for(current_member).each do |tag| %>
<a class="tag is-primary is-medium<%= tag.by?(current_member) ? ' mine' : '' %>" href="/tags/<%= tag.slug %>/"><%= tag.name %></a>
<%- end %>
</section>
</div>

+ 17
- 0
app/web/views/profile_tags.erb View File

@@ -0,0 +1,17 @@
<form action="/tags" method="post">
<label class="label" for="tag">Add your own</label>
<div class="field has-addons">
<div class="control">
<input type="hidden" name="handle" value="<%= profile.handle %>"/>
<input class="input" type="text" name="tag" id="tag"/>
</div>

<div class="control">
<button type="submit" class="button is-primary">
<span class="icon is-small">
<i class="mdi mdi-plus"></i>
</span>
</button>
</div>
</div>
</form>

+ 2
- 0
config.ru View File

@@ -10,11 +10,13 @@ require 'app/web/server'

use Web::HomeController
use Web::ProfilesController
use Web::TagsController

use Web::LoginController
# TODO: change from RPC alike "register" to "registration"
use Web::RegistrationsController
use Web::ConfirmationsController

use Web::MyProfilesController
use Web::ContactsController
use Web::UpdatesController

+ 29
- 0
test/integration/web/member_tags_member_test.rb View File

@@ -0,0 +1,29 @@
# frozen_string_literal: true

require 'test_helper'

##
# As a member using the web-app
# When I visit another members' profile
# And I click the "add tag" button
# And I fill provide a tag
# Then the tag is added to that profile
# And I follow the member
class MemberTagsMemberTest < Minitest::WebSpec
before do
harry
ron

as(harry)
discover_member(username: ron[:username]).upto(:profile_visited)

tags_member.upto(:tag_added)
end

it 'adds a tag to another profile' do
assert_content(flash(:success), '@ron@example.com was tagged as "friend"')
discover_member(username: ron[:username]).upto(:profile_visited)

assert_selector('.tag.mine', text: 'friend')
end
end

+ 32
- 0
test/support/workflows/tags_member.rb View File

@@ -0,0 +1,32 @@
# frozen_string_literal: true

module Workflows
##
# Workflow to tag another members' profile.
class TagsMember < Base
def tag_added
within '.tags' do
click_icon('plus')
end

within 'form' do
fill_in 'Add your own', with: form_attributes[:tag]
click_icon('plus')
end

process_events(%w[tag_added])
end

def form_attributes
{
tag: 'friend'
}.merge(@form_attributes)
end

private

def steps
%i[tag_added].freeze
end
end
end

Loading…
Cancel
Save