Browse files

Added tags

  • Loading branch information...
1 parent 8413943 commit 28e002a2e46d917213dcb48225090b963c4898db @abdullin committed Jul 26, 2011
View
4 FarleyFile.Abstractions/FarleyFile.Abstractions.csproj
@@ -58,7 +58,7 @@
<Compile Include="Views\ItemIndex.cs" />
<Compile Include="Views\NoteList.cs" />
<Compile Include="Views\NoteView.cs" />
- <Compile Include="Views\StoryComposite.cs" />
+ <Compile Include="Views\FocusComposite.cs" />
<Compile Include="Views\StoryList.cs" />
<Compile Include="Views\StoryView.cs" />
<Compile Include="Views\TaskList.cs" />
@@ -80,4 +80,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project>
View
16 FarleyFile.Abstractions/IEvent.cs
@@ -116,6 +116,8 @@ public ActivityId(Guid id)
ActivityId() {}
}
+
+
[DataContract]
public sealed class TaskId : Identity
{
@@ -128,4 +130,18 @@ public TaskId(Guid id)
TaskId() {}
}
+
+ [DataContract]
+ public sealed class TagId : Identity
+ {
+ public const int TagIdValue = 7;
+ public TagId(Guid id)
+ {
+ Tag = TagIdValue;
+ Id = id;
+ }
+
+
+ TagId() { }
+ }
}
View
3 FarleyFile.Abstractions/IdentityEvil.cs
@@ -14,7 +14,8 @@ static IdentityEvil()
{NoteId.TagId, g => new NoteId(g)},
{StoryId.TagId, g => new StoryId(g)},
{TaskId.TagId, g => new TaskId(g)},
- {ActivityId.TagId, g => new ActivityId(g)}
+ {ActivityId.TagId, g => new ActivityId(g)},
+ {TagId.TagIdValue, g => new TagId(g)}
};
}
View
43 FarleyFile.Abstractions/Messages.cs
@@ -238,6 +238,49 @@ public TaskAdded (TaskId taskId, string text, StoryId storyId)
}
}
+ [DataContract] public sealed class TagItem : ICommand
+ {
+ [DataMember(Order = 1)] public string Tag { get; internal set; }
+ [DataMember(Order = 2)] public Identity ItemId { get; internal set; }
+
+ internal TagItem () {}
+ public TagItem (string tag, Identity itemId)
+ {
+ Tag = tag;
+ ItemId = itemId;
+ }
+ }
+
+ [DataContract] public sealed class TagCreated : IEvent
+ {
+ [DataMember(Order = 1)] public string Tag { get; internal set; }
+ [DataMember(Order = 2)] public TagId TagId { get; internal set; }
+
+ internal TagCreated () {}
+ public TagCreated (string tag, TagId tagId)
+ {
+ Tag = tag;
+ TagId = tagId;
+ }
+ }
+
+ [DataContract] public sealed class TagAddedToStory : IEvent
+ {
+ [DataMember(Order = 1)] public StoryId StoryId { get; internal set; }
+ [DataMember(Order = 2)] public TagId TagId { get; internal set; }
+ [DataMember(Order = 3)] public string Tag { get; internal set; }
+ [DataMember(Order = 4)] public string StoryName { get; internal set; }
+
+ internal TagAddedToStory () {}
+ public TagAddedToStory (StoryId storyId, TagId tagId, string tag, string storyName)
+ {
+ StoryId = storyId;
+ TagId = tagId;
+ Tag = tag;
+ StoryName = storyName;
+ }
+ }
+
[DataContract] public sealed class ArchiveItem : ICommand
{
[DataMember(Order = 1)] public Identity Id { get; internal set; }
View
8 FarleyFile.Abstractions/Messages.tt
@@ -18,6 +18,7 @@ let taskId = TaskId TaskId;
let date = DateTime Date;
let activity = ActivityId ActivityId;
let id = Identity Id;
+let tagId = TagId TagId;
let time = DateTimeOffset Time;
PerspectiveCreated! ()
@@ -51,6 +52,13 @@ AddTask? (string text, storyId)
TaskAdded! (taskId, string text, storyId)
+TagItem? (string tag, Identity itemId)
+TagCreated! (string tag, tagId)
+
+TagAddedToStory! (storyId, tagId, string tag, string storyName)
+
+
+
ArchiveItem? (id, storyId)
NoteArchived!(noteId, storyId)
View
24 FarleyFile.Abstractions/Views/FocusComposite.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+
+namespace FarleyFile.Views
+{
+ public sealed class FocusComposite
+ {
+ public readonly Identity Focus;
+ public readonly string Name;
+
+ //public readonly StoryView View;
+ public readonly ICollection<ActivityList.Item> Activities;
+ public readonly ICollection<TaskList.Item> Tasks;
+ public readonly ICollection<NoteList.Item> Notes;
+
+ public FocusComposite(Identity id, string name, ICollection<ActivityList.Item> activities, ICollection<TaskList.Item> tasks, ICollection<NoteList.Item> notes)
+ {
+ Focus = id;
+ Name = name;
+ Activities = activities;
+ Tasks = tasks;
+ Notes = notes;
+ }
+ }
+}
View
18 FarleyFile.Abstractions/Views/StoryComposite.cs
@@ -1,18 +0,0 @@
-namespace FarleyFile.Views
-{
- public sealed class StoryComposite
- {
- public readonly StoryView View;
- public readonly ActivityList Activities;
- public readonly TaskList Tasks;
- public readonly NoteList Notes;
-
- public StoryComposite(StoryView view, ActivityList activities, TaskList tasks, NoteList notes)
- {
- View = view;
- Activities = activities;
- Tasks = tasks;
- Notes = notes;
- }
- }
-}
View
7 FarleyFile.Abstractions/Views/StoryView.cs
@@ -8,9 +8,12 @@ public sealed class StoryView : IEntityBase
{
public string Name { get; set; }
public StoryId StoryId { get; set; }
+ public IDictionary<string, TagId> Tags { get; private set; }
-
-
+ public StoryView()
+ {
+ Tags = new Dictionary<string,TagId>();
+ }
}
View
39 FarleyFile.Abstractions/Views/TaskList.cs
@@ -47,4 +47,43 @@ public sealed class Item
public bool Completed { get; set; }
}
}
+
+ public sealed class TagList : IEntityBase
+ {
+ public Dictionary<string, TagId> Items { get; private set; }
+
+ public TagList()
+ {
+ Items = new Dictionary<string, TagId>();
+ }
+ }
+
+ public sealed class TagView : IEntityBase
+ {
+ public string Name { get; set; }
+ public TagId Id { get; set; }
+
+ public List<StoryItem> Stories { get; private set; }
+
+ public void AddStory(StoryId id, string name)
+ {
+ Stories.Add(new StoryItem()
+ {
+ Name = name,
+ Story = id
+ });
+ }
+
+ public TagView()
+ {
+ Stories = new List<StoryItem>();
+ }
+
+
+ public sealed class StoryItem
+ {
+ public string Name { get; set; }
+ public StoryId Story { get; set; }
+ }
+ }
}
View
1 FarleyFile.Desktop/FarleyFile.Desktop.csproj
@@ -58,6 +58,7 @@
<Compile Include="Interactions\InteractionProcessor.cs" />
<Compile Include="Interactions\InteractionResultStatus.cs" />
<Compile Include="Interactions\Specific\DoAddActivity.cs" />
+ <Compile Include="Interactions\Specific\FocusOnStory.cs" />
<Compile Include="Solarized.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
View
42 FarleyFile.Desktop/Interactions/Specific/ClearScreen.cs
@@ -36,48 +36,6 @@ namespace FarleyFile.Interactions.Specific
// }
//}
- public sealed class FocusOnStory : AbstractInteraction
- {
- protected override string[] Alias
- {
- get { return new[] { "cd",""}; }
- }
-
- public override InteractionResult Handle(InteractionContext context)
- {
- StoryId id;
- var source = context.Request.Data;
- if (string.IsNullOrEmpty(source))
- {
- id = context.Request.CurrentStoryId;
- if (id.IsEmpty)
- {
- return Error("Story id was not specified and there is no focused story");
- }
- }
- else if (!context.Request.TryGetId(source, out id))
- {
- return Error("Could not find story ID '{0}'", source);
- }
-
- var store = context.Storage;
- var result = store.GetEntity<StoryView>(id);
- if (!result.HasValue)
- {
- return Error("Story id not found '{0}'", id);
- }
- var story = result.Value;
- var activities = store.GetEntity<ActivityList>(id).GetValue(new ActivityList());
- var tasks = store.GetEntity<TaskList>(id).GetValue(new TaskList());
- var notes = store.GetEntity<NoteList>(id).GetValue(new NoteList());
- var composite = new StoryComposite(story, activities, tasks, notes);
- context.Response.RenderView(composite);
- context.Response.FocusStory(story.StoryId, story.Name);
-
- return Handled();
- }
- }
-
public sealed class DoAddNote : AbstractInteraction
{
protected override string[] Alias
View
105 FarleyFile.Desktop/Interactions/Specific/FocusOnStory.cs
@@ -0,0 +1,105 @@
+using System.Collections.Generic;
+using FarleyFile.Views;
+using System.Linq;
+
+namespace FarleyFile.Interactions.Specific
+{
+ public sealed class DoTagItem : AbstractInteraction
+ {
+ protected override string[] Alias
+ {
+ get { return new[] {"tag"}; }
+ }
+
+ public override InteractionResult Handle(InteractionContext context)
+ {
+ var items = context.Request.Data.Split(' ');
+ Identity itemId;
+ if (!context.Request.TryGetId(items[0], out itemId))
+ {
+ return Error("Failed to lookup item '{0}'", items[0]);
+ }
+ context.Response.SendToProject(new TagItem(items[1], itemId));
+ return Handled();
+ }
+ }
+
+ public sealed class ListTags : AbstractInteraction
+ {
+ protected override string[] Alias
+ {
+ get { return new string[] {"lt"}; }
+ }
+
+ public override InteractionResult Handle(InteractionContext context)
+ {
+ var tags = context.Storage.GetSingletonOrNew<TagList>();
+ context.Response.RenderView(tags);
+ return Handled();
+ }
+ }
+
+ public sealed class FocusOnStory : AbstractInteraction
+ {
+ protected override string[] Alias
+ {
+ get { return new[] { "cd",""}; }
+ }
+
+ public override InteractionResult Handle(InteractionContext context)
+ {
+ Identity id;
+ var source = context.Request.Data;
+ if (string.IsNullOrEmpty(source))
+ {
+ id = context.Request.CurrentStoryId;
+ if (id.IsEmpty)
+ {
+ return Error("Id was not specified and there is no focused story");
+ }
+ }
+ else if (!context.Request.TryGetId(source, out id))
+ {
+ return Error("Could not find story ID '{0}'", source);
+ }
+ var store = context.Storage;
+ if (id is StoryId)
+ {
+ var result = store.GetEntity<StoryView>(id);
+ if (!result.HasValue)
+ {
+ return Error("Story id not found '{0}'", id);
+ }
+ var story = result.Value;
+ var activities = store.GetEntity<ActivityList>(id).GetValue(new ActivityList());
+ var tasks = store.GetEntity<TaskList>(id).GetValue(new TaskList());
+ var notes = store.GetEntity<NoteList>(id).GetValue(new NoteList());
+ var composite = new FocusComposite(story.StoryId, story.Name, activities.List, tasks.List, notes.Notes);
+ context.Response.RenderView(composite);
+ context.Response.FocusStory(story.StoryId, story.Name);
+ return Handled();
+ }
+ if (id is TagId)
+ {
+ var result = store.GetEntity<TagView>(id);
+ if (!result.HasValue)
+ {
+ return Error("Tag not found '{0}'", id);
+ }
+ var view = result.Value;
+ var stories = view.Stories
+ .Select(s => store.GetEntity<StoryView>(s.Story))
+ .Where(o => o.HasValue)
+ .Select(o => o.Value)
+ .ToList();
+ var activities = stories.SelectMany(s => store.GetEntity<ActivityList>(s.StoryId).Convert(al => al.List, new List<ActivityList.Item>())).ToList();
+ var tasks = stories.SelectMany(s => store.GetEntity<TaskList>(s.StoryId).Convert(al => al.List, new List<TaskList.Item>())).ToList();
+ var notes = stories.SelectMany(s => store.GetEntity<NoteList>(s.StoryId).Convert(al => al.Notes, new List<NoteList.Item>())).ToList();
+ var composite = new FocusComposite(id, view.Name, activities, tasks, notes);
+ context.Response.RenderView(composite);
+ return Handled();
+ }
+ return Error("Can't focus");
+ }
+ }
+}
View
53 FarleyFile.Desktop/LifelineViewport.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Windows.Forms;
using FarleyFile.Views;
@@ -118,9 +119,18 @@ public void Error(string text, params object[] args)
public void RenderView<T>(T view)
{
- RedirectToWhen.InvokeOptional(this, view, (i,v) => _rich.AppendText(ServiceStack.Text.TypeSerializer.SerializeAndFormat(view)));
+ RedirectToWhen.InvokeOptional(this, view, (i,v) =>
+ {
+ using (_rich.Styled(Solarized.Yellow))
+ {
+ _rich.AppendLine(view.GetType().Name);
+ }
+ _rich.AppendText(ServiceStack.Text.TypeSerializer.SerializeAndFormat(view));
+ });
}
+
+
public void When(StoryList list)
{
using (_rich.Styled(Solarized.Yellow))
@@ -135,17 +145,46 @@ public void When(StoryList list)
}
}
- public void When(StoryComposite composite)
+ public void When(TagList list)
{
- var view = composite.View;
- var txt = string.Format("Story: {0} .{1}", view.Name, AddReference(view.StoryId, view.Name));
+ using (_rich.Styled(Solarized.Violet))
+ {
+ _rich.AppendLine("Tags");
+ }
+ foreach (var item in list.Items.OrderBy(s => s.Key))
+ {
+ var reference = AddReference(item.Value, item.Key);
+ _rich.AppendLine("{0} .{1}", item.Key, reference);
+ }
+ }
+
+ public void When(FocusComposite composite)
+ {
+ //var view = composite.View;
+
+ string txt;
+ if (composite.Focus is StoryId)
+ {
+ txt = string.Format("Story: {0} .{1}", composite.Name, AddReference(composite.Focus, composite.Name));
+ }
+ else if (composite.Focus is TagId)
+ {
+ txt = string.Format("Tag: {0} .{1}", composite.Name, AddReference(composite.Focus, composite.Name));
+ }
+ else
+ {
+ throw new InvalidOperationException("Unexpected thing to focus on");
+ }
+
+
+
using (_rich.Styled(Solarized.Yellow))
{
_rich.AppendLine(txt);
}
_rich.AppendLine(new string('=', txt.Length));
- var tasks = composite.Tasks.List.Where(c => !c.Completed).ToList();
+ var tasks = composite.Tasks.Where(c => !c.Completed).ToList();
if (tasks.Count > 0)
{
using (_rich.Styled(Solarized.Green))
@@ -161,7 +200,7 @@ public void When(StoryComposite composite)
_rich.AppendLine();
}
- var activities = composite.Activities.List;
+ var activities = composite.Activities;
if (activities.Count > 0)
{
@@ -195,7 +234,7 @@ public void When(StoryComposite composite)
_rich.AppendLine();
}
- var notes = composite.Notes.Notes;
+ var notes = composite.Notes;
if (notes.Count > 0)
{
View
23 FarleyFile.Domain/Aggregates/PerspectiveAggregate.cs
@@ -30,6 +30,29 @@ public void When(StartSimpleStory c)
Apply(new SimpleStoryStarted(id, c.Name));
}
+ public void When(TagItem c)
+ {
+ TagId id;
+ if (!_state.TryGetTag(c.Tag, out id))
+ {
+ id = _state.GetNext(g => new TagId(g));
+ Apply(new TagCreated(c.Tag, id));
+ }
+
+ SimpleStory story;
+ if (_state.TryGetStory(new StoryId(c.ItemId),out story))
+ {
+ if (!story.Tags.Contains(id))
+ {
+ Apply(new TagAddedToStory(story.Id, id, c.Tag, story.Name));
+ }
+ return;
+ }
+
+ throw Error("Can't tag item '{0}'", c.ItemId);
+
+ }
+
public void When(RenameItem c)
{
NoteItem note;
View
21 FarleyFile.Domain/Aggregates/PerspectiveAggregateState.cs
@@ -12,6 +12,13 @@ public sealed class PerspectiveAggregateState : IAggregateState
readonly Dictionary<Identity, AbstractItem> _items = new Dictionary<Identity, AbstractItem>();
readonly SortedDictionary<Identity,Activity> _activities = new SortedDictionary<Identity, Activity>();
+ readonly Dictionary<string,TagId> _tags = new Dictionary<string, TagId>();
+
+ public bool TryGetTag(string tag, out TagId id)
+ {
+ return _tags.TryGetValue(tag, out id);
+ }
+
public void When(ActivityAdded e)
{
_activities.Add(e.ActivityId, new Activity());
@@ -84,6 +91,15 @@ public void When(SimpleStoryRenamed e)
story.Rename(e.NewName);
}
+ public void When(TagCreated e)
+ {
+ _tags.Add(e.Tag, e.TagId);
+ }
+ public void When(TagAddedToStory e)
+ {
+ _stories[e.StoryId].Tags.Add(e.TagId);
+ }
+
public bool TryGetStory<TStory>(StoryId storyId, out TStory story)
where TStory : AbstractStory
{
@@ -189,9 +205,8 @@ public sealed class Activity
public abstract class AbstractStory
{
- public HashSet<Identity> AsItGoes = new HashSet<Identity>();
-
-
+ public readonly HashSet<Identity> AsItGoes = new HashSet<Identity>();
+ public readonly HashSet<TagId> Tags = new HashSet<TagId>();
}
public sealed class SimpleStory : AbstractStory
View
8 FarleyFile.Domain/Views/StoryViewHandler.cs
@@ -6,7 +6,8 @@ namespace FarleyFile
{
public sealed class StoryViewHandler :
IConsume<SimpleStoryStarted>,
- IConsume<SimpleStoryRenamed>
+ IConsume<SimpleStoryRenamed>,
+ IConsume<TagAddedToStory>
{
readonly IAtomicEntityWriter<Identity,StoryView> _writer;
@@ -28,5 +29,10 @@ public void Consume(SimpleStoryRenamed e)
{
_writer.UpdateOrThrow(e.StoryId, v => v.Name = e.NewName);
}
+
+ public void Consume(TagAddedToStory e)
+ {
+ _writer.UpdateOrThrow(e.StoryId, v => v.Tags.Add(e.Tag, e.TagId));
+ }
}
}
View
39 FarleyFile.Domain/Views/TaskListHandler.cs
@@ -38,4 +38,43 @@ public void Consume(TaskArchived e)
_writer.UpdateOrThrow(e.StoryId, sv => sv.ArchiveTask(e.TaskId));
}
}
+
+ public sealed class TagListHandler : IConsume<TagCreated>
+ {
+ IAtomicSingletonWriter<TagList> _writer;
+ public TagListHandler(IAtomicSingletonWriter<TagList> writer)
+ {
+ _writer = writer;
+ }
+
+ public void Consume(TagCreated e)
+ {
+ _writer.UpdateEnforcingNew(v => v.Items.Add(e.Tag, e.TagId));
+ }
+ }
+
+ public sealed class TagViewHandler :
+ IConsume<TagAddedToStory>,
+ IConsume<TagCreated>
+ {
+ IAtomicEntityWriter<TagId, TagView> _writer;
+ public TagViewHandler(IAtomicEntityWriter<TagId, TagView> writer)
+ {
+ _writer = writer;
+ }
+
+ public void Consume(TagAddedToStory e)
+ {
+ _writer.UpdateOrThrow(e.TagId, v => v.AddStory(e.StoryId, e.StoryName));
+ }
+
+ public void Consume(TagCreated e)
+ {
+ _writer.Add(e.TagId, new TagView()
+ {
+ Id = e.TagId,
+ Name = e.Tag
+ });
+ }
+ }
}

0 comments on commit 28e002a

Please sign in to comment.