diff --git a/packages/admin/package.json b/packages/admin/package.json
index 4d01079..9a89d56 100644
--- a/packages/admin/package.json
+++ b/packages/admin/package.json
@@ -71,6 +71,7 @@
"access": "public"
},
"dependencies": {
- "@origami/zen": "^0.0.2-alpha.1"
+ "@origami/zen": "^0.0.4-alpha.0",
+ "@origami/zen-lib": "^0.0.4-alpha.0"
}
}
\ No newline at end of file
diff --git a/packages/admin/src/actions/UploadMedia.ts b/packages/admin/src/actions/UploadMedia.ts
index 1b2b3cf..05d1998 100644
--- a/packages/admin/src/actions/UploadMedia.ts
+++ b/packages/admin/src/actions/UploadMedia.ts
@@ -13,7 +13,7 @@ export const uploadProgress = (file: File) =>
const reader = new FileReader();
reader.onload = (e: ProgressEvent) => {
// @ts-ignore
- dispatch({ type: UPLOADING_MEDIA_PREVIEW, id, preview: e.target!.result});
+ dispatch({ type: UPLOADING_MEDIA_PREVIEW, id, preview: e.target!.result });
};
reader.readAsDataURL(file);
@@ -23,7 +23,7 @@ export const uploadProgress = (file: File) =>
request.open('POST', '/api/v1/media');
request.setRequestHeader('Authorization', API.token!);
- dispatch({type: UPLOADING_MEDIA_START, id, name: file.name});
+ dispatch({ type: UPLOADING_MEDIA_START, id, name: file.name });
request.upload.onprogress = ((e: ProgressEvent) => {
dispatch({
@@ -40,12 +40,21 @@ export const uploadProgress = (file: File) =>
});
});
- request.upload.onloadend = ((e: ProgressEvent) => {
- dispatch({
- type: UPLOADING_MEDIA_END,
- id
- });
- });
+ request.onreadystatechange = () => {
+ const ready = 4;
+ if (request.readyState === ready) {
+ dispatch({
+ type: UPLOADING_MEDIA_END,
+ id
+ });
+
+ dispatch({
+ type: 'MEDIA_CREATED',
+ media: JSON.parse(request.response).data
+ });
+
+ }
+ };
request.send(formData);
diff --git a/packages/admin/src/components/pages/Admin/Media/PageMedia.ts b/packages/admin/src/components/pages/Admin/Media/PageMedia.ts
index 0206e98..a351647 100644
--- a/packages/admin/src/components/pages/Admin/Media/PageMedia.ts
+++ b/packages/admin/src/components/pages/Admin/Media/PageMedia.ts
@@ -9,7 +9,9 @@ export class PageMedia extends titleSet('Media')(connect(store)(LitElement)) {
public static styles = [CSS];
public render() {
- return html``;
+ return html`
+
+ `;
}
}
diff --git a/packages/admin/src/components/pages/Admin/Media/page-media-css.ts b/packages/admin/src/components/pages/Admin/Media/page-media-css.ts
index ec30a95..3d9e941 100644
--- a/packages/admin/src/components/pages/Admin/Media/page-media-css.ts
+++ b/packages/admin/src/components/pages/Admin/Media/page-media-css.ts
@@ -1,4 +1,4 @@
import {css} from 'lit-element';
// tslint:disable-next-line no-default-export export-name
-export default css`.card{background:var(--card-bg, var(--color-white, #fff));border:var(--card-border, );border-radius:var(--card-border-radius, var(--border-radius, 0.4rem));padding:var(--card-padding, var(--size-main, 4rem));box-shadow:var(--card-shadow, var(--shadow-main-soft, 0 var(--size-tiny, 1rem) var(--size-main, 4rem) var(--color-main-soft, rgba(105,58,145,0.1))))}:host ui-media-grid{position:absolute;top:0;left:0;width:100%;height:100%}.card.hover{background-color:transparent;box-shadow:none;transition:all var(--transition-time)}.card.hover:hover{background-color:var(--card-bg);box-shadow:var(--card-shadow)}@keyframes fade-slide-up{from{margin-top:var(--size-large);opacity:0}to{margin-top:0;opacity:1}}:host{position:absolute;top:0;left:0;right:0;bottom:0;overflow-y:auto;padding:var(--size-small)}
+export default css`.card{background:var(--card-bg, var(--color-white, #fff));border:var(--card-border, );border-radius:var(--card-border-radius, var(--border-radius, 0.4rem));padding:var(--card-padding, var(--size-main, 4rem));box-shadow:var(--card-shadow, var(--shadow-main-soft, 0 var(--size-tiny, 1rem) var(--size-main, 4rem) var(--color-main-soft, rgba(105,58,145,0.1))))}.card.hover{background-color:transparent;box-shadow:none;transition:all var(--transition-time)}.card.hover:hover{background-color:var(--card-bg);box-shadow:var(--card-shadow)}@keyframes fade-slide-up{from{margin-top:var(--size-large);opacity:0}to{margin-top:0;opacity:1}}:host{position:absolute;top:0;left:0;right:0;bottom:0;overflow-y:auto;padding:var(--size-small)}
`;
diff --git a/packages/admin/src/components/pages/Admin/Media/page-media.scss b/packages/admin/src/components/pages/Admin/Media/page-media.scss
index 7d34ea6..2c14ce8 100644
--- a/packages/admin/src/components/pages/Admin/Media/page-media.scss
+++ b/packages/admin/src/components/pages/Admin/Media/page-media.scss
@@ -10,8 +10,4 @@
bottom: 0;
overflow-y: auto;
padding: var(--size-small);
-
- ui-media-grid {
- @extend %cover;
- }
}
diff --git a/packages/admin/src/components/ui/MediaGrid/MediaGrid.ts b/packages/admin/src/components/ui/MediaGrid/MediaGrid.ts
index d1927f8..1e8a110 100644
--- a/packages/admin/src/components/ui/MediaGrid/MediaGrid.ts
+++ b/packages/admin/src/components/ui/MediaGrid/MediaGrid.ts
@@ -42,6 +42,9 @@ export class MediaGrid extends connect(store)(LitElement) {
@property({ type: Boolean, attribute: true })
public multiple: boolean = false;
+ @property({ type: Boolean, attribute: true })
+ public searchable: boolean = false;
+
public get value() {
return this._value;
}
@@ -49,7 +52,6 @@ export class MediaGrid extends connect(store)(LitElement) {
@property()
private _value: MediaResource[] = [];
-
@property()
private _loading: boolean = true;
@@ -62,6 +64,9 @@ export class MediaGrid extends connect(store)(LitElement) {
@property()
private _meID: null | string = null;
+ @property()
+ private _filteredResources: GridResource[] = [];
+
@property({type: Boolean})
private _dragging: boolean = false;
@@ -106,9 +111,12 @@ export class MediaGrid extends connect(store)(LitElement) {
constructor() {
super();
- store.dispatch(mediaGet());
+ store.dispatch(mediaGet()).then(() => {
+ this._filteredResources = this._resources;
+ });
}
+
public connectedCallback() {
super.connectedCallback();
@@ -127,10 +135,21 @@ export class MediaGrid extends connect(store)(LitElement) {
public render() {
if (this._loading) return html``;
- const resources = this._resources;
- const empty = resources.length === 0;
+ const _resources = this._resources;
+ const resources = this.searchable ? this._filteredResources : _resources;
+ const empty = _resources.length === 0 && resources.length === 0;
return html`
+ ${this.searchable
+ ? html` this._filteredResources = detail}
+ placeholder="Search for media…">
+ `
+ : null
+ }
+
${repeat(resources, (r) => r.src, (r, i) => html`
- extends LitElement {
+ public static styles = [CSS];
+
+
+ /**
+ * The items to filter
+ */
+ @property()
+ public set items(v) {
+ this._items = v;
+ }
+ public get items() {
+ return this._items;
+ }
+
+ /**
+ * The text entered to filter the items
+ */
+ @property()
+ get filter() {
+ return this._filter;
+ }
+ set filter(v) {
+ this._filter = v;
+ if (!this._fuse || !v) this._filtered = [];
+ else this._filtered = this._fuse.search(v);
+
+ this.dispatchEvent(new CustomEvent(
+ SEARCH_EVENT_FILTERED,
+ {detail: this.filter ? this._filtered : this.items}
+ ));
+ }
+
+
+ get filtered() {
+ if (!this.filter) return this.items;
+ return this._filtered;
+ }
+
+
+ @property({type: String})
+ public placeholder: string = 'Search…';
+
+ /**
+ * Keys to pass into Fuse.js to lookup on the items
+ */
+ @property({type: Array})
+ public keys: (keyof FilterItem)[] = [];
+
+ @property()
+ private _filtered: FilterItem[] = [];
+
+ private _items: FilterItem[] = [];
+
+ @property()
+ private _fuse?: Fuse;
+ private _filter: string | null = null;
+
+
+ public render() {
+ return html`
+ `;
+ }
+
+
+ public updated(props: Map, string>) {
+ if (props.has('items') || props.has('keys')) {
+ this._fuse = new Fuse(this.items, {
+ keys: this.keys
+ });
+ }
+ }
+
+ private _onChange(e: Event) {
+ this.filter = (e.target as ZenInput).value;
+ }
+}
+
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'ui-search': Search;
+ }
+}
diff --git a/packages/admin/src/components/ui/Search/search-css.ts b/packages/admin/src/components/ui/Search/search-css.ts
new file mode 100644
index 0000000..2c2b7d8
--- /dev/null
+++ b/packages/admin/src/components/ui/Search/search-css.ts
@@ -0,0 +1,4 @@
+import {css} from 'lit-element';
+// tslint:disable-next-line no-default-export export-name
+export default css`:host{display:block}:host zen-input{width:100%}
+`;
diff --git a/packages/admin/src/components/ui/Search/search.scss b/packages/admin/src/components/ui/Search/search.scss
new file mode 100644
index 0000000..8013789
--- /dev/null
+++ b/packages/admin/src/components/ui/Search/search.scss
@@ -0,0 +1,7 @@
+:host {
+ display: block;
+
+ zen-input {
+ width: 100%;
+ }
+}
diff --git a/packages/admin/src/components/ui/index.ts b/packages/admin/src/components/ui/index.ts
index e66cfa2..1448991 100644
--- a/packages/admin/src/components/ui/index.ts
+++ b/packages/admin/src/components/ui/index.ts
@@ -9,6 +9,7 @@ export * from './Modal/Modal';
export * from './Modal/ModalContainer';
export * from './ResourcePage/ResourcePage';
export * from './ResourceTable/ResourceTable';
+export * from './Search/Search';
export * from './Sidebar/Sidebar';
export * from './SideMenu/SideMenu';
export * from './UploadProgress/UploadProgress';
diff --git a/packages/admin/src/reducers/UploadingMedia.ts b/packages/admin/src/reducers/UploadingMedia.ts
index 6e14347..7f09e95 100644
--- a/packages/admin/src/reducers/UploadingMedia.ts
+++ b/packages/admin/src/reducers/UploadingMedia.ts
@@ -1,7 +1,7 @@
import { AnyAction } from 'redux';
// tslint:disable-next-line match-default-export-name
import immutable, { ImmutableObjectMixin } from 'seamless-immutable';
-import { UPLOADING_MEDIA_PREVIEW, UPLOADING_MEDIA_PROGRESS, UPLOADING_MEDIA_START } from '../actions/UploadMedia';
+import { UPLOADING_MEDIA_END, UPLOADING_MEDIA_PREVIEW, UPLOADING_MEDIA_PROGRESS, UPLOADING_MEDIA_START } from '../actions/UploadMedia';
import { UploadingMedia as StateUploadingMedia, UploadingResource } from '../store/state';
const initialState = immutable.from({
@@ -39,6 +39,12 @@ export const UploadingMedia = (
return state.setIn(['uploading', index2, 'preview'], action.preview);
+ case UPLOADING_MEDIA_END:
+ return state.set(
+ 'uploading',
+ state.asMutable().uploading.filter((u) => u.id !== action.id)
+ );
+
default:
return state;
diff --git a/packages/admin/src/store/store.ts b/packages/admin/src/store/store.ts
index 7cb0b01..c0a0c34 100644
--- a/packages/admin/src/store/store.ts
+++ b/packages/admin/src/store/store.ts
@@ -1,4 +1,4 @@
-import { applyMiddleware } from 'redux';
+import { applyMiddleware, compose } from 'redux';
// tslint:disable-next-line match-default-export-name
import thunkMiddleware from 'redux-thunk';
import { createInjectStore } from '../lib/reduxInjector';
@@ -7,8 +7,12 @@ import { reducers } from '../reducers';
export const store = createInjectStore(
reducers,
- applyMiddleware(
- thunkMiddleware
+ compose(
+ applyMiddleware(
+ thunkMiddleware,
+ ),
+ // @ts-ignore
+ window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
diff --git a/yarn.lock b/yarn.lock
index fe23a99..e12eb69 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -965,9 +965,15 @@
tslint-eslint-rules "^5.4.0"
tslint-xo "^0.9.0"
-"@origami/zen@^0.0.2-alpha.1":
- version "0.0.2-alpha.1"
- resolved "https://registry.yarnpkg.com/@origami/zen/-/zen-0.0.2-alpha.1.tgz#0351148bf84b65a4ec0f8bc48f7b5f5bd3e0f312"
+"@origami/zen-lib@^0.0.4-alpha.0":
+ version "0.0.4-alpha.0"
+ resolved "https://registry.yarnpkg.com/@origami/zen-lib/-/zen-lib-0.0.4-alpha.0.tgz#244d176871d87823c2df2436fbec6e47da98f9dd"
+ dependencies:
+ polymer3-decorators "^0.0.1"
+
+"@origami/zen@^0.0.4-alpha.0":
+ version "0.0.4-alpha.0"
+ resolved "https://registry.yarnpkg.com/@origami/zen/-/zen-0.0.4-alpha.0.tgz#947aa3e9997a62281b46b2e3e030f27597a607e2"
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.0"
@@ -7918,6 +7924,12 @@ pngjs@^3.0.0, pngjs@^3.2.0:
version "3.3.3"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b"
+polymer3-decorators@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/polymer3-decorators/-/polymer3-decorators-0.0.1.tgz#6667bf7c7ed596bc6cc62892243b075ecad9eaea"
+ dependencies:
+ reflect-metadata "^0.1.10"
+
posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@@ -8491,7 +8503,7 @@ referrer-policy@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.1.0.tgz#35774eb735bf50fb6c078e83334b472350207d79"
-reflect-metadata@^0.1.12:
+reflect-metadata@^0.1.10, reflect-metadata@^0.1.12:
version "0.1.13"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"