~emersion/drmdb

f521d824c938a39e4c8148b6921444d61e0df3b3 — Simon Ser 2 years ago 5d97779
Add a property page
6 files changed, 165 insertions(+), 37 deletions(-)

M drmtree/drmtree.go
M public/assets/style.css
M public/properties.html
A public/property.html
M server.go
M template.go
M drmtree/drmtree.go => drmtree/drmtree.go +43 -35
@@ 191,6 191,39 @@ func (mode *Mode) String() string {
	return mode.Name
}

type prettyUint64 uint64

func (u prettyUint64) String() string {
	switch uint64(u) {
	case math.MaxUint64:
		return "UINT64_MAX"
	case math.MaxUint32:
		return "UINT32_MAX"
	case math.MaxInt64:
		return "INT64_MAX"
	case math.MaxInt32:
		return "INT32_MAX"
	default:
		return fmt.Sprintf("%v", uint64(u))
	}
}

type prettyInt64 int64

func (i prettyInt64) String() string {
	if i > 0 {
		return prettyUint64(i).String()
	}
	switch int64(i) {
	case math.MinInt64:
		return "INT64_MIN"
	case math.MinInt32:
		return "INT32_MIN"
	default:
		return fmt.Sprintf("%v", int64(i))
	}
}

type PlaneInFormatsModifier struct {
	Modifier drm.Modifier `json:"modifier"`
	Formats  []drm.Format `json:"formats"`


@@ 206,11 239,19 @@ type PropertySpecRange struct {
	Max uint64 `json:"max`
}

func (spec *PropertySpecRange) String() string {
	return fmt.Sprintf("[%v, %v]", prettyUint64(spec.Min), prettyUint64(spec.Max))
}

type PropertySpecSignedRange struct {
	Min int64 `json:"min"`
	Max int64 `json:"max`
}

func (spec *PropertySpecSignedRange) String() string {
	return fmt.Sprintf("[%v, %v]", prettyInt64(spec.Min), prettyInt64(spec.Max))
}

type Property struct {
	ID        drm.PropertyID   `json:"id"`
	Type      drm.PropertyType `json:"type"`


@@ 349,39 390,6 @@ func (m *PropertyMap) UnmarshalJSON(b []byte) error {
	return nil
}

type prettyUint64 uint64

func (u prettyUint64) String() string {
	switch uint64(u) {
	case math.MaxUint64:
		return "UINT64_MAX"
	case math.MaxUint32:
		return "UINT32_MAX"
	case math.MaxInt64:
		return "INT64_MAX"
	case math.MaxInt32:
		return "INT32_MAX"
	default:
		return fmt.Sprintf("%v", uint64(u))
	}
}

type prettyInt64 int64

func (i prettyInt64) String() string {
	if i > 0 {
		return prettyUint64(i).String()
	}
	switch int64(i) {
	case math.MinInt64:
		return "INT64_MIN"
	case math.MinInt32:
		return "INT32_MIN"
	default:
		return fmt.Sprintf("%v", int64(i))
	}
}

func (m *PropertyMap) FormatTree(tf treefmt.Formatter) {
	names := make([]string, 0, len(*m))
	for name := range *m {


@@ 410,7 418,7 @@ func (m *PropertyMap) FormatTree(tf treefmt.Formatter) {
		var specStr string
		switch spec := prop.Spec.(type) {
		case *PropertySpecRange:
			specStr = fmt.Sprintf("[%v, %v]", prettyUint64(spec.Min), prettyUint64(spec.Max))
			specStr = spec.String()
		case []PropertySpecEnum:
			var names []string
			for _, e := range spec {


@@ 420,7 428,7 @@ func (m *PropertyMap) FormatTree(tf treefmt.Formatter) {
		case drm.ObjectType:
			specStr = spec.String()
		case *PropertySpecSignedRange:
			specStr = fmt.Sprintf("[%v, %v]", prettyInt64(spec.Min), prettyInt64(spec.Max))
			specStr = spec.String()
		}
		if specStr != "" {
			s += " " + specStr

M public/assets/style.css => public/assets/style.css +16 -0
@@ 102,3 102,19 @@ ul.pre ul li:last-child:before {
.alt-formats {
    float: right;
}

dt, dd {
    padding: 4px 20px;
}

dt {
    font-weight: bold;
    float: left;
    clear: left;
    width: 150px;
    text-align: right;
}

dd.muted {
    color: gray;
}

M public/properties.html => public/properties.html +2 -2
@@ 9,7 9,7 @@
        <tr>
            <th>Property</th>
            <th>Type</th>
            <th>Object type</th>
            <th>Attached to</th>
            {{range $name, $_ := .Drivers}}
            <th>{{$name}}</th>
            {{end}}


@@ 18,7 18,7 @@
    <tbody>
        {{range $name, $prop := .Properties}}
        <tr>
            <td class="pre">{{$name}}</td>
            <td class="pre"><a href="/properties/{{$name}}">{{$name}}</a></td>
            <td>{{$prop.Type}}</td>
            <td>{{$prop.ObjectType}}</td>
            {{range $drv, $_ := $.Drivers}}

A public/property.html => public/property.html +57 -0
@@ 0,0 1,57 @@
{{template "head" (printf "Property: %s" .Name)}}

<h1>DRM database property: {{.Name}}</h1>

<p><a href="/">Back to index</a></p>

<h2>Details</h2>

<dl>
    <dt>Name</dt>
    <dd>{{.Name}}</dd>

    <dt>Flags</dt>
    {{if len .Flags}}
    <dd>{{join .Flags ", "}}</dd>
    {{else}}
    <dd class="muted">&lt;none&gt;</dd>
    {{end}}

    <dt>Type</dt>
    <dd>{{.Prop.Type}}</dd>

    <dt>Attached to</dt>
    <dd>{{.ObjectType}}</dd>

    <dt>Specification</dt>
    {{if .Prop.Spec}}
    <dd>{{.Prop.Spec}}</dd>
    {{else}}
    <dd class="muted">&lt;none&gt;</dd>
    {{end}}
</dl>

<h2>Driver support</h2>

<table>
    <thead>
        <tr>
            {{range $name, $_ := .Drivers}}
            <th>{{$name}}</th>
            {{end}}
        </tr>
    </thead>
    <tbody>
        <tr>
            {{range $name, $ok := .Drivers}}
            {{if $ok}}
            <td class="status-supported">✓</td>
            {{else}}
            <td class="status-unsupported">✗</td>
            {{end}}
            {{end}}
        </tr>
    </tbody>
</table>

{{template "foot"}}

M server.go => server.go +45 -0
@@ 389,6 389,51 @@ func New() *echo.Echo {
		}{drivers, props})
	})

	e.GET("/properties/:name", func(c echo.Context) error {
		propertyName := c.Param("name")

		found := false;
		var property drmtree.Property
		var objectType drm.ObjectType
		drivers := make(map[string]bool)
		err := walk(func(k string, n *drmtree.Node) error {
			drivers[n.Driver.Name] = false

			return walkNodeProps(n, func(obj drm.AnyID, name string, p *drmtree.Property) error {
				if name != propertyName {
					return nil
				}
				drivers[n.Driver.Name] = true
				found = true
				property = *p
				objectType = obj.Type()
				return nil
			})
		})
		if err != nil {
			return err
		}
		if !found {
			return c.String(http.StatusNotFound, "property not found")
		}

		var flags []string
		if property.Atomic {
			flags = append(flags, "atomic")
		}
		if property.Immutable {
			flags = append(flags, "immutable")
		}

		return c.Render(http.StatusOK, "property.html", struct {
			Name       string
			Prop       *drmtree.Property
			ObjectType drm.ObjectType
			Flags      []string
			Drivers    map[string]bool
		}{propertyName, &property, objectType, flags, drivers})
	})

	e.GET("/formats", func(c echo.Context) error {
		type modifierAndFormat struct {
			mod drm.Modifier

M template.go => template.go +2 -0
@@ 4,6 4,7 @@ import (
	"fmt"
	"html/template"
	"io"
	"strings"

	"github.com/labstack/echo/v4"
)


@@ 20,6 21,7 @@ func (t *tmpl) Render(w io.Writer, name string, data interface{}, c echo.Context

func loadTemplates() (*tmpl, error) {
	t, err := template.New("drmdb").Funcs(template.FuncMap{
		"join": strings.Join,
		"pct": func(num, tot int) float32 {
			return 100 * float32(num) / float32(tot)
		},