Giter Site home page Giter Site logo

beaconcms / beacon_live_admin Goto Github PK

View Code? Open in Web Editor NEW
31.0 11.0 13.0 2.85 MB

Admin UI to manage content for sites built by Beacon

Home Page: https://beaconcms.org

License: MIT License

Elixir 97.32% CSS 0.11% JavaScript 1.79% HTML 0.79%
cms elixir elixir-lang phoenix phoenix-framework phoenix-liveview

beacon_live_admin's People

Contributors

apb9785 avatar christiantovar avatar gitkumi avatar hanna-del-rae avatar karthikmurali60 avatar kgautreaux avatar leandrocp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

beacon_live_admin's Issues

Revisions: add a copy button

On the Revisions tab in the Layouts or Pages interfaces, you can see the code editor displaying templates and Elixir code but there's no shortcut to copy such content. We want to add a copy button next to those elements using the beacon_admin:clipcopy event. The Media Library has implemented the same feature, that's a good example to check out.

Beacon.LiveAdmin.PageLive.mount/3 MatchError because session map is missing beacon_live_admin_page_url key

[error] #PID<0.1084.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.891.0>, stream id 29) terminated
Server: localhost:4001 (https)
Request: GET /admin/shell/pages
** (exit) an exception was raised:
    ** (MatchError) no match of right hand side value: %{"_csrf_token" => "02NPbENSTJ_tS9dtH-7XCTx7", "live_socket_id" => "users_sessions:OsOtaeAOGX4zWeTzFKvVL3auSZ_pi2vUYNK3hn6imhA=", "locale" => "en", "pages" => [{"/layouts", Beacon.LiveAdmin.LayoutEditorLive.Index, :index, %{}}, {"/layouts/new", Beacon.LiveAdmin.LayoutEditorLive.New, :new, %{}}, {"/layouts/:id", Beacon.LiveAdmin.LayoutEditorLive.Edit, :edit, %{}}, {"/layouts/:id/meta_tags", Beacon.LiveAdmin.LayoutEditorLive.MetaTags, :meta_tags, %{}}, {"/layouts/:id/revisions", Beacon.LiveAdmin.LayoutEditorLive.Revisions, :revisions, %{}}, {"/layouts/:id/resource_links", Beacon.LiveAdmin.LayoutEditorLive.ResourceLinks, :resource_links, %{}}, {"/pages", Beacon.LiveAdmin.PageEditorLive.Index, :index, %{}}, {"/pages/new", Beacon.LiveAdmin.PageEditorLive.New, :new, %{}}, {"/pages/:id", Beacon.LiveAdmin.PageEditorLive.Edit, :edit, %{}}, {"/pages/:id/meta_tags", Beacon.LiveAdmin.PageEditorLive.MetaTags, :meta_tags, %{}}, {"/pages/:id/schema", Beacon.LiveAdmin.PageEditorLive.Schema, :schema, %{}}, {"/pages/:id/revisions", Beacon.LiveAdmin.PageEditorLive.Revisions, :revisions, %{}}, {"/pages/:page_id/events", Beacon.LiveAdmin.PageEditorLive.EventHandlers, :events, %{}}, {"/pages/:page_id/events/:event_handler_id", Beacon.LiveAdmin.PageEditorLive.EventHandlers, :events, %{}}, {"/pages/:page_id/variants", Beacon.LiveAdmin.PageEditorLive.Variants, :variants, %{}}, {"/pages/:page_id/variants/:variant_id", Beacon.LiveAdmin.PageEditorLive.Variants, :variants, %{}}, {"/components", Beacon.LiveAdmin.ComponentEditorLive.Index, :index, %{}}, {"/components/new", Beacon.LiveAdmin.ComponentEditorLive.New, :new, %{}}, {"/components/:id", Beacon.LiveAdmin.ComponentEditorLive.Edit, :edit, %{}}, {"/media_library", Beacon.LiveAdmin.MediaLibraryLive.Index, :index, %{}}, {"/media_library/upload", Beacon.LiveAdmin.MediaLibraryLive.Index, :upload, %{}}, {"/media_library/:id", Beacon.LiveAdmin.MediaLibraryLive.Index, :show, %{}}], "user_token" => <<58, 195, 173, 105, 224, 14, 25, 126, 51, 89, 228, 243, 20, 171, 213, 47, 118, 174, 73, 159, 233, 139, 107, 212, 96, 210, 183, 134, 126, 162, 154, 16>>}
        (beacon_live_admin 0.1.0-dev) lib/beacon/live_admin/page_live.ex:29: Beacon.LiveAdmin.PageLive.mount/3
        (phoenix_live_view 0.19.5) lib/phoenix_live_view/utils.ex:394: anonymous fn/6 in Phoenix.LiveView.Utils.maybe_call_live_view_mount!/5
        (telemetry 1.2.1) /Users/kaygee/Sites/swell/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
        (phoenix_live_view 0.19.5) lib/phoenix_live_view/static.ex:278: Phoenix.LiveView.Static.call_mount_and_handle_params!/5
        (phoenix_live_view 0.19.5) lib/phoenix_live_view/static.ex:119: Phoenix.LiveView.Static.render/3
        (phoenix_live_view 0.19.5) lib/phoenix_live_view/controller.ex:39: Phoenix.LiveView.Controller.live_render/3
        (phoenix 1.7.7) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
        (swell 1.5.2) lib/swell_web/endpoint.ex:1: SwellWeb.Endpoint.plug_builder_call/2
        (swell 1.5.2) deps/plug/lib/plug/debugger.ex:136: SwellWeb.Endpoint."call (overridable 3)"/2
        (swell 1.5.2) lib/swell_web/endpoint.ex:1: SwellWeb.Endpoint.call/2
        (phoenix 1.7.7) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
        (plug_cowboy 2.6.1) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
        (cowboy 2.10.0) /Users/kaygee/Sites/swell/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.10.0) /Users/kaygee/Sites/swell/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
        (cowboy 2.10.0) /Users/kaygee/Sites/swell/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
        (stdlib 5.0.2) proc_lib.erl:241: :proc_lib.init_p_do_apply/3

I get this error even if I add the on_mount option to the router for beacon_admin_site and log in successfully. This error also occurs on layouts, components, and media library.

I don't think this is a node connection issue because I can see the site on the root admin page but clicking on the button to navigate to the PageLive live_view blows up.

I did some inspection of the tuple returned from Beacon.LiveAdmin.Router.__session_options__/3 and indeed there isn't a "beacon_live_admin_page_url" key in there.

I put a dbg(session) into the Beacon.LiveAdmin.PageLive.mount/3 and got this:

[(beacon_live_admin 0.1.0-dev) deps/beacon_live_admin/lib/beacon/live_admin/page_live.ex:29: Beacon.LiveAdmin.PageLive.mount/3]
session #=> %{
  "_csrf_token" => "redacted",
  "live_socket_id" => "users_sessions:redacted",
  "locale" => "en",
  "pages" => [
    {"/layouts", Beacon.LiveAdmin.LayoutEditorLive.Index, :index, %{}},
    {"/layouts/new", Beacon.LiveAdmin.LayoutEditorLive.New, :new, %{}},
    {"/layouts/:id", Beacon.LiveAdmin.LayoutEditorLive.Edit, :edit, %{}},
    {"/layouts/:id/meta_tags", Beacon.LiveAdmin.LayoutEditorLive.MetaTags,
     :meta_tags, %{}},
    {"/layouts/:id/revisions", Beacon.LiveAdmin.LayoutEditorLive.Revisions,
     :revisions, %{}},
    {"/layouts/:id/resource_links",
     Beacon.LiveAdmin.LayoutEditorLive.ResourceLinks, :resource_links, %{}},
    {"/pages", Beacon.LiveAdmin.PageEditorLive.Index, :index, %{}},
    {"/pages/new", Beacon.LiveAdmin.PageEditorLive.New, :new, %{}},
    {"/pages/:id", Beacon.LiveAdmin.PageEditorLive.Edit, :edit, %{}},
    {"/pages/:id/meta_tags", Beacon.LiveAdmin.PageEditorLive.MetaTags,
     :meta_tags, %{}},
    {"/pages/:id/schema", Beacon.LiveAdmin.PageEditorLive.Schema, :schema, %{}},
    {"/pages/:id/revisions", Beacon.LiveAdmin.PageEditorLive.Revisions,
     :revisions, %{}},
    {"/pages/:page_id/events", Beacon.LiveAdmin.PageEditorLive.EventHandlers,
     :events, %{}},
    {"/pages/:page_id/events/:event_handler_id",
     Beacon.LiveAdmin.PageEditorLive.EventHandlers, :events, %{}},
    {"/pages/:page_id/variants", Beacon.LiveAdmin.PageEditorLive.Variants,
     :variants, %{}},
    {"/pages/:page_id/variants/:variant_id",
     Beacon.LiveAdmin.PageEditorLive.Variants, :variants, %{}},
    {"/components", Beacon.LiveAdmin.ComponentEditorLive.Index, :index, %{}},
    {"/components/new", Beacon.LiveAdmin.ComponentEditorLive.New, :new, %{}},
    {"/components/:id", Beacon.LiveAdmin.ComponentEditorLive.Edit, :edit, %{}},
    {"/media_library", Beacon.LiveAdmin.MediaLibraryLive.Index, :index, %{}},
    {"/media_library/upload", Beacon.LiveAdmin.MediaLibraryLive.Index, :upload,
     %{}},
    {"/media_library/:id", Beacon.LiveAdmin.MediaLibraryLive.Index, :show, %{}}
  ],
  "user_token" => <<redacted>>
}

I'm not sure why the session map passed to mount/3 in PageLive doesn't include the "beacon_live_admin_page_url".

Can anyone provide any insight?

General Improvements: Provide a visual indication of the current "Variant" and "Event" being edited

On the Variant and Event subpages, the page initially starts off very blank. Once you click "Add a variant" or "Add an event" you start creating a list of items on the panel on the left, and their default name is always the same. When you select one to start editing, there is no visual indication of the current selection.

Small adjustments I'd like to propose that would go a long way in improving the user experience here includes:

  • Adding a fallback, or empty state to the page when the list is empty. A message like "No Events created yet. Click the button to get started" is better than a blank screen.
  • Add a visual indication such as a subtle background color, and an accented font color to the current/selected event or variant in the list.

Screenshot 2023-09-15 at 8 46 47 AM

Manage Page events

Create and edit Page.Events in the Page Editor

This is a embeded field which may cause some issues and can be converted to a regular relational table, similar to Content.PageVariant, but it will conflict with the existing PageEvent schema so we need to find a way to accommodate both schemas.

Asset Manager Page: Pages using assets

As a PO, I would like to know which pages are using exact assets. We should be able to show which pages are using a given asset, maybe even a grouping feature

Hosting and Tenant: Add site selector on navbar

A single admin instance may manage multiple sites so we want to display a site selector in the navbar displaying all running sites which will redirect to the a chosen site.

Note that we don't currently have a dashboard or a main page for each site, so it can redirect to the /layouts page for the given site.

General Improvements: Improve the user experience within the Medial Uploader modal

Screenshot 2023-09-01 at 2 24 56 PM

User experience questions

In the above instance, I have already uploaded a test file, shown in the thumbnail. But the uploader message is still "Choose a file, No file chosen" which leaves me wondering if the file is not actually queued, or if it's asking me to upload a second image, or would selecting the "choose a file" button override the image I just uploaded?

A second pain point in this modal is the lack of a clear path forward from this state. The only option is the "X"in the top right corner, but it's unclear whether that will "save and close" or "delete and close" my changes. Some options I think users would expect to see include "Save" (which would also close the modal and return me to the library), "Delete Image" which would clear the selected image but not close the modal and "Close without saving"

Tidying

Import Livebook .livemd files

The .livemd files generated by Livebook can be used to write pages for Beacon since it's essentially markdown files as long as they are exported with outputs.

So we want to:

  • Add a new button "IMPORT LIVEBOOK" in the New Page /pages/new
  • Add the same button in the Edit Page /pages/:id

That button will accept the upload of .livemd files, fill the page template with the file content, and change the template format to "Livemd (Livebook)" (see below).

We need to add a new template format named :livemd along with :heex and :md to differentiate this kind of content and allow further customizations in the future.

Layouts: Sorting and Pagination

Rules

  • Sort by title, status
  • Paginate by page, 20 records by page
  • Use query params to preserve state as ?query=FOO&page=INT&sort=NAME
  • Searching should reset pagination to page 1 and preserve sort query param and current state
  • Paginating should preserve search query and sort params and their current state
  • Display a navigation bar like this one below:

Image

Related code

def list_layouts(site, opts \\ []) do

https://github.com/BeaconCMS/beacon/blob/cbe3bf7445cc559c96310593105e710366ed2cea/lib/beacon/content.ex#L302

General Improvements: Create and modify data source at runtime

Beacon live data source is currently defined as a module in the host application but that impose a couple of problems:

  1. Require Elixir knowledge to change values, even scalar basic values like a person name or a number;
  2. Require redeployment, which goes against Beacon's main proposal;
  3. Templates get out of sync causing crashes, suppose you change an assign name in a template. That change requires changing the data source but the template will break until the data source is deployed, and doing the operation operation (changing the data source first) will also crash the template until the updated page is published.

For those reasons, we need to to:

  • Add a new tab in the Pages page to allow users to create/edit the data source for a given page;
  • Version the data source along with the template (the whole page) so changes on either one goes together;

The layout for that page may contain:

The data type allows us to display the correct "content" field.

Page Variants: Add option to render a specific variant via query param

One idea which came up during the original conversation with Brian around the page variants feature:

If we want to force a page to use a specific variant, we could pass a query param to specify which one.

So for example if a page deployed at mysite.com/blog has a variant named "featured_on_top" then one could force rendering that specific variant by visiting mysite.com/blog?variant=featured_on_top

See https://github.com/BeaconCMS/beacon/blob/cbe3bf7445cc559c96310593105e710366ed2cea/lib/beacon/template.ex#L63-L69

Page Revisions: increase preview code modal size

On the Page Revisions tab you can see the variants and event handler code in a modal, but that modal is too small to properly inspect and read the code. We want to increase the height and width of that modal to around 70% or 80% of the viewport size.

Variants on Revisions page

Page Variants are saved in the snapshots, but currently not shown in the Revisions page content.

In order to prevent the Revisions page from growing too long, we should either:

  • re-use the existing body template code block, with a selector to switch between showing the primary template and variant template
  • use a modal to display variant templates

General Improvements: Add a visual feedback on save operations

Clicking on "Save Changes" on most pages won't display a flash message or any other visual feedback to tell the user if the operations has succeed or failed. That happens because there's no page redirect so the flash message isn't displayed.

We want to research a solution that's simple and capable of improving UX by displaying some visual feedback to users.

Components and Pages: PageEventHandlers: validate event handler code

The code inserted into the page event handler is not validated which imposes some risks, including breaking the site with a malformed code. Similar to what is done with HEEx templates, we want to validate that code is semantically correct, ie: it compiles.

We could validate the code with something like Code.compile_string/2

Only issue is that the code expects a variable event_params to exist and be a map. Since this variable is only created when the code is injected into the Page module, it will not be available during validation. One solution could be to append a dummy variable assignment just for validation i.e.

to_validate = "event_params = %{}\n" <> event_handler_code

Media Library: Sorting and Pagination

Rules

  • Sort by name, type
  • Paginate by page, 20 records by page
  • Use query params to preserve state as ?query=FOO&page=INT&sort=NAME
  • Searching should reset pagination to page 1 and preserve sort query param and current state
  • Paginating should preserve search query and sort params and their current state
  • Display a navigation bar like this one below:

Image

Related code

https://github.com/BeaconCMS/beacon/blob/cbe3bf7445cc559c96310593105e710366ed2cea/lib/beacon/media_library.ex#L174

Webfiles and Metatags: Upload and serve app icons

Managing app icons may be complex and time consuming for end users. We want to 1) have a page on beacon admin to upload icons, and 2) generate the html tags for displaying such icons.

upload icons on beacon admin

Ideally users would upload a high-res .svg file that beacon can convert to:

  • 1 favicon.ico with 2 layers 32x32 and 16x16
  • apple-touch-icon.png size 180x180
  • icon-192.png size 192x192
  • icon-512.png size 512x512
  • optimized icon.svg

We may allow users uploading individual files, either to overwrite the generated one or because users may not have the high-res .svg file.

display icons

The expected tags are:

<link rel="icon" href="{site_prefix}/favicon.ico" sizes="any">
<link rel="icon" href="{site_prefix}/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="{site_prefix}/apple-touch-icon.png"><!-- 180ร—180 -->
<link rel="manifest" href="{site_prefix}/manifest.webmanifest">

Note that {site_prefix} has to be replaced with router(conn).__beacon_site_prefix__(site), see asset_path/2 for example.

Refs

Read https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs for the full explanation.

Extra:

General Improvements: Add support for multiple button style variants to the button component

In the design system we have several variations of buttons, so I'd like to add support for these variants without needing to create a new component but modifying the existing component to render different styles based on the button type.

There are many places in the recent updates to the admin where we have large blue (primary) buttons where a more discreet secondary or tertiary button would be more fitting, since its not a primary action.

Also include support for an accessible icon-only button.

Admin -> General Improvements: a/b/c/d/e/f/etc... testing spec

Beacon should be able to support multiple variants of a given URL and be able to set weights on the render frequency.

The variants should be infinite. When visiting the URL the variants are not present in the URL however we could selectively render a given variant with a query param:

https://dockyard.com/campaign-page?variant=a

something like that

for analytics and conversion testing we can embed the variant name.

Preview changes before publishing

The UX when authoring layouts and pages is not that great currently. In order to make changes I have to first press "save changes" followed by a "publish" and then reload my browser window to see the changes I did.

It would be much nicer to be able to preview the changes while editing without having to publish and refresh.

Some other random feedback:

  • Some high level docs describing the core concepts would be nice
  • Make the demo app a little fancier, it is so barebones right now that you almost question if it is working or not when seeing it fro the firs time :)

Editor: Extend markdown to support HEEx features

Regular Markdown converter isn't capable of handling HEEx features. We want a subset of a regular Markdown that is capable of parsing and generating valid HEEx without losing features or breaking the compilation.

Function components

Beacon provides function components to display assets and will provide components for building pages, for eg:

<div>
  <BeaconWeb.Components.image name="my_image.png" />
</div>

Using such component should generate the expected HTML tags as it would in a HEEx template.

Navigation

A regular markdown link should probably generate the same markup as <.link navigate=..."> to include the phx-* attributes and allow it to transition pages efficiently, otherwise it triggers a redirect.

Research

MDX is a great solution for the JS ecosystem and we it can serve as inspiration to build something similar in Elixir.

The library md may be is capable of embedding heex but it doesn't support the CommonMark spec.

So a new library mdex was created to support what is needed for Beacon, but loading Phoenix Components is still a WIP.

Live svelte not rendering svelte component. Browser shows `unknown hook found for "SvelteHook"`

I'm trying the project on my live_view app and getting... well, not very far.

/assets/svelte/HelloSvelte.svelte looks like this:

<script>
  alert('Does this work????');
</script>
<h1>I'm the hello world</h1>

On my live_view template I render it like this:

      <%= if @visual_mode do %>
        Before svelte component
        <.svelte name="HelloSvelte" props={%{foo: "bar"}} socket={@socket} />
        After svelte component
      <% else %>
        ...
      <%.end %>

After following the install steps, the app runs without any errors on the phoenix side of things, but nothing renders. The browser's console does show an error message: unknown hook found for "SvelteHook.

What may I be missing?

Asset Manager Page: Used/Not used assets

As a PO I'd like to know a list of assets that are currently in use/not in use. We should be able to show a list of all assets that are currently in use and not in use

Components: search

Add a search input to Components page to search by "name". Similar to the search on Layouts and Pages.

Editor: Editing URL after publishing

Allow users to republish a page under a new path. It needs to:

  • Delete the old page from the router
  • Publish the new page version as usual
  • Perform a 301 redirect from the older path to the new one extracted as a new feature, see #97 so when editing a published URL it should generate a new record in the URL Redirect manager.

Route and Resource Loading: Layout Resource Links - remove empty keys

Given this configuration for Resource Links:
Screenshot 2023-08-29 at 9 39 11 AM

It will generate:

<link as="" crossorigin="" href="https://cdn.mysite.com" rel="preconnect" type="">
<link as="font" crossorigin="anonymous" href="https://cdn.mysite.com/font.woff2" rel="preload" type="font/woff2">

But it should remove the keys that have a null or "" value, generating:

<link href="https://cdn.mysite.com" rel="preconnect">
<link as="font" crossorigin="anonymous" href="https://cdn.mysite.com/font.woff2" rel="preload" type="font/woff2">

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.