diff --git a/common/actions.js b/common/actions.js index 3fb8cb5f..5b7b5012 100644 --- a/common/actions.js +++ b/common/actions.js @@ -206,6 +206,13 @@ export const deleteBucketItem = async (data) => { }); }; +export const deleteBucketItems = async (data) => { + return await returnJSON(`/api/data/remove-multiple`, { + ...DEFAULT_OPTIONS, + body: JSON.stringify({ data }), + }); +}; + export const getSerializedSlate = async (data) => { return await returnJSON(`/api/slates/get-serialized`, { ...DEFAULT_OPTIONS, diff --git a/common/constants.js b/common/constants.js index ddbdf307..a3198053 100644 --- a/common/constants.js +++ b/common/constants.js @@ -1,3 +1,6 @@ +import React from "react"; +import * as SVG from "~/common/svg"; + export const values = { version: "1.0.0", sds: "0.1.0", @@ -79,3 +82,27 @@ export const theme = { export const gateways = { ipfs: "https://slate.textile.io/ipfs", }; + +export function FileTypeIcon(props) { + if (props.type && props.type.startsWith("image/")) { + return ; + } + + if (props.type && props.type.startsWith("video/")) { + return ; + } + + if (props.type && props.type.startsWith("audio/")) { + return ; + } + + if (props.type && props.type.startsWith("application/epub")) { + return ; + } + + if (props.type && props.type.startsWith("application/pdf")) { + return ; + } + + return ; +} diff --git a/common/svg.js b/common/svg.js index c53ca246..4f5fc4e7 100644 --- a/common/svg.js +++ b/common/svg.js @@ -593,6 +593,25 @@ export const Slate = (props) => ( ); +export const Trash = (props) => ( + + + + + + +); + export const Folder = (props) => ( Name, - width: "100%", - }, - { - key: "size", - name: Size, - width: "104px", - }, - { - key: "more", - name:
, - width: "64px", - }, -]; +const STYLES_CONTAINER_HOVER = css` + display: flex; + + :hover { + color: ${Constants.system.brand}; + } +`; const STYLES_LINK = css` + display: inline; cursor: pointer; transition: 200ms ease all; font-size: 0.9rem; @@ -41,10 +34,6 @@ const STYLES_LINK = css` overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - - :hover { - color: ${Constants.system.brand}; - } `; const STYLES_VALUE = css` @@ -55,18 +44,8 @@ const STYLES_VALUE = css` white-space: nowrap; `; -const STYLES_TABLE_VALUE = { - fontFamily: Constants.font.medium, - padding: "0px 24px", -}; - -const STYLES_TABLE_CONTAINER = css` - border: 1px solid rgba(229, 229, 229, 0.75); -`; - const STYLES_ICON_BOX = css` - display: flex; - justify-content: flex-end; + display: inline-flex; align-items: center; padding: 8px; cursor: pointer; @@ -85,6 +64,7 @@ const STYLES_COPY_INPUT = css` const STYLES_IMAGE_GRID = css` display: flex; flex-direction: row; + justify-content: space-between; flex-wrap: wrap; margin: 0 -27px; `; @@ -109,6 +89,7 @@ export default class DataView extends React.Component { state = { menu: null, + checked: {}, loading: {}, }; @@ -385,6 +366,13 @@ export default class DataView extends React.Component { return null; } + dispatchCustomEvent({ + name: "create-alert", + detail: { + alert: { message: "File successfully deleted!", status: "INFO" }, + }, + }); + await this.props.onRehydrate(); await this._handleUpdate(); this._handleLoading({ cid }); @@ -419,16 +407,73 @@ export default class DataView extends React.Component { ); } - const columns = COLUMNS_SCHEMA; + const columns = [ + { + key: "checkbox", + name: , + width: "24px", + }, + { + key: "name", + name:
Name
, + width: "100%", + }, + { + key: "size", + name:
Size
, + width: "104px", + }, + { + key: "more", + name: , + width: "48px", + }, + ]; const rows = this.props.items.map((each, index) => { const cid = each.ipfs.replace("/ipfs/", ""); const isOnNetwork = each.networks && each.networks.includes("FILECOIN"); return { ...each, + checkbox: this.props.onCheckBox ? ( +
0 + ? 1 + : this.state.hover === index + ? 1 + : 0, + }} + > + +
+ ) : ( +
+ ), name: ( -
this._handleSelect(index)}> - {each.file || each.name} +
this._handleSelect(index)} + > +
+ +
+
{each.file || each.name}
), size:
{Strings.bytesToSize(each.size)}
, @@ -496,19 +541,13 @@ export default class DataView extends React.Component { }; return ( -
- + this.setState({ hover: i })} + onMouseLeave={() => this.setState({ hover: null })} /> { @@ -518,7 +557,7 @@ export default class DataView extends React.Component { value={this.state.copyValue} css={STYLES_COPY_INPUT} /> - + ); } } diff --git a/components/core/SlateMediaObjectPreview.js b/components/core/SlateMediaObjectPreview.js index d1c3bd98..296e9930 100644 --- a/components/core/SlateMediaObjectPreview.js +++ b/components/core/SlateMediaObjectPreview.js @@ -51,75 +51,21 @@ export default class SlateMediaObjectPreview extends React.Component { ? this.props.title.substring(0, this.props.charCap) + "..." : this.props.title; + if (this.props.type && this.props.type.startsWith("image/")) { + return ; + } + let element = ( + + ); + + return (
-
- -
+
{element}
{this.props.title && !this.props.small ? (
{title}
) : null}
); - - if (this.props.type && this.props.type.startsWith("video/")) { - element = ( -
-
- -
- {this.props.title && !this.props.small ? ( -
{title}
- ) : null} -
- ); - } - - if (this.props.type && this.props.type.startsWith("audio/")) { - element = ( -
-
- -
- {this.props.title && !this.props.small ? ( -
{title}
- ) : null} -
- ); - } - - if (this.props.type && this.props.type.startsWith("application/epub")) { - element = ( -
-
- -
- {this.props.title && !this.props.small ? ( -
{title}
- ) : null} -
- ); - } - - if (this.props.type && this.props.type.startsWith("application/pdf")) { - element = ( -
-
- -
- {this.props.title && !this.props.small ? ( -
{title}
- ) : null} -
- ); - } - - if (this.props.type && this.props.type.startsWith("image/")) { - element = ( - - ); - } - - return element; } } diff --git a/components/core/SlatePreviewBlock.js b/components/core/SlatePreviewBlock.js index 8e61643f..dcc4ebd4 100644 --- a/components/core/SlatePreviewBlock.js +++ b/components/core/SlatePreviewBlock.js @@ -16,6 +16,7 @@ const STYLES_IMAGE_ROW = css` flex-direction: row; flex-wrap: wrap; height: 160px; + justify-content: space-between; overflow: hidden; @media (max-width: ${Constants.sizes.mobile}px) { @@ -26,7 +27,7 @@ const STYLES_IMAGE_ROW = css` const STYLES_ITEM_BOX = css` width: 160px; height: 160px; - margin: 0px 18px; + margin: 0px 12px; display: flex; align-items: center; justify-content: center; diff --git a/components/core/Table.js b/components/core/Table.js new file mode 100644 index 00000000..5ca14324 --- /dev/null +++ b/components/core/Table.js @@ -0,0 +1,131 @@ +import * as React from "react"; +import * as Constants from "~/common/constants"; +import * as Strings from "~/common/strings"; +import * as SubSystem from "~/components/system/components/fragments/TableComponents"; + +import { css } from "@emotion/react"; +import { P } from "~/components/system/components/Typography"; +import * as SVG from "~/common/svg"; + +const TABLE_COLUMN_WIDTH_DEFAULTS = { + 1: "100%", + 2: "50%", + 3: "33.333%", + 4: "25%", + 5: "20%", + 6: "16.666%", + 7: "14.28%", + 8: "12.5%", +}; + +const STYLES_CONTAINER = css` + border: 1px solid rgba(229, 229, 229, 0.75); +`; + +const STYLES_TABLE_ROW = css` + position: relative; + box-sizing: border-box; + border-bottom: 1px solid rgba(229, 229, 229, 0.75); + display: flex; + align-items: center; + width: 100%; + transition: 200ms ease all; + + :last-child { + border: 0; + } +`; + +const STYLES_TABLE_TOP_ROW = css` + box-sizing: border-box; + font-family: ${Constants.font.semiBold}; + border-bottom: 1px solid rgba(229, 229, 229, 0.75); + display: flex; + width: 100%; + align-items: center; + background-color: ${Constants.system.foreground}; +`; + +export class Table extends React.Component { + render() { + const { data } = this.props; + + const ac = {}; + + if (!data || !data.rows || data.rows.length === 0) { + return

No data.

; + } + + for (let x = 0; x < data.columns.length; x++) { + ac[data.columns[x].key] = { + ...data.columns[x], + index: x, + }; + } + + const width = TABLE_COLUMN_WIDTH_DEFAULTS[data.columns.length]; + return ( +
+ {this.props.noLabel ? null : ( +
+ {data.columns.map((c, cIndex) => { + let localWidth = c.width ? c.width : width; + let flexShrink = c.width && c.width !== "100%" ? "0" : null; + if (cIndex === 0 && !c.width) { + localWidth = "100%"; + } + + return ( +
+ {c.name || ""} +
+ ); + })} +
+ )} + + {data.rows.map((r, i) => { + return ( +
this.props.onMouseEnter(i)} + > + {Object.keys(ac).map((each, cIndex) => { + const field = ac[each]; + const content = r[each]; + + let localWidth = field.width ? field.width : width; + let flexShrink = + field.width && field.width !== "100%" ? "0" : null; + if (cIndex === 0 && !field.width) { + localWidth = "100%"; + } + + return ( +
+ {content} +
+ ); + })} +
+ ); + })} +
+ ); + } +} diff --git a/components/system/components/CheckBox.js b/components/system/components/CheckBox.js index 67d4cb9d..12ffc130 100644 --- a/components/system/components/CheckBox.js +++ b/components/system/components/CheckBox.js @@ -25,8 +25,8 @@ const STYLES_CHECKBOX_FIGURE = css` justify-content: center; pointer-events: none; flex-shrink: 0; - height: 32px; - width: 32px; + height: 24px; + width: 24px; margin: 0; padding: 0; `; @@ -74,7 +74,7 @@ export class CheckBox extends React.Component { render() { return (