To Masu 0.6
Masu 0.6 brings the filter bar: a grid's filters show above it as chips that open their filter, with Add filter, and each header has one menu, its ⋯, with its sorts, the app's items, Group by and its filter. A grid has it unless it says otherwise, so every grid gets a line above it and ⋯ in place of the funnel on its headers. See Filters.
Steps
Update
{:masu, "~> 0.6"}.Choose each grid's header. Nothing else changes, and a grid that keeps the default needs nothing. For a grid in a small place, or to keep the look of 0.5:
-<.data_grid id="orders" source={Order} repo={Repo}> +<.data_grid id="orders" source={Order} repo={Repo} filter_bar={false}>header_filters={false}keeps the filters in the bar alone.Tests and styles that read the header. A filtered column's funnel (
.masu-filter-button[data-active]) is the leaner header's only; with the filter bar, its chip says it. A header menu's items begin with its sorts. A group's chip ends with a × drawn as an icon, not the text "×".Translations: add
add_filter,no_columnsandsort_clearto a grid'smessages(Masu.Messages.defaults/0has every key).
To Masu 0.5
Masu 0.5 hands what is the room's to Issho
0.3, as Kotoba 0.7 and Hakushi 0.3 do: following someone, and how agents
move. A grid without issho needs nothing.
Why
- Following is the room's, not the grid's. In 0.4 a grid followed someone on its own: on a page with a grid, a text and a canvas, following Ada in the grid left the text and the canvas where they were. Following is now Issho's: follow Ada from the page's people list or the grid's avatars, and the grid shows her view, the canvas her viewport and the text her caret, and the page scrolls to her. A grid alone on a page follows within itself, as before.
- Agents move as people do, everywhere alike. An agent goes to each
cell it edits and types in it before the value lands, selects a range as
a drag does, and its pointer goes from the text to the grid as one. Only
where it goes is sent; each browser draws the way; and it moves only for
someone who sees it (
Issho.Motion).
What changes
| 0.4 | 0.5 |
|---|---|
| a grid followed someone on its own | following is the room's (data-issho-following, the issho:following event): the grid's avatars, the page's people list and every block of the room agree |
| scrolling or a key in the grid stopped following in the grid | it stops following in the room |
config :masu, Masu.Issho, pace: 120: the agent saved, then waited | the agent goes to the cell (travel, true), "types" for pace, then saves; pace: 0, travel: false for changes at once |
{:issho, "~> 0.2"} | {:issho, "~> 0.3"} |
issho={[instance: MyApp.Issho, room: "orders"]} (the grid's place "orders/<its id>") | issho={[instance: MyApp.Issho, document: "orders"]}: the keys of every component (Issho.Join); the grid's document is its name, whose room is the part before the first "/" |
people={false}, follow={false} | issho={[..., people: false, follow: false]} |
the grid's "masu" key at the top of a person's state | under the grid's document, in "blocks" |
a Masu.Write had no author | its by: an Issho.Identity on a grid with issho, else the grid's user; each saved write emits "document.changed" in the room |
The grid's markup is the same: its avatars carry data-issho-follow-control,
so that pressing one is not taken for the person going their own way.
Steps
Update
{:masu, "~> 0.5"}and{:issho, "~> 0.3"}.Load Issho's script on the page, if it is not there yet: following across the page, and the pointers, are its (
Hooksfromissho, in your LiveSocket). A grid follows within itself without it.Join with
document.room:, and thepeopleandfollowattributes, raise with what to write instead:-<.data_grid id="orders" ... issho={[instance: MyApp.Issho, room: "orders"]} follow={false} user={@user} /> +<.data_grid id="orders" ... issho={[instance: MyApp.Issho, document: "orders", follow: false]} user={@user} />A grid's document is what its place in the room was:
"orders/orders"for a gridordersin the room"orders"before, so give itdocument: "orders/orders"to keep its people's places, or a name of your own ("orders", a room of its own).List the page's people once:
Issho.Components.people/1, andissho'speople: falseon the grid, on a page with several blocks in the room. A click on someone there follows them.Agents' tools name a grid by its document already (
"notebook:42/tasks"): nothing changes.
To Masu 0.4
Masu 0.4 moves a grid's people onto Issho,
collaboration for Phoenix, as Kotoba 0.6 moves its shared editing there,
and as Hakushi was built. A grid that shows no people works exactly as
before: rows, sources, scrolling, queries, editing, history, views and
live rows are unchanged, and need nothing.
This guide is for a grid with presence: the avatars above it, each
person's cell, the cell someone types in, following someone.
Why
Masu 0.3 kept its people in Phoenix.Presence, on its own. That was
enough for one grid on a page, and it was the only thing it could do:
- A page has one set of people. A page with a grid, a text and a
canvas showed three lists of people, three colors for one person, and
three ways of saying who may be there. In an Issho room it shows one:
one list (
Issho.Components.people/1), one color for each person on every part of the page, and the same people in the grid as in the editor beside it. - The room's policy says who is there.
presenceshowed whoever had the topic open. An Issho room asks your policy (Issho.Policy) who may join, read, write and hold a cell, on join and again as they work, and takes out someone whose access you take away. - Agents. In an Issho room an agent is someone: it reads the grid,
points at cells, edits them, adds and deletes rows the grid's way (its
changeset, its read-only rules, the compare of a cell changed
meanwhile, its history), the people see it on its cell, and its rows
flash in its color. It reaches your app however you like: MCP, your
app's own model, a job (
Masu.Issho,Masu.Sheet). - The page as a live space. Issho draws each person's pointer over
the whole page (
Issho.Components.pointers/1), and an agent at work in the grid at its corner. - What comes next is Issho's. Following someone from page to page, a grid inside a text or a canvas, a grid of another app or another cluster: Issho's roadmap, which a grid in a room gets as it comes, rather than each library building its own.
Masu keeps what is Masu's: the rows. They come from your database, in
blocks, as the person scrolls, and live brings the others' changes as
they land, as before. Issho carries only who is there and where.
What changes
| 0.3 | 0.4 |
|---|---|
presence={MyAppWeb.Presence} | issho={[instance: MyApp.Issho, room: "orders"]} |
on_mount Masu.Live | on_mount Masu.Live and on_mount Issho.Live |
Masu.Presence.color/1, a palette of eight in Masu | Issho's colors: a person's own, or their color of the room's palette in Issho's theme (issho.css, --issho-person-1 to -8) |
| a person with no color flashes rows in Masu's palette | in the room's color; with live and no room, in their own color, or the grid's default flash |
user, share_view, the :person slot, configure({peerLabel}), the
.masu-peer elements and their CSS, and the messages are as they were.
A grid given presence raises, and says what to give it instead.
Steps
Add Issho to your dependencies:
{:masu, "~> 0.4"}, {:issho, "~> 0.2"}Start it in your supervision tree, after the PubSub, with a policy:
{Issho, name: MyApp.Issho, pubsub: MyApp.PubSub, policy: MyApp.Collaboration}defmodule MyApp.Collaboration do @behaviour Issho.Policy # Whoever could open the grid's page may be in its room. @impl true def authorize(%Issho.Identity{key: user_id}, "orders", _action), do: if(MyApp.Accounts.member?(user_id), do: :ok, else: {:error, :forbidden}) def authorize(_identity, _room, _action), do: {:error, :forbidden} @impl true def document(_identity, _id), do: {:error, :not_found} endA grid needs no Issho socket: its LiveView is the room's session. Mount Issho's channel (see Issho's README) when the page has Kotoba editors or Issho's people list or pointers, whose browsers join the room themselves.
Add Issho's hook next to Masu's:
live_session :default, on_mount: [Masu.Live, Issho.Live] doGive the grid its room instead of
presence:<.data_grid id="orders" source={Order} repo={Repo} changeset={&Order.changeset/2} live={{MyApp.PubSub, "orders"}} - presence={MyAppWeb.Presence} + issho={[instance: MyApp.Issho, room: "orders"]} user={%{id: @current_user.id, name: @current_user.name}} >Keep
live: it is the rows. When the room knows the person by your user struct (anIssho.Actorof your own, as your Kotoba editors use), give it asactor(issho={[instance: ..., room: ..., actor: @current_user]}), so the person is the same one in every part of the page.Load Issho's theme, for the room's colors:
issho.css(andissho-sumi.cssafter it for the Sumi theme), or your own--issho-person-1to--issho-person-8.Remove your
Phoenix.Presencemodule, if the grid was all it was for.
Then
- Give the grid's agents their tools:
Masu.Issho.tools/0, with Issho's room tools, over MCP or to your own model (see Collaboration). - On a page with several parts in the room, list its people once
(
Issho.Components.people/1) and give the gridpeople={false}. - Show the pointers of the page's people:
Issho.Components.pointers/1.