aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionView.tsx
diff options
context:
space:
mode:
authorljungster <parkerljung@gmail.com>2022-08-09 11:52:07 -0500
committerljungster <parkerljung@gmail.com>2022-08-09 11:52:07 -0500
commitda3cb00f809a482a9fdf732f6a656fbc467cce27 (patch)
tree9eb1fd278bc71d080d71bbfb7e3aec482d35f439 /src/client/views/collections/CollectionView.tsx
parent1638527259a072dfc2ab286bd27bbb1751e8434e (diff)
parent26670c8b9eb6e2fd981c3a0997bff5556b60504b (diff)
Merge branch 'parker' of https://github.com/brown-dash/Dash-Web into parker
Diffstat (limited to 'src/client/views/collections/CollectionView.tsx')
-rw-r--r--src/client/views/collections/CollectionView.tsx239
1 files changed, 126 insertions, 113 deletions
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 54b0a2af3..1ee77d4ce 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,26 +1,26 @@
import { computed, observable, runInAction } from 'mobx';
-import { observer } from "mobx-react";
+import { observer } from 'mobx-react';
import * as React from 'react';
-import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app
import { Doc, DocListCast } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { ObjectField } from '../../../fields/ObjectField';
import { ScriptField } from '../../../fields/ScriptField';
-import { Cast, ScriptCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
import { returnEmptyString } from '../../../Utils';
import { DocUtils } from '../../documents/Documents';
+import { CollectionViewType } from '../../documents/DocumentTypes';
import { BranchCreate, BranchTask } from '../../documents/Gitlike';
-import { CurrentUserUtils } from '../../util/CurrentUserUtils';
import { ImageUtils } from '../../util/Import & Export/ImageUtils';
import { InteractionUtils } from '../../util/InteractionUtils';
-import { ContextMenu } from "../ContextMenu";
+import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
+import { DashboardView } from '../DashboardView';
import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent';
import { FieldView, FieldViewProps } from '../nodes/FieldView';
import { CollectionCarousel3DView } from './CollectionCarousel3DView';
import { CollectionCarouselView } from './CollectionCarouselView';
-import { CollectionDockingView } from "./CollectionDockingView";
+import { CollectionDockingView } from './CollectionDockingView';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import { CollectionGridView } from './collectionGrid/CollectionGridView';
import { CollectionLinearView } from './collectionLinear';
@@ -28,73 +28,58 @@ import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMul
import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView';
import { CollectionNoteTakingView } from './CollectionNoteTakingView';
import { CollectionPileView } from './CollectionPileView';
-import { CollectionSchemaView } from "./collectionSchema/CollectionSchemaView";
+import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView';
import { CollectionStackingView } from './CollectionStackingView';
import { SubCollectionViewProps } from './CollectionSubView';
import { CollectionTimeView } from './CollectionTimeView';
-import { CollectionTreeView } from "./CollectionTreeView";
+import { CollectionTreeView } from './CollectionTreeView';
import './CollectionView.scss';
export const COLLECTION_BORDER_WIDTH = 2;
const path = require('path');
-//TODO: see everywhere that this exists
-export enum CollectionViewType {
- Invalid = "invalid",
- Freeform = "freeform",
- Schema = "schema",
- Docking = "docking",
- Tree = 'tree',
- Stacking = "stacking",
- Masonry = "masonry",
- Multicolumn = "multicolumn",
- Multirow = "multirow",
- Time = "time",
- Carousel = "carousel",
- Carousel3D = "3D Carousel",
- Linear = "linear",
- //Staff = "staff",
- Map = "map",
- Grid = "grid",
- Pile = "pileup",
- StackedTimeline = "stacked timeline",
- NoteTaking = "notetaking"
-}
-export interface CollectionViewProps extends FieldViewProps {
- isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc)
+interface CollectionViewProps_ extends FieldViewProps {
+ isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc)
isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
layoutEngine?: () => string;
setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void;
// property overrides for child documents
- children?: never | (() => JSX.Element[]) | React.ReactNode;
childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
- childDocumentsActive?: () => boolean;// whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode)
+ childDocumentsActive?: () => boolean; // whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode)
childFitWidth?: (child: Doc) => boolean;
childShowTitle?: () => string;
childOpacity?: () => number;
- childContextMenuItems?: () => { script: ScriptField, label: string }[];
+ childContextMenuItems?: () => { script: ScriptField; label: string }[];
childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children
childHideDecorationTitle?: () => boolean;
childHideResizeHandles?: () => boolean;
- childLayoutTemplate?: () => (Doc | undefined);// specify a layout Doc template to use for children of the collection
+ childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection
childLayoutString?: string;
- childFreezeDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height
childIgnoreNativeSize?: boolean;
childClickScript?: ScriptField;
childDoubleClickScript?: ScriptField;
+ //TODO: [AL] add these fields
+ AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+ RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+ hierarchyIndex?: number[]; // hierarchical index of a document up to the rendering root (primarily used for tree views)
}
+export interface CollectionViewProps extends React.PropsWithChildren<CollectionViewProps_> {}
@observer
export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & CollectionViewProps>() {
- public static LayoutString(fieldStr: string) { return FieldView.LayoutString(CollectionView, fieldStr); }
+ public static LayoutString(fieldStr: string) {
+ return FieldView.LayoutString(CollectionView, fieldStr);
+ }
@observable private static _safeMode = false;
- public static SetSafeMode(safeMode: boolean) { this._safeMode = safeMode; }
+ public static SetSafeMode(safeMode: boolean) {
+ this._safeMode = safeMode;
+ }
protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
constructor(props: any) {
super(props);
- runInAction(() => this._annotationKeySuffix = returnEmptyString);
+ runInAction(() => (this._annotationKeySuffix = returnEmptyString));
}
get collectionViewType(): CollectionViewType | undefined {
@@ -102,15 +87,17 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
if (CollectionView._safeMode) {
switch (viewField) {
case CollectionViewType.Freeform:
- case CollectionViewType.Schema: return CollectionViewType.Tree;
- case CollectionViewType.Invalid: return CollectionViewType.Freeform;
+ case CollectionViewType.Schema:
+ return CollectionViewType.Tree;
+ case CollectionViewType.Invalid:
+ return CollectionViewType.Freeform;
}
}
return viewField as any as CollectionViewType;
}
showIsTagged = () => {
- return (null);
+ return null;
// this section would display an icon in the bototm right of a collection to indicate that all
// photos had been processed through Google's content analysis API and Google's tags had been
// assigned to the documents googlePhotosTags field.
@@ -119,9 +106,10 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
// const allTagged = imageProtos.length > 0 && imageProtos.every(image => image.googlePhotosTags);
// return !allTagged ? (null) : <img id={"google-tags"} src={"/assets/google_tags.png"} />;
//this.isContentActive();
- }
+ };
- screenToLocalTransform = () => this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth());
+ screenToLocalTransform = () => (this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth()));
+ // prettier-ignore
private renderSubView = (type: CollectionViewType | undefined, props: SubCollectionViewProps) => {
TraceMobx();
if (type === undefined) return null;
@@ -144,110 +132,132 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
case CollectionViewType.Grid: return <CollectionGridView key="collview" {...props} />;
//case CollectionViewType.Staff: return <CollectionStaffView key="collview" {...props} />;
}
- }
+ };
setupViewTypes(category: string, func: (viewType: CollectionViewType) => Doc, addExtras: boolean) {
const subItems: ContextMenuProps[] = [];
- subItems.push({ description: "Freeform", event: () => func(CollectionViewType.Freeform), icon: "signature" });
+ subItems.push({ description: 'Freeform', event: () => func(CollectionViewType.Freeform), icon: 'signature' });
if (addExtras && CollectionView._safeMode) {
- ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => func(CollectionViewType.Invalid), icon: "project-diagram" });
+ ContextMenu.Instance.addItem({ description: 'Test Freeform', event: () => func(CollectionViewType.Invalid), icon: 'project-diagram' });
}
- subItems.push({ description: "Schema", event: () => func(CollectionViewType.Schema), icon: "th-list" });
- subItems.push({ description: "Tree", event: () => func(CollectionViewType.Tree), icon: "tree" });
- subItems.push({ description: "Stacking", event: () => func(CollectionViewType.Stacking)._autoHeight = true, icon: "ellipsis-v" });
- subItems.push({ description: "Note taking", event: () => func(CollectionViewType.NoteTaking)._autoHeight = true, icon: "ellipsis-v" });
- subItems.push({ description: "Multicolumn", event: () => func(CollectionViewType.Multicolumn), icon: "columns" });
- subItems.push({ description: "Multirow", event: () => func(CollectionViewType.Multirow), icon: "columns" });
- subItems.push({ description: "Masonry", event: () => func(CollectionViewType.Masonry), icon: "columns" });
- subItems.push({ description: "Carousel", event: () => func(CollectionViewType.Carousel), icon: "columns" });
- subItems.push({ description: "3D Carousel", event: () => func(CollectionViewType.Carousel3D), icon: "columns" });
- !Doc.UserDoc().noviceMode && subItems.push({ description: "Pivot/Time", event: () => func(CollectionViewType.Time), icon: "columns" });
- !Doc.UserDoc().noviceMode && subItems.push({ description: "Map", event: () => func(CollectionViewType.Map), icon: "globe-americas" });
- subItems.push({ description: "Grid", event: () => func(CollectionViewType.Grid), icon: "th-list" });
+ subItems.push({ description: 'Schema', event: () => func(CollectionViewType.Schema), icon: 'th-list' });
+ subItems.push({ description: 'Tree', event: () => func(CollectionViewType.Tree), icon: 'tree' });
+ subItems.push({ description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._autoHeight = true), icon: 'ellipsis-v' });
+ subItems.push({ description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._autoHeight = true), icon: 'ellipsis-v' });
+ subItems.push({ description: 'Multicolumn', event: () => func(CollectionViewType.Multicolumn), icon: 'columns' });
+ subItems.push({ description: 'Multirow', event: () => func(CollectionViewType.Multirow), icon: 'columns' });
+ subItems.push({ description: 'Masonry', event: () => func(CollectionViewType.Masonry), icon: 'columns' });
+ subItems.push({ description: 'Carousel', event: () => func(CollectionViewType.Carousel), icon: 'columns' });
+ subItems.push({ description: '3D Carousel', event: () => func(CollectionViewType.Carousel3D), icon: 'columns' });
+ !Doc.noviceMode && subItems.push({ description: 'Pivot/Time', event: () => func(CollectionViewType.Time), icon: 'columns' });
+ !Doc.noviceMode && subItems.push({ description: 'Map', event: () => func(CollectionViewType.Map), icon: 'globe-americas' });
+ subItems.push({ description: 'Grid', event: () => func(CollectionViewType.Grid), icon: 'th-list' });
if (!Doc.IsSystem(this.rootDoc) && !this.rootDoc.isGroup && !this.rootDoc.annotationOn) {
const existingVm = ContextMenu.Instance.findByDescription(category);
- const catItems = existingVm && "subitems" in existingVm ? existingVm.subitems : [];
- catItems.push({ description: "Add a Perspective...", addDivider: true, noexpand: true, subitems: subItems, icon: "eye" });
- !existingVm && ContextMenu.Instance.addItem({ description: category, subitems: catItems, icon: "eye" });
+ const catItems = existingVm && 'subitems' in existingVm ? existingVm.subitems : [];
+ catItems.push({ description: 'Add a Perspective...', addDivider: true, noexpand: true, subitems: subItems, icon: 'eye' });
+ !existingVm && ContextMenu.Instance.addItem({ description: category, subitems: catItems, icon: 'eye' });
}
}
onContextMenu = (e: React.MouseEvent): void => {
const cm = ContextMenu.Instance;
- if (cm && !e.isPropagationStopped() && this.rootDoc[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
- this.setupViewTypes("UI Controls...", vtype => {
- const newRendition = Doc.MakeAlias(this.rootDoc);
- newRendition._viewType = vtype;
- this.props.addDocTab(newRendition, "add:right");
- return newRendition;
- }, false);
+ if (cm && !e.isPropagationStopped() && this.rootDoc[Id] !== Doc.MainDocId) {
+ // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+ this.setupViewTypes(
+ 'UI Controls...',
+ vtype => {
+ const newRendition = Doc.MakeAlias(this.rootDoc);
+ newRendition._viewType = vtype;
+ this.props.addDocTab(newRendition, 'add:right');
+ return newRendition;
+ },
+ false
+ );
- const options = cm.findByDescription("Options...");
- const optionItems = options && "subitems" in options ? options.subitems : [];
- !Doc.UserDoc().noviceMode ? optionItems.splice(0, 0, { description: `${this.rootDoc.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.rootDoc.forceActive = !this.rootDoc.forceActive, icon: "project-diagram" }) : null;
+ const options = cm.findByDescription('Options...');
+ const optionItems = options && 'subitems' in options ? options.subitems : [];
+ !Doc.noviceMode ? optionItems.splice(0, 0, { description: `${this.rootDoc.forceActive ? 'Select' : 'Force'} Contents Active`, event: () => (this.rootDoc.forceActive = !this.rootDoc.forceActive), icon: 'project-diagram' }) : null;
if (this.rootDoc.childLayout instanceof Doc) {
- optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.rootDoc.childLayout as Doc, "add:right"), icon: "project-diagram" });
+ optionItems.push({ description: 'View Child Layout', event: () => this.props.addDocTab(this.rootDoc.childLayout as Doc, 'add:right'), icon: 'project-diagram' });
}
if (this.rootDoc.childClickedOpenTemplateView instanceof Doc) {
- optionItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.rootDoc.childClickedOpenTemplateView as Doc, "add:right"), icon: "project-diagram" });
+ optionItems.push({ description: 'View Child Detailed Layout', event: () => this.props.addDocTab(this.rootDoc.childClickedOpenTemplateView as Doc, 'add:right'), icon: 'project-diagram' });
}
- !Doc.UserDoc().noviceMode && optionItems.push({ description: `${this.rootDoc.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.rootDoc.isInPlaceContainer = !this.rootDoc.isInPlaceContainer, icon: "project-diagram" });
+ !Doc.noviceMode && optionItems.push({ description: `${this.rootDoc.isInPlaceContainer ? 'Unset' : 'Set'} inPlace Container`, event: () => (this.rootDoc.isInPlaceContainer = !this.rootDoc.isInPlaceContainer), icon: 'project-diagram' });
- if (!Doc.UserDoc().noviceMode) {
+ if (!Doc.noviceMode) {
optionItems.push({
- description: "Create Branch", event: async () => this.props.addDocTab(await BranchCreate(this.rootDoc), "add:right"), icon: "project-diagram"
+ description: 'Create Branch',
+ event: async () => this.props.addDocTab(await BranchCreate(this.rootDoc), 'add:right'),
+ icon: 'project-diagram',
});
optionItems.push({
- description: "Pull Master", event: () => BranchTask(this.rootDoc, "pull"), icon: "project-diagram"
+ description: 'Pull Master',
+ event: () => BranchTask(this.rootDoc, 'pull'),
+ icon: 'project-diagram',
});
optionItems.push({
- description: "Merge Branches", event: () => BranchTask(this.rootDoc, "merge"), icon: "project-diagram"
+ description: 'Merge Branches',
+ event: () => BranchTask(this.rootDoc, 'merge'),
+ icon: 'project-diagram',
});
}
if (this.Document._viewType === CollectionViewType.Docking) {
- optionItems.push({ description: "Create Dashboard", event: () => CurrentUserUtils.createNewDashboard(Doc.UserDoc()), icon: "project-diagram" });
+ optionItems.push({ description: 'Create Dashboard', event: () => DashboardView.createNewDashboard(), icon: 'project-diagram' });
}
- !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "hand-point-right" });
+ !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'hand-point-right' });
- if (!Doc.UserDoc().noviceMode && !this.rootDoc.annotationOn) {
- const existingOnClick = cm.findByDescription("OnClick...");
- const onClicks = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
- const funcs = [{ key: "onChildClick", name: "On Child Clicked" }, { key: "onChildDoubleClick", name: "On Child Double Clicked" }];
- funcs.map(func => onClicks.push({
- description: `Edit ${func.name} script`, icon: "edit", event: (obj: any) => {
- const alias = Doc.MakeAlias(this.rootDoc);
- DocUtils.makeCustomViewClicked(alias, undefined, func.key);
- this.props.addDocTab(alias, "add:right");
- }
- }));
- DocListCast(Cast(Doc.UserDoc()["clickFuncs-child"], Doc, null).data).forEach(childClick =>
+ if (!Doc.noviceMode && !this.rootDoc.annotationOn) {
+ const existingOnClick = cm.findByDescription('OnClick...');
+ const onClicks = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
+ const funcs = [
+ { key: 'onChildClick', name: 'On Child Clicked' },
+ { key: 'onChildDoubleClick', name: 'On Child Double Clicked' },
+ ];
+ funcs.map(func =>
+ onClicks.push({
+ description: `Edit ${func.name} script`,
+ icon: 'edit',
+ event: (obj: any) => {
+ const alias = Doc.MakeAlias(this.rootDoc);
+ DocUtils.makeCustomViewClicked(alias, undefined, func.key);
+ this.props.addDocTab(alias, 'add:right');
+ },
+ })
+ );
+ DocListCast(Cast(Doc.UserDoc()['clickFuncs-child'], Doc, null)?.data).forEach(childClick =>
onClicks.push({
description: `Set child ${childClick.title}`,
- icon: "edit",
- event: () => Doc.GetProto(this.rootDoc)[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)),
- }));
- !Doc.IsSystem(this.rootDoc) && !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
+ icon: 'edit',
+ event: () => (Doc.GetProto(this.rootDoc)[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data))),
+ })
+ );
+ !Doc.IsSystem(this.rootDoc) && !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' });
}
- if (!Doc.UserDoc().noviceMode) {
- const more = cm.findByDescription("More...");
- const moreItems = more && "subitems" in more ? more.subitems : [];
- moreItems.push({ description: "Export Image Hierarchy", icon: "columns", event: () => ImageUtils.ExportHierarchyToFileSystem(this.rootDoc) });
- !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
+ if (!Doc.noviceMode) {
+ const more = cm.findByDescription('More...');
+ const moreItems = more && 'subitems' in more ? more.subitems : [];
+ moreItems.push({ description: 'Export Image Hierarchy', icon: 'columns', event: () => ImageUtils.ExportHierarchyToFileSystem(this.rootDoc) });
+ !more && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'hand-point-right' });
}
}
- }
+ };
bodyPanelWidth = () => this.props.PanelWidth();
+ childHideResizeHandles = () => this.props.childHideResizeHandles?.() ?? BoolCast(this.Document.childHideResizeHandles);
+ childHideDecorationTitle = () => this.props.childHideDecorationTitle?.() ?? BoolCast(this.Document.childHideDecorationTitle);
childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.rootDoc.childLayoutTemplate, Doc, null);
- @computed get childLayoutString() { return StrCast(this.rootDoc.childLayoutString); }
-
- isContentActive = (outsideReaction?: boolean) => {
- return this.props.isContentActive();
+ @computed get childLayoutString() {
+ return StrCast(this.rootDoc.childLayoutString);
}
+
+ isContentActive = (outsideReaction?: boolean) => this.props.isContentActive();
+
render() {
TraceMobx();
const props: SubCollectionViewProps = {
@@ -263,12 +273,15 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
ScreenToLocalTransform: this.screenToLocalTransform,
childLayoutTemplate: this.childLayoutTemplate,
childLayoutString: this.childLayoutString,
+ childHideResizeHandles: this.childHideResizeHandles,
+ childHideDecorationTitle: this.childHideDecorationTitle,
CollectionView: this,
};
- return (<div className={"collectionView"} onContextMenu={this.onContextMenu}
- style={{ pointerEvents: this.props.layerProvider?.(this.rootDoc) === false ? "none" : undefined }}>
- {this.showIsTagged()}
- {this.renderSubView(this.collectionViewType, props)}
- </div>);
+ return (
+ <div className={'collectionView'} onContextMenu={this.onContextMenu} style={{ pointerEvents: this.props.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform && this.rootDoc._lockedPosition ? 'none' : undefined }}>
+ {this.showIsTagged()}
+ {this.renderSubView(this.collectionViewType, props)}
+ </div>
+ );
}
}