chore(nimbus): setup webpack for nimbus_ui_new (#10834)

Because

* Now that all of the functionality is finished for the new nimbus ui
list page
* We can setup webpack to bundle all the dependencies

This commit
* Adds webpack to nimbus_ui_new
* Move scripts from being inline to actually stored as static assets
with proper linting
* Setup SASS so we can have some proper styling for bootstrap-select
with dark mode

fixes #10708
This commit is contained in:
Jared Lockhart 2024-06-13 13:57:54 -04:00 коммит произвёл GitHub
Родитель fef1e6cb91
Коммит 7b3dce9a3a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
16 изменённых файлов: 1346 добавлений и 88 удалений

Просмотреть файл

@ -26,6 +26,8 @@ ESLINT_LEGACY = yarn workspace @experimenter/core lint
ESLINT_FIX_CORE = yarn workspace @experimenter/core lint-fix
ESLINT_NIMBUS_UI = yarn workspace @experimenter/nimbus-ui lint
ESLINT_FIX_NIMBUS_UI = yarn workspace @experimenter/nimbus-ui lint-fix
ESLINT_NIMBUS_UI_NEW = yarn workspace @experimenter/nimbus_ui_new lint
ESLINT_FIX_NIMBUS_UI_NEW = yarn workspace @experimenter/nimbus_ui_new format
TYPECHECK_NIMBUS_UI = yarn workspace @experimenter/nimbus-ui lint:tsc
DJLINT_CHECK = djlint --check experimenter/nimbus_ui_new/
DJLINT_FIX = djlint --reformat experimenter/nimbus_ui_new/
@ -148,7 +150,7 @@ kill: compose_stop compose_rm docker_prune ## Stop, remove, and prune container
echo "All containers removed!"
lint: build_test ## Running linting on source code
$(COMPOSE_TEST) run experimenter sh -c '$(WAIT_FOR_DB) (${PARALLEL} "$(NIMBUS_SCHEMA_CHECK)" "$(PYTHON_CHECK_MIGRATIONS)" "$(CHECK_DOCS)" "$(BLACK_CHECK)" "$(RUFF_CHECK)" "$(DJLINT_CHECK)" "$(ESLINT_LEGACY)" "$(ESLINT_NIMBUS_UI)" "$(TYPECHECK_NIMBUS_UI)" "$(PYTHON_TYPECHECK)" "$(PYTHON_TEST)" "$(JS_TEST_LEGACY)" "$(JS_TEST_NIMBUS_UI)" "$(JS_TEST_REPORTING)") ${COLOR_CHECK}'
$(COMPOSE_TEST) run experimenter sh -c '$(WAIT_FOR_DB) (${PARALLEL} "$(NIMBUS_SCHEMA_CHECK)" "$(PYTHON_CHECK_MIGRATIONS)" "$(CHECK_DOCS)" "$(BLACK_CHECK)" "$(RUFF_CHECK)" "$(DJLINT_CHECK)" "$(ESLINT_LEGACY)" "$(ESLINT_NIMBUS_UI)" "$(ESLINT_NIMBUS_UI_NEW)" "$(TYPECHECK_NIMBUS_UI)" "$(PYTHON_TYPECHECK)" "$(PYTHON_TEST)" "$(JS_TEST_LEGACY)" "$(JS_TEST_NIMBUS_UI)" "$(JS_TEST_REPORTING)") ${COLOR_CHECK}'
check: lint
test: build_test ## Run tests
@ -185,7 +187,7 @@ generate_types: build_dev
$(COMPOSE) run experimenter sh -c "$(NIMBUS_TYPES_GENERATE)"
format: build_dev ## Format source tree
$(COMPOSE) run experimenter sh -c '${PARALLEL} "$(RUFF_FIX);$(DJLINT_FIX);$(BLACK_FIX)" "$(ESLINT_FIX_CORE)" "$(ESLINT_FIX_NIMBUS_UI)"'
$(COMPOSE) run experimenter sh -c '${PARALLEL} "$(RUFF_FIX);$(DJLINT_FIX);$(BLACK_FIX)" "$(ESLINT_FIX_CORE)" "$(ESLINT_FIX_NIMBUS_UI)" "$(ESLINT_FIX_NIMBUS_UI_NEW)"'
code_format: format
makemigrations: build_dev

Просмотреть файл

@ -16,14 +16,35 @@ services:
- ./experimenter:/experimenter
- ./docs/experimenter:/experimenter/experimenter/docs
- media_volume:/experimenter/experimenter/media
- nimbus_ui_new_volume:/experimenter/experimenter/nimbus_ui_new/static/dist/
- /experimenter/experimenter/legacy/legacy-ui/core/.cache/
- /experimenter/experimenter/legacy/legacy-ui/core/node_modules/
- /experimenter/experimenter/nimbus-ui/node_modules/
- /experimenter/experimenter/nimbus_ui_new/static/node_modules/
- /experimenter/experimenter/served/
- /experimenter/node_modules/
- ${GOOGLE_ADC_FILE}:${GOOGLE_APPLICATION_CREDENTIALS}:ro
command: bash -c "python bin/setup_kinto.py;/experimenter/bin/wait-for-it.sh db:5432 -- python /experimenter/manage.py runserver 0:7001"
yarn-nimbus_ui_new:
image: experimenter:dev
env_file: .env
stdin_open: true
tty: true
volumes:
- ./experimenter:/experimenter
- ./docs/experimenter:/experimenter/experimenter/docs
- media_volume:/experimenter/experimenter/media
- nimbus_ui_new_volume:/experimenter/experimenter/nimbus_ui_new/static/dist/
- /experimenter/experimenter/legacy/legacy-ui/core/.cache/
- /experimenter/experimenter/legacy/legacy-ui/core/node_modules/
- /experimenter/experimenter/nimbus-ui/node_modules/
- /experimenter/experimenter/nimbus_ui_new/static/node_modules/
- /experimenter/experimenter/served/
- /experimenter/node_modules/
- ${GOOGLE_ADC_FILE}:${GOOGLE_APPLICATION_CREDENTIALS}:ro
command: bash -c "FORCE_COLOR=true yarn workspace @experimenter/nimbus_ui_new watch | cat"
yarn-nimbus-ui:
image: experimenter:dev
env_file: .env
@ -36,6 +57,7 @@ services:
- /experimenter/experimenter/legacy/legacy-ui/core/.cache/
- /experimenter/experimenter/legacy/legacy-ui/core/node_modules/
- /experimenter/experimenter/nimbus-ui/node_modules/
- /experimenter/experimenter/nimbus_ui_new/static/node_modules/
- /experimenter/experimenter/served/
- /experimenter/node_modules/
- ${GOOGLE_ADC_FILE}:${GOOGLE_APPLICATION_CREDENTIALS}:ro
@ -105,3 +127,4 @@ services:
volumes:
db_volume:
media_volume:
nimbus_ui_new_volume:

Просмотреть файл

@ -65,6 +65,7 @@ COPY --from=file-loader /experimenter/package.json /experimenter/package.json
COPY --from=file-loader /experimenter/yarn.lock /experimenter/yarn.lock
COPY --from=file-loader /experimenter/experimenter/legacy/legacy-ui/core/package.json /experimenter/experimenter/legacy/legacy-ui/core/package.json
COPY --from=file-loader /experimenter/experimenter/nimbus-ui/package.json /experimenter/experimenter/nimbus-ui/package.json
COPY --from=file-loader /experimenter/experimenter/nimbus_ui_new/static/package.json /experimenter/experimenter/nimbus_ui_new/static/package.json
RUN yarn install --frozen-lockfile
@ -84,6 +85,7 @@ COPY --from=python-builder /usr/local/lib/python3.11/site-packages/ /usr/local/l
# Node packages
COPY --from=node-builder /experimenter/experimenter/legacy/legacy-ui/core/node_modules/ /experimenter/experimenter/legacy/legacy-ui/core/node_modules/
COPY --from=node-builder /experimenter/experimenter/nimbus-ui/node_modules/ /experimenter/experimenter/nimbus-ui/node_modules/
COPY --from=node-builder /experimenter/experimenter/nimbus_ui_new/static/node_modules/ /experimenter/experimenter/nimbus_ui_new/static/node_modules/
COPY --from=node-builder /experimenter/node_modules/ /experimenter/node_modules/
# Rust packages
@ -115,6 +117,10 @@ RUN yarn workspace @experimenter/core build
COPY --from=file-loader /experimenter/experimenter/nimbus-ui/ /experimenter/experimenter/nimbus-ui/
RUN yarn workspace @experimenter/nimbus-ui build
# Build nimbus_ui_new assets
COPY --from=file-loader /experimenter/experimenter/nimbus_ui_new/ /experimenter/experimenter/nimbus_ui_new/
RUN yarn workspace @experimenter/nimbus_ui_new build
# Deploy image
#-------------------------
@ -143,4 +149,6 @@ COPY --from=file-loader /experimenter/experimenter/ /experimenter/experimenter/
COPY --from=file-loader /experimenter/manifesttool/ /experimenter/manifesttool/
COPY --from=ui /experimenter/experimenter/legacy/legacy-ui/assets/ /experimenter/experimenter/legacy/legacy-ui/assets/
COPY --from=ui /experimenter/experimenter/nimbus-ui/build/ /experimenter/experimenter/nimbus-ui/build/
COPY --from=ui /experimenter/experimenter/nimbus_ui_new/static/dist/ /experimenter/experimenter/nimbus_ui_new/static/dist/
ENV PYTHONPATH=$PYTHONPATH:/application-services/

Просмотреть файл

@ -49,6 +49,7 @@
"fuse.js": "^6.6.2",
"graphql": "^15.8.0",
"json-to-ast": "^2.1.0",
"postcss": "7.0.36",
"react": "^17.0.2",
"react-async-hook": "^3.6.2",
"react-bootstrap": "^1.6.1",

Просмотреть файл

@ -0,0 +1,20 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:prettier/recommended"
],
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
"prettier/prettier": "error"
},
"globals": {
"$": "readonly"
}
}

Просмотреть файл

@ -0,0 +1,2 @@
{
}

Просмотреть файл

@ -0,0 +1,104 @@
// src/styles.scss
// Import Bootstrap's variables and mixins
@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/variables';
@import '~bootstrap/scss/mixins';
@include color-mode(light) {
.bootstrap-select {
.dropdown-menu {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text
.dropdown-item {
color: var(--bs-body-color); // White text for items
&:hover,
&:focus {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text on hover/focus
}
&.active {
background-color: var(--bs-primary); // Active item background
color: var(--bs-body-color); // White text for active item
}
}
}
.dropdown-toggle {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text
border: 1px solid var(--bs-dropdown-border-color); // Border color
&:focus,
&:hover {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text on hover/focus
}
}
.bs-searchbox {
input {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-input-color); // White text for search box
border: 1px solid var(--bs-input-border-color); // Border color for search box
&::placeholder {
color: var(--bs-input-placeholder-color); // Placeholder color
}
}
}
}
}
@include color-mode(dark) {
.bootstrap-select {
.dropdown-menu {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text
.dropdown-item {
color: var(--bs-body-color); // White text for items
&:hover,
&:focus {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text on hover/focus
}
&.active {
background-color: var(--bs-primary); // Active item background
color: var(--bs-body-color); // White text for active item
}
}
}
.dropdown-toggle {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text
border: 1px solid var(--bs-dropdown-border-color); // Border color
&:focus,
&:hover {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-body-color); // White text on hover/focus
}
}
.bs-searchbox {
input {
background-color: var(--bs-dropdown-link-hover-bg); // Darker background on hover/focus
color: var(--bs-input-color); // White text for search box
border: 1px solid var(--bs-input-border-color); // Border color for search box
&::placeholder {
color: var(--bs-input-placeholder-color); // Placeholder color
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap-select/dist/css/bootstrap-select.min.css";
import "@fortawesome/fontawesome-free/css/all.min.css";
import "../css/style.scss";
import "bootstrap";
import "bootstrap-select";
import "jquery";
import "htmx.org";

Просмотреть файл

@ -0,0 +1,11 @@
document.body.addEventListener("htmx:afterSwap", function () {
// After reloading the table, we must update the values for status and sort in the sidebar form
// since it will not have been reloaded in the htmx get call
const urlParams = new URLSearchParams(window.location.search);
const sortValue = urlParams.get("sort");
const statusValue = urlParams.get("status");
$('#filter-form input[name="status"]').each(
(i, e) => (e.value = statusValue),
);
$('#filter-form input[name="sort"]').each((i, e) => (e.value = sortValue));
});

Просмотреть файл

@ -0,0 +1,35 @@
{
"name": "@experimenter/nimbus_ui_new",
"version": "1.0.0",
"description": "New Nimbus UI for Experimenter",
"private": true,
"scripts": {
"lint": "eslint js/ --ext .js,.jsx,.ts,.tsx",
"format": "prettier --write js/",
"build": "webpack",
"watch": "webpack --watch"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.2",
"bootstrap": "^5.3.3",
"bootstrap-select": "1.14.0-beta3",
"htmx.org": "^1.9.12",
"jquery": "^3.7.1"
},
"devDependencies": {
"babel-loader": "^9.1.3",
"css-loader": "6.7.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"postcss": "^8.4.38",
"postcss-loader": "^5",
"prettier": "^3.3.2",
"sass": "^1.77.5",
"sass-loader": "12.4.0",
"style-loader": "3.3.1",
"webpack": "^5.92.0",
"webpack-cli": "^5.1.4"
}
}

Просмотреть файл

@ -0,0 +1,51 @@
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
app: './js/index.js',
experiment_list: './js/scripts/experiment_list.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default'],
bootstrap: 'bootstrap',
}),
],
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
},
mode: 'production'
};

Просмотреть файл

@ -13,18 +13,7 @@
{% endblock title %}
</title>
<script src="{% static 'fontawesomefree/js/all.min.js' %}"></script>
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
{% bootstrap_css %}
{% bootstrap_javascript %}
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
crossorigin="anonymous"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.14.0-beta3/dist/css/bootstrap-select.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.14.0-beta3/dist/js/bootstrap-select.min.js"></script>
<script src="{% static 'nimbus_ui_new/app.bundle.js' %}"></script>
</head>
<body class="bg-body-tertiary">
<div class="container-fluid bg-body border-bottom border-1 mb-4 py-1">
@ -38,12 +27,8 @@
{% include "common/footer.html" %}
</div>
<script>
{% block extrascripts %}
{% endblock extrascripts %}
{% block extrascripts %}
{% endblock extrascripts %}
</script>
</body>
</html>

Просмотреть файл

@ -1,5 +1,6 @@
{% extends "common/with_sidebar.html" %}
{% load static %}
{% load nimbus_extras %}
{% block title %}
@ -25,14 +26,5 @@
{% block extrascripts %}
{{ block.super }}
document.body.addEventListener('htmx:afterSwap', function(evt) {
$('.selectpicker').selectpicker();
// After reloading the table, we must update the values for status and sort in the sidebar form
// since it will not have been reloaded in the htmx get call
const urlParams = new URLSearchParams(window.location.search);
const sortValue = urlParams.get('sort');
const statusValue = urlParams.get('status');
$('#filter-form input[name="status"]').each((i, e) => e.value = statusValue);
$('#filter-form input[name="sort"]').each((i, e) => e.value = sortValue);
});
<script src="{% static 'nimbus_ui_new/experiment_list.bundle.js' %}"></script>
{% endblock %}

Просмотреть файл

@ -231,6 +231,7 @@ STATICFILES_DIRS = [
("scripts", BASE_DIR / "legacy" / "legacy-ui" / "scripts"),
("imgs", BASE_DIR / "legacy" / "legacy-ui" / "imgs"),
("nimbus", BASE_DIR / "nimbus-ui" / "build"),
("nimbus_ui_new", BASE_DIR / "nimbus_ui_new" / "static" / "dist"),
BASE_DIR / "static",
]

Просмотреть файл

@ -4,7 +4,8 @@
"private": true,
"workspaces": [
"experimenter/legacy/legacy-ui/*",
"experimenter/nimbus-ui"
"experimenter/nimbus-ui",
"experimenter/nimbus_ui_new/static"
],
"devDependencies": {},
"resolutions": {
@ -17,7 +18,6 @@
"normalize-url": "^4.5.1",
"nth-check": "^2.0.1",
"object-path": "^0.11.5",
"postcss": "^7.0.36",
"prismjs": "^1.23.0",
"react-dev-utils": "^11.0.4",
"serialize-javascript": "^3.1.0",

Разница между файлами не показана из-за своего большого размера Загрузить разницу