Skip to content

Commit

Permalink
Add beginnings of feature-flagged Preact create group page
Browse files Browse the repository at this point in the history
Add the non-functional beginnings of a new, feature-flagged
re-implementation of the create-group page as a Preact app.
  • Loading branch information
seanh committed Jul 3, 2024
1 parent 3d064cf commit 83eb202
Show file tree
Hide file tree
Showing 15 changed files with 973 additions and 50 deletions.
26 changes: 25 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
{
"presets": ["@babel/preset-env"]
"presets": [
"@babel/preset-typescript",
[
"@babel/preset-react",
{
"runtime": "automatic",
"importSource": "preact"
}
],
"@babel/preset-env"
],
"env": {
"development": {
"presets": [
[
"@babel/preset-react",
{
"development": true,
"runtime": "automatic",
"importSource": "preact"
}
]
]
}
}
}
22 changes: 14 additions & 8 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,30 @@ import changed from 'gulp-changed';
import gulpIf from 'gulp-if';
import svgmin from 'gulp-svgmin';

import tailwindConfig from './tailwind.config.js';

const IS_PRODUCTION_BUILD = process.env.NODE_ENV === 'production';

gulp.task('build-js', () => buildJS('./rollup.config.js'));
gulp.task('watch-js', () => watchJS('./rollup.config.js'));

gulp.task('build-css', () =>
buildCSS([
'./node_modules/bootstrap/dist/css/bootstrap.css',
'./h/static/styles/admin.scss',
'./h/static/styles/help-page.scss',
'./h/static/styles/site.scss',
'./h/static/styles/vendor/icomoon.css',
]),
buildCSS(
[
'./node_modules/bootstrap/dist/css/bootstrap.css',
'./h/static/styles/admin.scss',
'./h/static/styles/help-page.scss',
'./h/static/styles/site.scss',
'./h/static/styles/vendor/icomoon.css',
'./h/static/styles/group-forms.css',
],
{ tailwindConfig },
),
);

gulp.task('watch-css', () => {
gulp.watch(
'h/static/styles/**/*.scss',
['h/static/styles/**/*.{css,scss}', 'h/static/scripts/**/*.{js,ts,tsx}'],
{ ignoreInitial: false },
gulp.series('build-css'),
);
Expand Down
6 changes: 6 additions & 0 deletions h/assets.ini
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ site_css =
help_page_css =
styles/icomoon.css
styles/help-page.css

group_forms_css =
styles/group-forms.css

group_forms_js =
scripts/group-forms.bundle.js
1 change: 1 addition & 0 deletions h/models/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"pdf_custom_text_layer": "Use custom text layer in PDFs for improved text selection",
"styled_highlight_clusters": "Style different clusters of highlights in the client",
"client_user_profile": "Enable client-side user profile and preferences management",
"preact_create_group_form": "Enable the new Preact version of the create group form",
}


Expand Down
55 changes: 55 additions & 0 deletions h/static/scripts/group-forms/components/CreateGroupForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export default function CreateGroupForm() {
return (
<>
<h1 class="form-header">Create a new private group</h1>

<form class="form group-form__form">
<div class="form-input">
<label for="name" class="form-input__label group-form__name-label">
Name <span class="form-input__required">*</span>
</label>
<input
type="text"
id="name"
class="form-input__input group-form__name-input has-label"
autofocus=""
autocomplete="off"
required
/>
<span class="form-input__character-counter is-ready">0/25</span>
</div>

<div class="form-input">
<label
class="form-input__label group-form__description-label"
for="description"
>
Description
</label>
<textarea
id="description"
class="form-input__input group-form__description-input has-label"
></textarea>
<span class="form-input__character-counter is-ready">0/250</span>
</div>

<div class="form-actions">
<div class="u-stretch"></div>

<div class="form-actions__buttons">
<button class="form-actions__btn btn primary-action-btn group-form__submit-btn">
Create group
</button>
</div>
</div>
</form>

<footer class="form-footer">
<span class="form-footer__required">
<span class="form-footer__symbol">*</span>
<span class="form-footer__text">Required</span>
</span>
</footer>
</>
);
}
9 changes: 9 additions & 0 deletions h/static/scripts/group-forms/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { render } from 'preact';

import CreateGroupForm from './components/CreateGroupForm';

function init() {
render(<CreateGroupForm />, document.querySelector('#create-group-form'));
}

init();
22 changes: 22 additions & 0 deletions h/static/scripts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"checkJs": true,
"lib": ["es2018", "dom"],
"jsx": "react-jsx",
"jsxImportSource": "preact",
"module": "commonjs",
"noEmit": true,
"strict": true,
"target": "ES2020",
"useUnknownInCatchVariables": false
},
"include": ["**/*.js", "**/*.ts", "**/*.tsx"],
"exclude": [
// Tests and test infrastructure
"**/test/*.js",
"bootstrap.js",
"karma.config.cjs"
]
}
5 changes: 5 additions & 0 deletions h/static/styles/group-forms.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* CSS entry point for the 'new group' app. */

@tailwind base;
@tailwind components;
@tailwind utilities;
23 changes: 23 additions & 0 deletions h/templates/groups/create.html.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% extends "h:templates/layouts/group.html.jinja2" %}

{% set page_title = 'Create a new private group' %}

{% block styles %}
{{ super() }}

{% for url in asset_urls('group_forms_css') %}
<link rel="stylesheet" href="{{ url }}">
{% endfor %}
{% endblock %}

{% block page_content %}
<div id="create-group-form"></div>
{% endblock %}

{% block scripts %}
{{ super() }}

{% for url in asset_urls('group_forms_js') %}
<script type="module" src="{{ url }}"></script>
{% endfor %}
{% endblock %}
18 changes: 18 additions & 0 deletions h/views/groups.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import deform
from pyramid import httpexceptions
from pyramid.config import not_
from pyramid.view import view_config, view_defaults

from h import form, i18n
Expand All @@ -13,6 +14,7 @@
route_name="group_create",
renderer="h:templates/groups/legacy_create.html.jinja2",
is_authenticated=True,
feature=not_("preact_create_group_form"),
)
class LegacyGroupCreateController:
def __init__(self, request):
Expand Down Expand Up @@ -64,6 +66,22 @@ def _template_data(self):
return {"form": self.form.render()}


@view_defaults(
route_name="group_create",
renderer="h:templates/groups/create.html.jinja2",
is_authenticated=True,
feature="preact_create_group_form",
)
class GroupCreateController:
def __init__(self, request):
self.request = request

@view_config(request_method="GET")
def get(self):
"""Render the page for creating a new group."""
return {}


@view_defaults(
route_name="group_edit",
renderer="h:templates/groups/edit.html.jinja2",
Expand Down
15 changes: 11 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@
"description": "The Internet, peer reviewed.",
"scripts": {
"build": "gulp build",
"checkformatting": "prettier --check *.js h/static/scripts",
"format": "prettier --list-different --write *.js h/static/scripts",
"checkformatting": "prettier --check *.{js,ts,tsx} h/static/scripts",
"format": "prettier --list-different --write *.{js,ts,tsx} h/static/scripts",
"lint": "eslint h/static/scripts",
"test": "gulp test"
},
"dependencies": {
"@babel/core": "^7.24.7",
"@babel/preset-env": "^7.24.6",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@hypothesis/frontend-build": "^3.0.0",
"@hypothesis/frontend-shared": "^7.11.2",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"autoprefixer": "^10.4.19",
"bootstrap": "^4.6.2",
"classnames": "^2.5.1",
"escape-html": "^1.0.3",
"gulp": "^5.0.0",
"gulp-changed": "^5.0.2",
Expand All @@ -31,10 +35,12 @@
"normalize.css": "^8.0.0",
"popper.js": "^1.16.1",
"postcss": "^8.4.39",
"preact": "^10.22.1",
"raven-js": "^3.7.0",
"rollup": "^4.18.0",
"sass": "^1.77.6",
"scroll-into-view": "^1.16.2"
"scroll-into-view": "^1.16.2",
"tailwindcss": "^3.4.4"
},
"devDependencies": {
"babel-plugin-mockable-imports": "^2.0.1",
Expand All @@ -54,7 +60,8 @@
"mocha": "^10.5.2",
"prettier": "^3.2.5",
"sinon": "^18.0.0",
"syn": "^0.2.2"
"syn": "^0.2.2",
"typescript": "^5.5.3"
},
"engines": {
"node": ">=6"
Expand Down
7 changes: 6 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ function bundleConfig(name, entryFile) {
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**',
extensions: ['.js', '.ts', '.tsx'],
}),
nodeResolve({
extensions: ['.js', '.ts', '.tsx'],
}),
nodeResolve(),
commonjs(),
...prodPlugins,
],
Expand All @@ -35,6 +38,8 @@ function bundleConfig(name, entryFile) {
export default [
// Public-facing website
bundleConfig('site', 'h/static/scripts/site.js'),
// Preact app for creating new private groups.
bundleConfig('group-forms', 'h/static/scripts/group-forms/index.tsx'),
// Admin areas of the site
bundleConfig('admin-site', 'h/static/scripts/admin-site.js'),
// Header script inserted inline at the top of the page
Expand Down
63 changes: 63 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import tailwindConfig from '@hypothesis/frontend-shared/lib/tailwind.preset.js';

export default {
presets: [tailwindConfig],
content: [
'./h/static/scripts/**/*.{js,ts,tsx}',
'./node_modules/@hypothesis/frontend-shared/lib/**/*.js',
],
theme: {
extend: {
animation: {
'fade-in': 'fade-in 0.3s forwards',
'fade-out': 'fade-out 0.3s forwards',
'slide-in-from-right': 'slide-in-from-right 0.3s forwards ease-in-out',
},
fontFamily: {
sans: [
'"Helvetica Neue"',
'Helvetica',
'Arial',
'"Lucida Grande"',
'sans-serif',
],
},
boxShadow: {
// Similar to tailwind's default `shadow-inner` but coming from the
// right edge instead of the left
'r-inner': 'inset -2px 0 4px 0 rgb(0,0,0,.05)',
},
keyframes: {
'fade-in': {
'0%': {
opacity: '0',
},
'100%': {
opacity: '1',
},
},
'fade-out': {
'0%': {
opacity: '1',
},
'100%': {
opacity: '0',
},
},
'slide-in-from-right': {
'0%': {
opacity: '0',
left: '100%',
},
'80%': {
left: '-10px',
},
'100%': {
left: '0',
opacity: '1',
},
},
},
},
},
};
11 changes: 11 additions & 0 deletions tests/unit/h/views/groups_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,17 @@ def handle_form_submission(self, patch):
return patch("h.views.groups.form.handle_form_submission")


class TestGroupCreateController:
def test_get(self, controller):
result = controller.get()

assert result == {}

@pytest.fixture
def controller(self, pyramid_request):
return views.GroupCreateController(pyramid_request)


@pytest.mark.usefixtures("routes")
class TestGroupEditController:
def test_get_reads_group_properties(self, pyramid_request, group):
Expand Down
Loading

0 comments on commit 83eb202

Please sign in to comment.