Skip to content

Commit 2e37e54

Browse files
committed
feat: WIP content browser component
1 parent 450b5ea commit 2e37e54

File tree

8 files changed

+167
-0
lines changed

8 files changed

+167
-0
lines changed

.storybook/main.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,40 @@ module.exports = {
3838
use: ["@svgr/webpack"],
3939
});
4040

41+
// Support Svelte
42+
config.module.rules.push({
43+
test: /\.svelte$/,
44+
use: [
45+
{
46+
loader: "svelte-loader",
47+
options: {
48+
compilerOptions: {
49+
dev: true,
50+
},
51+
emitCss: true,
52+
hotReload: true,
53+
},
54+
},
55+
],
56+
});
57+
58+
// TODO: make the mock work
59+
// Force Storybook to always use the mock instead of the real component ?
60+
config.resolve.alias["./src/pat/contentbrowser/src/App.svelte"] = path.resolve(
61+
__dirname,
62+
"../src/pat/contentbrowser/src/App.mock.js"
63+
);
64+
config.resolve.alias["#pat/contentbrowser/src/App"] = path.resolve(
65+
__dirname,
66+
"../src/pat/contentbrowser/src/App.mock.js"
67+
);
68+
config.resolve.alias["./src/pat/contentbrowser/src/SelectedItem.svelte"] =
69+
path.resolve(__dirname, "../src/pat/contentbrowser/src/App.mock.js");
70+
config.resolve.alias["#pat/contentbrowser/src/App"] = path.resolve(
71+
__dirname,
72+
"../src/pat/contentbrowser/src/SelectedItem.mock.js"
73+
);
74+
4175
return config;
4276
},
4377
};

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@
101101
"sass": "~1.77.8",
102102
"underscore": "1.13.7"
103103
},
104+
"imports": {
105+
"#pat/contentbrowser/src/App": {
106+
"storybook": "./src/pat/contentbrowser/src/App.mock.js",
107+
"default": "./src/pat/contentbrowser/src/App.svelte"
108+
},
109+
"#pat/contentbrowser/src/SelectedItem": {
110+
"storybook": "./src/pat/contentbrowser/src/SelectedItem.mock.js",
111+
"default": "./src/pat/contentbrowser/src/SelectedItem.svelte"
112+
}
113+
},
104114
"scripts": {
105115
"clean": "rimraf docs/_site",
106116
"build:webpack": "NODE_ENV=production webpack --config webpack.config.js",
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Meta, Story } from "@storybook/addon-docs";
2+
import { ContentBrowser } from "./contentbrowser.stories.js";
3+
4+
<Meta title="Patterns/ContentBrowser" />
5+
6+
# Contentbrowser
7+
8+
Show a widget to select items in an offcanvas miller-column browser.
9+
10+
## Configuration
11+
12+
```md
13+
| Option | Type | Default | Description |
14+
| :------------------: | :-----: | :-------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------: |
15+
| vocabularyUrl | string | null | This is a URL to a JSON-formatted file used to populate the list |
16+
| attributes | array | ['UID', 'Title', 'portal_type', 'path'] | This list is passed to the server during an AJAX request to specify the attributes which should be included on each item. |
17+
| rootPath | string | "/" | Browsing/searching root path. You will not get beneath this path |
18+
| rootUrl | string | | Browsing/searching root url. |
19+
| basePath | string | set to rootPath. | Start browse/search in this path. |
20+
| contextPath | string | | Path of the object, which is currently edited. If this path is given, this object will not be selectable. |
21+
| favorites | array | [] | Array of objects. These are favorites, which can be used to quickly jump to different locations. Objects have the attributes "title" and "path". |
22+
| maximumSelectionSize | integer | -1 | The maximum number of items that can be selected in a multi-select control. If this number is less than 1 selection is not limited. |
23+
| mode | string | "browse" | Toggle between "browse" and "search" |
24+
| width | integer | | Override the width of the selected items field |
25+
| bSize | integer | 10 | Batch size of the items listed in levels |
26+
| maxDepth | integer | | Maximum level depth for "browse" mode |
27+
| separator | string | ',' | Select2 option. String which separates multiple items. |
28+
| upload | boolean | | Allow file and image uploads from within the related items widget. |
29+
| recentlyUsed | boolean | false | Show the recently used items dropdown. |
30+
| recentlyUsedKey | integer | | Storage key for saving the recently used items. This is generated with fieldname and username in the patternoptions. |
31+
| recentlyUsedMaxItems | integer | 20 | Maximum items to keep in recently used list. 0: no restriction. |
32+
| customComponentKeys | dict | {} | Register custom components. Currently only "SelectedItem" implemented |
33+
```
34+
35+
## Examples
36+
37+
### Simple
38+
39+
<br />
40+
<Story name="Content Browser" of={ContentBrowser} />
41+
42+
```html
43+
<input
44+
type="text"
45+
class="pat-contentbrowser"
46+
data-pat-contentbrowser='{"selectableTypes": ["Document"], "vocabularyUrl": "contentbrowser-test.json"}'
47+
/>
48+
```

src/pat/contentbrowser/contentbrowser.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import registry from "@patternslib/patternslib/src/core/registry";
44
import utils from "../../core/utils";
55
import plone_registry from "@plone/registry";
66

7+
// TODO: make SB mock work ?
8+
// Subpath imports from package.json (so Storybook can mock them)
9+
import SelectedItem from "#pat/contentbrowser/src/SelectedItem";
10+
import ContentBrowserApp from "#pat/contentbrowser/src/App";
11+
712
// Contentbrowser pattern
813

914
export const parser = new Parser("contentbrowser");
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import $ from "jquery";
2+
import { RenderHTML } from "../../../.storybook/setup.js";
3+
import ContentBrowserComponent from "./contentbrowser.js";
4+
5+
export default {
6+
title: "Patterns/ContentBrowser",
7+
parameters: {
8+
mockData: [
9+
{
10+
url: "/contentbrowser-test.json", // Fake API URL
11+
method: "GET",
12+
status: 200,
13+
response: {
14+
items: [
15+
{
16+
UID: "1234",
17+
Title: "Example Document",
18+
path: "/example-document",
19+
},
20+
{ UID: "5678", Title: "Another Item", path: "/another-item" },
21+
],
22+
},
23+
},
24+
],
25+
},
26+
};
27+
28+
// Basic Contentbrowser
29+
const getContentBrowser = (args) => `
30+
<input
31+
type="text"
32+
class="pat-contentbrowser"
33+
data-pat-contentbrowser='{"vocabularyUrl": "${args.vocabularyUrl}"}'
34+
/>
35+
`;
36+
37+
// TODO:
38+
// Story for this component: error Invalid URL
39+
// Check svelte components mocks ?
40+
export const ContentBrowser = {
41+
render: (args) => RenderHTML(args, getContentBrowser),
42+
args: {
43+
vocabularyUrl: "/contentbrowser-test.json",
44+
},
45+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
console.log("Using App:", import.meta.url);
2+
3+
// TODO:
4+
// How to prevent App.svelte from running ?
5+
// both mock and real App.svelte are running rn
6+
if (typeof window !== "undefined") {
7+
console.log({ aqui: window.ContentBrowserApp });
8+
window.ContentBrowserApp = "alala";
9+
console.log({ aqui: window.ContentBrowserApp });
10+
}
11+
12+
export default function MockContentBrowserApp({ target, props }) {
13+
console.log("MockSelectedItem initialized with", props);
14+
target.innerHTML = `<div style="border: 2px solid blue; padding: 10px;">
15+
Mocked Content Browser App
16+
</div>`;
17+
}

src/pat/contentbrowser/src/App.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script>
2+
console.log("Using App:", import.meta.url);
3+
24
import logger from "@patternslib/patternslib/src/core/logging";
35
import { getContext } from "svelte";
46
import ContentBrowser from "./ContentBrowser.svelte";
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default function MockSelectedItem({ target, props }) {
2+
console.log("MockSelectedItem initialized with", props);
3+
target.innerHTML = `<div style="border: 2px solid blue; padding: 10px;">
4+
Mocked Selected Item
5+
</div>`;
6+
}

0 commit comments

Comments
 (0)