Skip to content

Commit

Permalink
UI 2.0 Review (#3556) 馃敟
Browse files Browse the repository at this point in the history
* create list templete

* create add form view templete

* refactor and create NautobotInput Component

* move sites/ to dcim/sites/

* move react back one folder

* move react back one folder

* new changes

* new changes

* get model fields

* copy react files from plugin into nautobot frontend

* fix menu

* Work in progress on table

* json api

* Add get table fields

* fix table header

* Use absolte path

* slugify python

* Field groups

* Account for status and tags

* add react to example plugin

* push all code

* nautobot.2319 React UI components update

* add docker-compose.nodejs.yml to run an nginx reverse proxy for nautobot and nodejs

* remove unused ui prototype

* update to work with nextjs

* Revert "remove unused ui prototype"

This reverts commit 7bccab7.

* make react work?

* add object detail view

* remove comment

* remove comments

* add links to object detail view

* fix region

* Implement basic module federation for webpack

- Publishes `nautobot` module as `remoteEntry.js`
- Implemented webpack `config-overrides.js` using `react-app-rewired` as a dev dependency

* remove nextjs ui

* remove plugin file copy

* optimize dev docker environment

* Update react app build output paths

Output js to static/reactjs
Output css to static/reactcss

* use global router

* add postbuild script to move files to nautobot

* add navmenu headers

* convert prototype to nextjs

* fix some imports

* update to use cross site api calls

* remove nginx config

* update nautobot dev server to use uwsgi instead of runserver

* consolidate frontend pages, update django routing for react

* add plugin full width html fragment support

* fix detail page layout

* add plugin routes

* expose django's login/logout routes

* YEET

* Fixing some lints and bugs.

- Removed bad import in router
- Fixed linting errors for unused imports
- Fixed URL route on table item
- Improved Docker compose file to mount node_modules as a separate volume

* fix permissions issue on docker-compose in linux

* fix linux docker nodejs permissions (really)

* Make detail view generic

* stashing

* add paginator for list view

* yolo

* fix nautobot brand image, add some better looking icons

* stashing

* stashing

* replace react views with base.html that's derived from the react app's index.html

* Something broke but this is progress

* CustomViews and Plugin Components

* fix bug in detail view when json key name starts with underscore

* basic management command to generate ui

* tweaks

* Tweaks and update

* fixes and starts

* update dockerfile to match next

* update poetry lockfile

* linting and minor bug fixes

* clean up imports

* fix bug

* added nginx container in nodejs.yml and made nodejs serve up /static/js/bundle.js (#3057)

Co-authored-by: Hanlin Miao <hanlinmiao@Hanlins-MBP-2.home>

* fix runserver database exhaustion with nginx

* increase keepalive timeout on nginx connection

* Revert "increase keepalive timeout on nginx connection"

This reverts commit d3aabdd.

* increase keepalive timeout on nginx connection

* clean up api for plugin react components

* add web_url to all valid serializers

* remove debug logging

* add login view

* fix js error

* Implemented generic create view for React app.

- Requires the nested serialization changes.
- Implemented nested serialization using `?depth=`
    - Revert nested serializer and `brief=True` pattern
    - Replace it with `depth=?` arguments to views and rendering forms from JSON schema using `drf-react-template-framework`
    - Commented out all `brief=` and associated code
- Updated `RegionSerializer` to have `parent` field fallback to default.

* First pass at #3204 (#3252)

* Some low-hanging fruit fixes to get us closer back to next

* next-ui-2.0 cleanup and commenting (#3285)

* Remove unused code added to example_plugin

* Add a bunch of TODO comments

* More TODO comments

* Black

* Flake8

* Markdownlint

* Pylint

* Removing some more stuff that's not needed at present

* Revert a few things back to baseline

* One more deletion

* Fixes to example_plugin and example_plugin_with_view_override

* Update comments and address a couple of TODOs

* More TODO updates

* web_url fixup

* Added a `nautobot-server build_ui` command (#3306)

- This command does the following from the `nautobot/ui` directory
  - Generates the `app_imports.js` file from any installed plugins
  - Runs `npm install` when `--npm-install` is passed
  - Runs `npm run build`
- This command is now also called by `nautobot-server post_upgrade`, which calls it with `--npm-install`
- Updated the `config-overrides.js` to not hash JS or CSS files so that their raw filename can be stored in static files and referenced using `{% static %}` (e.g. `{% static 'js/main.js %}`) without having to overload the `base.html` template for the web UI
- Updated `nautobot/core/templates/base.html` to link directly to the static files for JS and CSS that get pulled in from the UI build environment by `nautobot-server collectstatic` 
- Parameterized the API key needed for now to read from `NAUTOBOT_API_TOKEN` environment variable
- `app_imports.js` now renders with relative paths vs. absolute paths making commits that happen compatible across Docker-local and production use-cases.
- Restored the `/plugins/` route and the `InstalledPlugins.jsx` module
- The `build` command runs `npm` silently by default to hide the debug/warn/error messages unless `-v 2` or `-v 3` are passed.
- There is some `console.log` output that is now not displayed unless `NAUTOBOT_DEBUG` environment variable is set. The `build_ui` command will also set this if verbosity is desired.
- Implemented a new `invoke version` task to align versions of core with UI apps.
  - Will bump both `pyproject.toml` and `package.json` to keep them in sync.
  - If no argument is provided, displays the versions instead.
- Also added `NAUTOBOT_UI_DIR` into `nautobot.core.settings` so that it can be easily reused
- Moved `nautobot_ui` to `nautobot/ui`
- `nautobot/ui` is now included in the package build
- Added a basic README file back to `nautobot/ui`
- Renamed all UI references of "plugin" to "app"

After using `build_ui` it's possible to serve the entire application using Django now without requiring `node`. Of course for development `node` will still be desirable due to live rendering.

* setState for islogged in

* Revert "setState for islogged in"

This reverts commit 596d9c1.

* remove ourrunserver reference in docker compose (#3366)

* UI 2.0 remove nginx container (#3367)

* Initial removal of react-bootstrap and addition of nautobot-ui

* Clean up devDependencies

* Simplify tasks.py

* Updates from feedback

* Add node_modules ignore

* move 'api/' ui related urls under 'api/ui/' (#3385)

* move 'api/' ui related urls under 'api/ui/'

* flake8

* address PR feedback

* exclude get-menu api endpoint from OpenAPI schema and add documentation for UI-related API endpoints

* flake8

* mdlint

* elaborate UI-related endpoints documentation

* update mkdocs.yml

---------

Co-authored-by: Hanlin Miao <hanlinmiao@Hanlins-MBP-2.home>

* Logged in state for nautobot-ui (#3356)

* Update from fix nautobot/nautobot-ui#9

* Black

* Hadolint

* More hadolint

* UI docker dev environment tweaks (#3408)

* Don't copy node_modules and UI build when rebuilding docker image

* Capture npm output and print it in case of failures

* Create docker volume for node_modules, change container startup, update docs

* nautobot-ui is public now; can use node:18-slim

* Add TODO comments

* Add unittest for all react components (#3404)

* Add test for component common

* common test case

* Done testing core

* Add test for BSTableItem Component

* Add partial views test

* Add test for views

* add doc

* run ui unittest

* Apply suggestions from code review

Co-authored-by: Hanlin Miao <46973263+HanlinMiao@users.noreply.github.com>

* fix markdown

* update ReadMe

* Update nautobot/ui/README.md

Co-authored-by: Bryan Culver <31187+bryanculver@users.noreply.github.com>

* Merge conflicts

* Update README.md

---------

Co-authored-by: Hanlin Miao <46973263+HanlinMiao@users.noreply.github.com>
Co-authored-by: Bryan Culver <31187+bryanculver@users.noreply.github.com>
Co-authored-by: Bryan Culver <bryan.culver@networktocode.com>

* UI 2.0 Cleanup (#3444)

* Provide a way to refresh CSRF without shortcutting CSRF protections

* Session endpoint

* Stashing to switch between computers

* more stashing

* yeeet

* This is going to be a lot

* Updates

* Updates from feedback

* Black & flake8

* Fix indention

* Remove top-level package lock

* Revert bad merge

* UI 2.0: Cleanup Router Links, Import Font as Source (#3482)

* Cleanup Router Links

* Move font to built-in instead of served via Google Fonts.

* Remove unneccessary import

* UI 2.0: Introduce Prettier, Use ESLint for Formatting and Linting (#3531)

* Move to craco (#3546)

Fix Jest testing

Remove should be ignored paths file as this is autogenerated

Scope creep avoid get tests passing so we can demonstrate it's working.

Prettier...

Add base paths for testing

No cached example, just copy the template in CI

Mock would prefer a file exists for app_imports.js

* Add New UI Toggle (#3615)

* Add New UI Toggle

* Add changelog fragment.

* Prettier

* Fix corrupted package-lock.json (#3618)

* Fix corrupted package-lock.json

* Add changelog fragment.

* Remove duplicate package for nautbot-ui

* Get tests passing for UI 2.0 (#3632)

* Get tests passing for UI 2.0

* Add changelog fragment.

* Updates from feedback

* Exception handling

* Fix CI step merge

* Pylint

* Fix changes from next

* UI 2.0 Implement GenericView component (#3626)

* [UI 2.0] Implement GenericView component

* [UI 2.0] Add missing objectData prop to GenericView in ObjectRetrieve view

* [UI 2.0] Remove Current route is ... debug message

* Move popover to it's own component.

---------

Co-authored-by: Bryan Culver <bryan.culver@networktocode.com>
Co-authored-by: Bryan Culver <me@bryanculver.com>

* 馃憻

---------

Co-authored-by: Timizuo <timizuoebideri@gmail.com>
Co-authored-by: Chris Thant <chris.thant@networktocode.com>
Co-authored-by: Gary Snider <gary.snider@networktocode.com>
Co-authored-by: jathanism <jathan@gmail.com>
Co-authored-by: Hanlin Miao <46973263+HanlinMiao@users.noreply.github.com>
Co-authored-by: Hanlin Miao <hanlinmiao@Hanlins-MBP-2.home>
Co-authored-by: Glenn Matthews <glenn.matthews@networktocode.com>
Co-authored-by: Gary Snider <75227981+gsnider2195@users.noreply.github.com>
Co-authored-by: Timizuo <94907097+timizuoebideri1@users.noreply.github.com>
Co-authored-by: Norbert Mieczkowski <117445994+norbert-mieczkowski-codilime@users.noreply.github.com>
  • Loading branch information
11 people committed Apr 25, 2023
1 parent d33ad55 commit 8a331fe
Show file tree
Hide file tree
Showing 140 changed files with 30,678 additions and 336 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@

# Add specific exclusions
**/__pycache__
nautobot/ui/build
nautobot/ui/node_modules
5 changes: 5 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
!/nautobot
/nautobot/*
!/nautobot/ui
/nautobot/ui/build
52 changes: 52 additions & 0 deletions .github/workflows/ci_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@ jobs:
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Linting: flake8"
run: "poetry run invoke flake8"
prettier:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_LOCAL: "True"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v2"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Install NPM Dependencies"
run: "npm install"
- name: "Linting: prettier"
run: "poetry run invoke prettier"
eslint:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_LOCAL: "True"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v2"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Install NPM Dependencies"
run: "npm install"
- name: "Linting: eslint"
run: "poetry run invoke eslint"
yamllint:
runs-on: "ubuntu-20.04"
env:
Expand Down Expand Up @@ -249,6 +275,31 @@ jobs:
- "check-migrations"
- "check-schema"

tests-ui:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_LOCAL: "True"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v2"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Install NPM Dependencies"
working-directory: ./nautobot/ui
run: "npm install"
- name: "Setup base aliases for tests"
working-directory: ./nautobot/ui
run: "cp jsconfig-base.json jsconfig.paths.json"
- name: "Setup base app_imports for mock"
working-directory: ./nautobot/ui
run: "echo 'export const NautobotApps = {}; export default NautobotApps;' > src/app_imports.js"
- name: "Run unittest-ui"
working-directory: ./nautobot/ui
run: "poetry run invoke unittest-ui"
needs:
- "prettier"
- "eslint"

integration-test:
runs-on: "ubuntu-20.04"
env:
Expand Down Expand Up @@ -292,6 +343,7 @@ jobs:
- "pylint"
- "tests-postgres"
- "tests-mysql"
- "tests-ui"

container-build:
name: "Build Container Images (GHCR Only)"
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/ci_pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,32 @@ jobs:
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Linting: flake8"
run: "poetry run invoke flake8"
prettier:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_LOCAL: "True"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v2"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Install NPM Dependencies"
run: "npm install"
- name: "Linting: prettier"
run: "poetry run invoke prettier"
eslint:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_LOCAL: "True"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v2"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Install NPM Dependencies"
run: "npm install"
- name: "Linting: eslint"
run: "poetry run invoke eslint"
yamllint:
runs-on: "ubuntu-20.04"
env:
Expand Down Expand Up @@ -248,6 +274,31 @@ jobs:
- "check-migrations"
- "check-schema"

tests-ui:
runs-on: "ubuntu-20.04"
env:
INVOKE_NAUTOBOT_LOCAL: "True"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v2"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v2"
- name: "Install NPM Dependencies"
working-directory: ./nautobot/ui
run: "npm install"
- name: "Setup base aliases for tests"
working-directory: ./nautobot/ui
run: "cp jsconfig-base.json jsconfig.paths.json"
- name: "Setup base app_imports for mock"
working-directory: ./nautobot/ui
run: "echo 'export const NautobotApps = {}; export default NautobotApps;' > src/app_imports.js"
- name: "Run unittest-ui"
working-directory: ./nautobot/ui
run: "poetry run invoke unittest-ui"
needs:
- "prettier"
- "eslint"

performance-test:
runs-on: "ubuntu-20.04"
strategy:
Expand Down Expand Up @@ -333,6 +384,7 @@ jobs:
- "pylint"
- "tests-postgres"
- "tests-mysql"
- "tests-ui"

changelog:
if: github.base_ref == 'develop' || github.base_ref == 'next'
Expand Down
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
!/nautobot
/nautobot/*
!/nautobot/ui
/nautobot/ui/build
4 changes: 4 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"tabWidth": 4,
"useTabs": false
}
1 change: 1 addition & 0 deletions changes/2901.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added `get_absolute_url` method on `BaseModel` which will attempt to resolve the detail view route for all subclassed models.
1 change: 1 addition & 0 deletions changes/3203.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a `nautobot-server build_ui` command for building the web UI
1 change: 1 addition & 0 deletions changes/3615.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added toggle buttons between Legacy UI and New UI.
1 change: 1 addition & 0 deletions changes/3618.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix corrupted `package-lock.json` which was causing test failures.
4 changes: 4 additions & 0 deletions development/dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ NAUTOBOT_SELENIUM_HOST=nautobot

# Allow self signed git repositories for config contexts, export templates, ...
# GIT_SSL_NO_VERIFY="1"

# Set max connection age to the default for Django (close at end of each request)
# NodeJS container will cause connection exhaustion
NAUTOBOT_DB_TIMEOUT=0
20 changes: 20 additions & 0 deletions development/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,23 @@ services:
mkdocs:
volumes:
- ../:/source
nodejs:
image: node:18-slim
environment:
PORT: "3000"
# DEBUG: "express:*" # nodejs web server debug logging
ports:
- "3000:3000"
working_dir: /opt/node/nautobot
# user: node # Best practice, but "nautobot" container currently uses root --> permission issues for shared volume
volumes:
- ../nautobot/ui/:/opt/node/nautobot
- ../examples/:/opt/examples
- ../:/source
- node_modules:/opt/node/nautobot/node_modules
# Wait for nautobot container to be fully ready, meaning that it's already run `npm install/build` successfully
depends_on:
nautobot:
condition: service_healthy
command: >
bash -c "npm run start"
6 changes: 5 additions & 1 deletion development/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ services:
healthcheck:
interval: 5s
timeout: 5s
start_period: 45s
start_period: 10m # intentionally conservative upper bound for `npm install` time in a fresh setup
retries: 3
test:
- "CMD"
- "curl"
- "-f"
- "http://localhost:8080/health/"
volumes:
- node_modules:/source/nautobot/ui/node_modules
celery_worker:
image: "local/nautobot-dev:local-py${PYTHON_VER}"
ports:
Expand Down Expand Up @@ -92,3 +94,5 @@ services:
tty: true
ports:
- "8001:8001"
volumes:
node_modules:
3 changes: 3 additions & 0 deletions development/nautobot_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
"example_plugin",
]

CORS_ALLOWED_ORIGINS = ["http://localhost:3000"]
CORS_ALLOW_CREDENTIALS = True
SESSION_COOKIE_SAMESITE = None

#
# Development Environment for SSO
Expand Down
27 changes: 8 additions & 19 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -215,36 +215,25 @@ FROM dependencies-dev-python as dependencies-dev-platform-amd64
RUN curl -Lo /usr/bin/hadolint https://github.com/hadolint/hadolint/releases/download/v2.10.0/hadolint-Linux-x86_64 && \
chmod +x /usr/bin/hadolint

# Install NodeJS for installing markdownlint-cli

RUN curl -Lo /tmp/node.tar.xz https://nodejs.org/dist/v17.9.0/node-v17.9.0-linux-x64.tar.xz && \
mkdir -p /usr/local/lib/nodejs && \
tar -xf /tmp/node.tar.xz -C /usr/local/lib/nodejs && \
rm -rf /tmp/node.tar.xz

ENV PATH="${PATH}:/usr/local/lib/nodejs/node-v17.9.0-linux-x64/bin"

FROM dependencies-dev-python as dependencies-dev-platform-arm64

# Install hadolint for linting Dockerfiles
RUN curl -Lo /usr/bin/hadolint https://github.com/hadolint/hadolint/releases/download/v2.10.0/hadolint-Linux-arm64 && \
chmod +x /usr/bin/hadolint

# Install NodeJS for installing markdownlint-cli

RUN curl -Lo /tmp/node.tar.xz https://nodejs.org/dist/v17.9.0/node-v17.9.0-linux-arm64.tar.xz && \
mkdir -p /usr/local/lib/nodejs && \
tar -xf /tmp/node.tar.xz -C /usr/local/lib/nodejs && \
rm -rf /tmp/node.tar.xz

ENV PATH="${PATH}:/usr/local/lib/nodejs/node-v17.9.0-linux-arm64/bin"

################################ Stage: dependencies-dev (intermediate build target)

# hadolint ignore=DL3006
FROM dependencies-dev-platform-$TARGETARCH as dependencies-dev

RUN npm install --global markdownlint-cli@0.31.1
# Install node.js 18.x (LTS)
# hadolint ignore=DL3008,DL4006
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
apt-get install --no-install-recommends -y nodejs && \
apt-get autoremove -y && \
apt-get clean all && \
rm -rf /var/lib/apt/lists/* && \
npm install --global markdownlint-cli@0.31.1

# Nautobot wheel build is no longer a direct previous layer
# /source from build-nautobot will include docs from build-docs as well
Expand Down
7 changes: 0 additions & 7 deletions examples/example_plugin/example_plugin/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from django.db import models
from django.urls import reverse

from nautobot.apps.models import extras_features, OrganizationalModel

Expand All @@ -24,9 +23,6 @@ class Meta:
def __str__(self):
return f"{self.name} - {self.number}"

def get_absolute_url(self):
return reverse("plugins:example_plugin:examplemodel", kwargs={"pk": self.pk})

def to_csv(self):
return (
self.name,
Expand All @@ -48,6 +44,3 @@ class AnotherExampleModel(OrganizationalModel):

class Meta:
ordering = ["name"]

def get_absolute_url(self):
return reverse("plugins:example_plugin:anotherexamplemodel", kwargs={"pk": self.pk})
12 changes: 12 additions & 0 deletions examples/example_plugin/example_plugin/template_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ def detail_tabs(self):
},
]

def full_width_page(self):
return """
<div class="card card-default">
<div class="card-header">
<strong>Plugin Full Width Page</strong>
</div>
<div class="card-body">
I am a teapot short and stout.
</div>
</div>
"""


class LocationContent(TemplateExtension):
model = "dcim.location"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

{% block content %}
<h2>Device Plugin Tab 1</h2>
<p>I am some content for the example plugin's device ({{ object.pk }}) detail tab 1.</p>
<div class="card">
<div class="card-body">I am some content for the example plugin's device ({{ object.pk }}) detail tab 1.</div>
</div>
{% endblock %}
7 changes: 7 additions & 0 deletions examples/example_plugin/example_plugin/ui/FullWidthPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Card } from '@chakra-ui/react'; // TODO: import from nautobot-ui when available.

export function MyFancyCard(props) {
return <Card body>I am a full-fledge component provided by the default example App. The ID of the object I am displaying is: {props.id}</Card>;
}

export default MyFancyCard;
11 changes: 11 additions & 0 deletions examples/example_plugin/example_plugin/ui/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export { default as ExampleAppFullWidthPageComponent } from "./FullWidthPage"

const app_config = {
detail_tabs: {},
full_width_components: {
"dcim:sites": ["ExampleAppFullWidthPageComponent"]
},
view_overrides: {}
}

export default app_config
5 changes: 5 additions & 0 deletions examples/example_plugin/example_plugin/ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "example_plugin",
"version": "0.0.1",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Table from 'react-bootstrap/Table';

export function CustomTableView(props) {
return (
<Table striped bordered hover>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>ID</td>
<td>{props.id}</td>
</tr>
<tr>
<td>Display</td>
<td>{props.display}</td>
</tr>
<tr>
<td>Web URL</td>
<td>{props.web_url}</td>
</tr>
</tbody>
</Table>
);
}

export default CustomTableView;

0 comments on commit 8a331fe

Please sign in to comment.