diff --git a/assets/components/categories.jsx b/assets/components/categories.jsx
index 3e61ee5..86fd761 100644
--- a/assets/components/categories.jsx
+++ b/assets/components/categories.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react'
+import React from 'react'
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
import {
CheckIcon,
diff --git a/assets/components/commands.jsx b/assets/components/commands.jsx
index 7b07e95..d544beb 100644
--- a/assets/components/commands.jsx
+++ b/assets/components/commands.jsx
@@ -1,22 +1,7 @@
import React, { useState, useEffect } from 'react'
-import { createRoot } from "react-dom/client";
+import { createRoot } from "react-dom/client"
import { motion, useAnimate, stagger } from 'framer-motion'
-const container = {
- hidden: { opacity: 0 },
- show: {
- opacity: 1,
- transition: {
- staggerChildren: 0.1
- }
- }
-}
-
-const character = {
- hidden: { opacity: 0 },
- show: { opacity: 1 }
-}
-
const tabs = [
{
title: 'Logs',
diff --git a/assets/components/products.jsx b/assets/components/products.jsx
new file mode 100644
index 0000000..c4e2425
--- /dev/null
+++ b/assets/components/products.jsx
@@ -0,0 +1,47 @@
+import React from 'react'
+import { createRoot } from "react-dom/client"
+import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
+import {
+ CheckIcon,
+ ChevronUpDownIcon,
+} from '@heroicons/react/16/solid'
+
+function Products({ products, interval, selected }) {
+ return (
+
+ )
+}
+
+export function mountProducts() {
+ const domNode = this.el;
+ const root = createRoot(domNode);
+ let { products, interval, selected } = this.el.dataset;
+
+ products = JSON.parse(products);
+
+ root.render()
+}
\ No newline at end of file
diff --git a/assets/js/app.jsx b/assets/js/app.jsx
index 383b2cf..7a4f88d 100644
--- a/assets/js/app.jsx
+++ b/assets/js/app.jsx
@@ -35,6 +35,7 @@ import { Technologies } from '../components/technologies';
import { SSHAccess } from '../components/access';
import { Timeline } from '../components/rollback';
import { mountCommands } from '../components/commands';
+import { mountProducts } from '../components/products';
function mountTimeline() {
const domNode = this.el;
@@ -169,6 +170,11 @@ Hooks.MountCategories = {
updated: mountCategories,
}
+Hooks.MountProducts = {
+ mounted: mountProducts,
+ updated: mountProducts,
+}
+
let csrfToken = document
.querySelector("meta[name='csrf-token']")
.getAttribute("content");
diff --git a/lib/opsmaru/content/product.ex b/lib/opsmaru/content/product.ex
index 5ca78d1..b833004 100644
--- a/lib/opsmaru/content/product.ex
+++ b/lib/opsmaru/content/product.ex
@@ -2,6 +2,8 @@ defmodule Opsmaru.Content.Product do
use Ecto.Schema
import Ecto.Changeset
+ @derive {Jason.Encoder, only: [:index, :reference, :name]}
+
@valid_attrs ~w(id index reference name)a
embedded_schema do
diff --git a/lib/opsmaru_web/components/pricing_components.ex b/lib/opsmaru_web/components/pricing_components.ex
index 61f63b5..55568ee 100644
--- a/lib/opsmaru_web/components/pricing_components.ex
+++ b/lib/opsmaru_web/components/pricing_components.ex
@@ -111,6 +111,7 @@ defmodule OpsmaruWeb.PricingComponents do
attr :products, :list, required: true
attr :features, :list, required: true
attr :product_features, :list, required: true
+ attr :focus_product, :string, default: nil
def matrix(assigns) do
~H"""
@@ -120,7 +121,9 @@ defmodule OpsmaruWeb.PricingComponents do
<.display
:for={product <- @products}
+ product={product}
feature={feature}
+ focus_product={@focus_product}
product_feature={match_product_feature(@product_features, product, feature)}
/>
@@ -128,11 +131,16 @@ defmodule OpsmaruWeb.PricingComponents do
end
attr :feature, Content.Feature, required: true
+ attr :product, Content.Product, required: true
attr :product_feature, Products.Feature, default: nil
+ attr :focus_product, :string, default: nil
def display(assigns) do
~H"""
-
+ |
{@product_feature.remark}
diff --git a/lib/opsmaru_web/live/blog_live/index.ex b/lib/opsmaru_web/live/blog_live/index.ex
index 4c334b8..0b385bd 100644
--- a/lib/opsmaru_web/live/blog_live/index.ex
+++ b/lib/opsmaru_web/live/blog_live/index.ex
@@ -48,7 +48,7 @@ defmodule OpsmaruWeb.BlogLive.Index do
diff --git a/lib/opsmaru_web/live/pricing_live.ex b/lib/opsmaru_web/live/pricing_live.ex
index 911c72f..7c4bd02 100644
--- a/lib/opsmaru_web/live/pricing_live.ex
+++ b/lib/opsmaru_web/live/pricing_live.ex
@@ -45,6 +45,7 @@ defmodule OpsmaruWeb.PricingLive do
attr :main_nav, Content.Navigation, required: true
attr :interval, :string, default: "month"
attr :products, :list, default: []
+ attr :focus_product, :string, default: nil
def render(assigns) do
~H"""
@@ -124,7 +125,15 @@ defmodule OpsmaruWeb.PricingLive do
-
+
+
|
<.link
@@ -162,6 +171,7 @@ defmodule OpsmaruWeb.PricingLive do
|
@@ -219,7 +229,7 @@ defmodule OpsmaruWeb.PricingLive do
end
@impl true
- def handle_params(%{"interval" => interval}, _uri, %{assigns: assigns} = socket) do
+ def handle_params(%{"interval" => interval} = params, _uri, %{assigns: assigns} = socket) do
prices = load_prices(interval)
active_products_names = Enum.map(prices, & &1.product.name)
@@ -232,16 +242,19 @@ defmodule OpsmaruWeb.PricingLive do
product.reference in active_products_names
end)
+ focus_product = Map.get(params, "product", List.first(products).reference)
+
socket =
socket
|> assign(:prices, prices)
|> assign(:interval, interval)
|> assign(:products, products)
+ |> assign(:focus_product, focus_product)
{:noreply, socket}
end
- def handle_params(_, _uri, %{assigns: assigns} = socket) do
+ def handle_params(params, _uri, %{assigns: assigns} = socket) do
prices = load_prices()
active_products_names = Enum.map(prices, & &1.product.name)
@@ -253,11 +266,14 @@ defmodule OpsmaruWeb.PricingLive do
product.reference in active_products_names
end)
+ focus_product = Map.get(params, "product", List.first(products).reference)
+
socket =
socket
|> assign(:prices, prices)
|> assign(:interval, "month")
|> assign(:products, products)
+ |> assign(:focus_product, focus_product)
{:noreply, socket}
end
|