aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shard/lib/app/directory.ex45
-rw-r--r--shardweb/lib/controllers/directory_controller.ex29
-rw-r--r--shardweb/lib/controllers/identity_controller.ex34
-rw-r--r--shardweb/lib/router.ex4
-rw-r--r--shardweb/lib/templates/directory/view.html.eex38
-rw-r--r--shardweb/lib/templates/identity/view.html.eex12
-rw-r--r--shardweb/lib/templates/layout/app.html.eex7
-rw-r--r--shardweb/lib/templates/page/shard_entry.html.eex30
-rw-r--r--shardweb/lib/templates/page/shard_list.html.eex31
-rw-r--r--shardweb/lib/views/directory_view.ex9
-rw-r--r--shardweb/lib/views/identity_view.ex5
11 files changed, 210 insertions, 34 deletions
diff --git a/shard/lib/app/directory.ex b/shard/lib/app/directory.ex
index f7d871a..55413c4 100644
--- a/shard/lib/app/directory.ex
+++ b/shard/lib/app/directory.ex
@@ -42,10 +42,12 @@ defmodule SApp.Directory do
end
SNet.Group.init_lookup(netgroup, self())
+ revfiles = for {n, m} <- SData.SignRev.get(files), into: %{}, do: {m, n}
+
{:ok, %{
owner: owner, public: public, name: name,
manifest: manifest, id: id, netgroup: netgroup,
- files: files}}
+ files: files, revfiles: revfiles}}
end
def handle_call(:manifest, _from, state) do
@@ -66,7 +68,10 @@ defmodule SApp.Directory do
GenServer.cast(Shard.Manager, {:dep_list, state.id, Map.values(dict)})
{:ok, st2} = SData.SignRev.set(state.files, dict, state.owner)
Shard.Manager.save_state(state.id, st2)
- state = put_in(state.files, st2)
+ state = %{state |
+ files: st2,
+ revfiles: Map.put(state.revfiles, manifest, name)
+ }
bcast_state(state)
{:reply, :ok, state}
end
@@ -81,6 +86,7 @@ defmodule SApp.Directory do
if dict[name] == nil do
{:reply, :not_found, state}
else
+ state = put_in(state.revfiles, Map.delete(state.revfiles, dict[name]))
dict = Map.delete(dict, name)
GenServer.cast(Shard.Manager, {:dep_list, state.id, Map.values(dict)})
{:ok, st2} = SData.SignRev.set(state.files, dict, state.owner)
@@ -94,6 +100,15 @@ defmodule SApp.Directory do
end
end
+ def handle_call({:read, name}, _from, state) do
+ dict = SData.SignRev.get(state.files)
+ {:reply, dict[name], state}
+ end
+
+ def handle_call({:find, manifest}, _from, state) do
+ {:reply, state.revfiles[manifest], state}
+ end
+
def handle_cast(:send_deps, state) do
dict = SData.SignRev.get(state.files)
GenServer.cast(Shard.Manager, {:dep_list, state.id, Map.values(dict)})
@@ -144,13 +159,29 @@ defmodule SApp.Directory do
@doc"""
Return list of files stored in this directory.
- Returns a list of {name, manifests}.
+ Returns a dictionnary of %{name => manifest}.
"""
def get_files(pid) do
GenServer.call(pid, :get_files)
end
@doc"""
+ Return the manifest of file with a given name in directory, or nil if not found.
+
+ Equivalent to get_files(pid)[name] but better.
+ """
+ def read(pid, name) do
+ GenServer.call(pid, {:read, name})
+ end
+
+ @doc"""
+ Find a file in the directory by its manifest. Returns name if found or nil if not found.
+ """
+ def find(pid, manifest) do
+ GenServer.call(pid, {:find, manifest})
+ end
+
+ @doc"""
Add a file to this directory. A file is a name for a shard manifest.
A file added to a directory becomes a dependency of the directory, i.e.
if the directory is pinned then all files inside are pinned as well.
@@ -165,4 +196,12 @@ defmodule SApp.Directory do
def rm_file(pid, name) do
GenServer.call(pid, {:rm_file, name})
end
+
+ @doc"""
+ Returns the friends directory of a user
+ """
+ def friends_dir(pk) do
+ manifest = %Manifest{name: "friends", owner: pk, public: false}
+ Shard.Manager.find_or_start manifest
+ end
end
diff --git a/shardweb/lib/controllers/directory_controller.ex b/shardweb/lib/controllers/directory_controller.ex
new file mode 100644
index 0000000..1e3a0b0
--- /dev/null
+++ b/shardweb/lib/controllers/directory_controller.ex
@@ -0,0 +1,29 @@
+defmodule ShardWeb.DirectoryController do
+ use ShardWeb, :controller
+
+ def view_pub(conn, %{"owner" => owner, "name" => name}) do
+ owner = Base.decode16! owner
+ shard = %SApp.Directory.Manifest{public: true, owner: owner, name: name}
+ pid = Shard.Manager.find_or_start shard
+
+ render conn, "view.html",
+ public: true,
+ shard: shard,
+ pid: pid,
+ owner: owner,
+ name: name
+ end
+
+ def view_priv(conn, %{"owner" => owner, "name" => name}) do
+ owner = Base.decode16! owner
+ shard = %SApp.Directory.Manifest{public: false, owner: owner, name: name}
+ pid = Shard.Manager.find_or_start shard
+
+ render conn, "view.html",
+ public: false,
+ shard: shard,
+ pid: pid,
+ owner: owner,
+ name: name
+ end
+end
diff --git a/shardweb/lib/controllers/identity_controller.ex b/shardweb/lib/controllers/identity_controller.ex
index 962a888..d1c6886 100644
--- a/shardweb/lib/controllers/identity_controller.ex
+++ b/shardweb/lib/controllers/identity_controller.ex
@@ -25,6 +25,40 @@ defmodule ShardWeb.IdentityController do
end
end
+ def view_post(conn, opts) do
+ IO.puts(inspect opts)
+ {:ok, pk} = Base.decode16(opts["pk"])
+ manifest = %SApp.Identity.Manifest{pk: pk}
+ nick = SApp.Identity.get_nick pk
+ shard = manifest |> SData.term_hash
+ pid = Shard.Manager.find_proc shard
+
+ if opts["add_friend"] == "true" do
+ friend_list = SApp.Directory.friends_dir(conn.assigns.pk)
+ name = nick <> " " <> Shard.Keys.pk_display(pk)
+ SApp.Directory.add_file(friend_list, name, manifest)
+ end
+
+ if opts["rm_friend"] == "true" do
+ friend_list = SApp.Directory.friends_dir(conn.assigns.pk)
+ name = SApp.Directory.find(friend_list, manifest)
+ if name != nil do
+ SApp.Directory.rm_file(friend_list, name)
+ end
+ end
+
+ if pid == nil do
+ render conn, ShardWeb.ErrorView, "404.html"
+ else
+ render conn, "view.html",
+ view_pk: pk,
+ view_nick: SApp.Identity.get_nick(pk),
+ shard: shard,
+ pid: pid
+ end
+ #TODO
+ end
+
def update(conn, params) do
pid = SApp.Identity.find_proc(conn.assigns.pk)
info = SApp.Identity.get_info(pid)
diff --git a/shardweb/lib/router.ex b/shardweb/lib/router.ex
index 981f946..eb1868f 100644
--- a/shardweb/lib/router.ex
+++ b/shardweb/lib/router.ex
@@ -24,11 +24,15 @@ defmodule ShardWeb.Router do
get "/people", IdentityController, :list
get "/people/:pk", IdentityController, :view
+ post "/people/:pk", IdentityController, :view_post
get "/identity", IdentityController, :self
post "/identity", IdentityController, :update
post "/identity/switch", IdentityController, :switch
post "/identity/create", IdentityController, :create
+ get "/pub/:owner/:name", DirectoryController, :view_pub
+ get "/priv/:owner/:name", DirectoryController, :view_priv
+
get "/chat/:chan", ChatController, :chat
get "/pm/:people_list", ChatController, :privchat
end
diff --git a/shardweb/lib/templates/directory/view.html.eex b/shardweb/lib/templates/directory/view.html.eex
new file mode 100644
index 0000000..b981391
--- /dev/null
+++ b/shardweb/lib/templates/directory/view.html.eex
@@ -0,0 +1,38 @@
+<!-- Page Heading -->
+<div class="row">
+ <div class="col-lg-12">
+ <h1 class="page-header">
+ <%= @name %>
+ <small>directory contents</small>
+
+ </h1>
+ <ol class="breadcrumb">
+ <li class="active">
+ <i class="fa fa-folder"></i> <%= @name %>
+ </li>
+ </ol>
+ </div>
+</div>
+<!-- /.row -->
+
+<%= render ShardWeb.LayoutView, "flashes.html", assigns %>
+
+<table class="table table-striped">
+ <tr>
+ <th>Name</th>
+ <th>Shard</th>
+ <th>Id</th>
+ </tr>
+ <%= for {name, manifest} <- dir_contents(@conn, @shard) do %>
+ <tr>
+ <td>
+ <strong><%= name %></strong>
+ </td>
+ <td>
+ <%= render ShardWeb.PageView, "shard_entry.html", conn: @conn, manifest: manifest %>
+ </td>
+ <td><small><%= (SData.term_hash manifest) |> Base.encode16 %></small></td>
+ </tr>
+ <% end %>
+</table>
+
diff --git a/shardweb/lib/templates/identity/view.html.eex b/shardweb/lib/templates/identity/view.html.eex
index 58be7e7..6cb1bde 100644
--- a/shardweb/lib/templates/identity/view.html.eex
+++ b/shardweb/lib/templates/identity/view.html.eex
@@ -18,6 +18,18 @@
<%= render ShardWeb.LayoutView, "flashes.html", assigns %>
+<%= if is_friend(@conn, @view_pk) do %>
+ <%= form_for @conn, identity_path(@conn, :view_post, @view_pk|>Base.encode16()), [class: "form-inline"], fn f -> %>
+ <%= hidden_input f, :rm_friend, value: "true" %>
+ <%= submit "Remove from friends", [class: "btn btn-sm btn-danger"] %>
+ <% end %>
+<% else %>
+ <%= form_for @conn, identity_path(@conn, :view_post, @view_pk|>Base.encode16()), [class: "form-inline"], fn f -> %>
+ <%= hidden_input f, :add_friend, value: "true" %>
+ <%= submit "Add to friends", [class: "btn btn-sm btn-success"] %>
+ <% end %>
+<% end %>
+
<pre>
<%= inspect(SApp.Identity.get_info(@pid), pretty: true, width: 40) %>
</pre>
diff --git a/shardweb/lib/templates/layout/app.html.eex b/shardweb/lib/templates/layout/app.html.eex
index 8d9924e..71a08f9 100644
--- a/shardweb/lib/templates/layout/app.html.eex
+++ b/shardweb/lib/templates/layout/app.html.eex
@@ -150,8 +150,13 @@
</ul>
</li>
+
+ <li class="<%= if @view_module == ShardWeb.DirectoryView and @view_template == "view.html" and not @public and @name == "friends" do "active" else "" end %>">
+ <a href="<%= directory_path(@conn, :view_priv, @pk|>Base.encode16(), "friends") %>"><i class="fa fa-fw fa-heart"></i> Friends</a>
+ </li>
+
<li class="<%= if (@view_module == ShardWeb.IdentityView and @view_template == "list.html") or (@view_module == ShardWeb.ChatView and @view_template == "chat.html" and not @public) do "active" else "" end %>">
- <a href="<%= identity_path(@conn, :list) %>"><i class="fa fa-fw fa-users"></i> People<i class="fa fa-fw fa-caret-down"></i></a>
+ <a href="<%= identity_path(@conn, :list) %>"><i class="fa fa-fw fa-users"></i> Everyone<i class="fa fa-fw fa-caret-down"></i></a>
<%= if (@view_module == ShardWeb.IdentityView and @view_template == "list.html") or (@view_module == ShardWeb.ChatView and @view_template == "chat.html" and not @public) do %>
<ul>
<%= for {id, %SApp.Chat.PrivChat.Manifest{pk_list: pk_list}, pid} <- shard_list() do %>
diff --git a/shardweb/lib/templates/page/shard_entry.html.eex b/shardweb/lib/templates/page/shard_entry.html.eex
new file mode 100644
index 0000000..8a55b3a
--- /dev/null
+++ b/shardweb/lib/templates/page/shard_entry.html.eex
@@ -0,0 +1,30 @@
+ <%= case @manifest do %>
+ <% %SApp.Identity.Manifest{pk: pk} -> %><i class="fa fa-user"></i>
+ <%= SApp.Identity.get_nick(pk) %>
+ <a href="<%= identity_path(@conn, :view, pk|>Base.encode16) %>">
+ <small><%= Shard.Keys.pk_display pk %></small>
+ </a>
+
+ <% %SApp.Chat.Manifest{channel: chan} -> %><i class="fa fa-hashtag"></i>
+ <a href="<%= chat_path(@conn, :chat, chan) %>">
+ <%= chan %>
+ </a>
+
+ <% %SApp.Chat.PrivChat.Manifest{pk_list: pk_list} -> %><i class="fa fa-comments"></i>
+ <a href="<%= chat_path(@conn, :privchat,
+ (pk_list |> Enum.filter(&(&1!=@pk)) |> Enum.map(&Base.encode16/1) |> Enum.join(","))) %>">
+ <%= pk_list |> Enum.filter(&(&1!=@pk)) |> Enum.map(&SApp.Identity.get_nick/1) |> Enum.join(", ") %>
+ </a>
+
+ <% %SApp.Directory.Manifest{owner: owner, public: public, name: name} -> %><i class="fa fa-folder"></i>
+ <%= SApp.Identity.get_nick(owner) %>
+ <a href="<%= identity_path(@conn, :view, owner|>Base.encode16) %>">
+ <small><%= Shard.Keys.pk_display owner %></small>
+ </a>
+ /
+ <a href="<%= directory_path(@conn, (if public do :view_pub else :view_priv end), owner|>Base.encode16(), name) %>"><%= name %></a>
+ <%= if public do %><i class="fa fa-globe"></i><% else %><i class="fa fa-lock"></i><% end %>
+
+
+ <% x -> %> <%= inspect x %>
+ <% end %>
diff --git a/shardweb/lib/templates/page/shard_list.html.eex b/shardweb/lib/templates/page/shard_list.html.eex
index 489c1a5..53f6264 100644
--- a/shardweb/lib/templates/page/shard_list.html.eex
+++ b/shardweb/lib/templates/page/shard_list.html.eex
@@ -35,36 +35,7 @@
<% end %>
</td>
<td>
- <%= case manifest do %>
- <% %SApp.Identity.Manifest{pk: pk} -> %><i class="fa fa-user"></i>
- <%= SApp.Identity.get_nick(pk) %>
- <a href="<%= identity_path(@conn, :view, pk|>Base.encode16) %>">
- <small><%= Shard.Keys.pk_display pk %></small>
- </a>
-
- <% %SApp.Chat.Manifest{channel: chan} -> %><i class="fa fa-hashtag"></i>
- <a href="<%= chat_path(@conn, :chat, chan) %>">
- <%= chan %>
- </a>
-
- <% %SApp.Chat.PrivChat.Manifest{pk_list: pk_list} -> %><i class="fa fa-comments"></i>
- <a href="<%= chat_path(@conn, :privchat,
- (pk_list |> Enum.filter(&(&1!=@pk)) |> Enum.map(&Base.encode16/1) |> Enum.join(","))) %>">
- <%= pk_list |> Enum.filter(&(&1!=@pk)) |> Enum.map(&SApp.Identity.get_nick/1) |> Enum.join(", ") %>
- </a>
-
- <% %SApp.Directory.Manifest{owner: owner, public: public, name: name} -> %><i class="fa fa-folder"></i>
- <%= SApp.Identity.get_nick(owner) %>
- <a href="<%= identity_path(@conn, :view, owner|>Base.encode16) %>">
- <small><%= Shard.Keys.pk_display owner %></small>
- </a>
- /
- <a href="#"><%= name %></a>
- <%= if public do %><i class="fa fa-globe"></i><% else %><i class="fa fa-lock"></i><% end %>
-
-
- <% x -> %> <%= inspect x %>
- <% end %>
+ <%= render "shard_entry.html", conn: @conn, manifest: manifest %>
</td>
<td><small><%= id |> Base.encode16 %></small></td>
</tr>
diff --git a/shardweb/lib/views/directory_view.ex b/shardweb/lib/views/directory_view.ex
new file mode 100644
index 0000000..9ebdd3b
--- /dev/null
+++ b/shardweb/lib/views/directory_view.ex
@@ -0,0 +1,9 @@
+defmodule ShardWeb.DirectoryView do
+ use ShardWeb, :view
+
+ def dir_contents(conn, manifest) do
+ IO.puts(inspect manifest)
+ pid = Shard.Manager.find_or_start manifest
+ SApp.Directory.get_files pid
+ end
+end
diff --git a/shardweb/lib/views/identity_view.ex b/shardweb/lib/views/identity_view.ex
index 1844ce8..86423b2 100644
--- a/shardweb/lib/views/identity_view.ex
+++ b/shardweb/lib/views/identity_view.ex
@@ -18,4 +18,9 @@ defmodule ShardWeb.IdentityView do
end
end)
end
+
+ def is_friend(conn, pk) do
+ fd = SApp.Directory.friends_dir(conn.assigns.pk)
+ SApp.Directory.find(fd, %SApp.Identity.Manifest{pk: pk}) != nil
+ end
end