diff options
-rw-r--r-- | shard/lib/app/directory.ex | 45 | ||||
-rw-r--r-- | shardweb/lib/controllers/directory_controller.ex | 29 | ||||
-rw-r--r-- | shardweb/lib/controllers/identity_controller.ex | 34 | ||||
-rw-r--r-- | shardweb/lib/router.ex | 4 | ||||
-rw-r--r-- | shardweb/lib/templates/directory/view.html.eex | 38 | ||||
-rw-r--r-- | shardweb/lib/templates/identity/view.html.eex | 12 | ||||
-rw-r--r-- | shardweb/lib/templates/layout/app.html.eex | 7 | ||||
-rw-r--r-- | shardweb/lib/templates/page/shard_entry.html.eex | 30 | ||||
-rw-r--r-- | shardweb/lib/templates/page/shard_list.html.eex | 31 | ||||
-rw-r--r-- | shardweb/lib/views/directory_view.ex | 9 | ||||
-rw-r--r-- | shardweb/lib/views/identity_view.ex | 5 |
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 |