aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionCardDeckView.tsx2
-rw-r--r--src/client/views/collections/CollectionCarouselView.scss66
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx244
-rw-r--r--src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx4
5 files changed, 257 insertions, 61 deletions
diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx
index 28a769896..37b1adeff 100644
--- a/src/client/views/collections/CollectionCardDeckView.tsx
+++ b/src/client/views/collections/CollectionCardDeckView.tsx
@@ -373,7 +373,7 @@ export class CollectionCardView extends CollectionSubView() {
const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
try {
const hrefBase64 = await CollectionCardView.imageUrlToBase64(hrefComplete);
- const response = await gptImageLabel(hrefBase64);
+ const response = await gptImageLabel(hrefBase64, 'Give three to five labels to describe this image.');
image[DocData].description = response.trim();
return response; // Return the response from gptImageLabel
} catch (error) {
diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss
index f115bb40a..b402a7a32 100644
--- a/src/client/views/collections/CollectionCarouselView.scss
+++ b/src/client/views/collections/CollectionCarouselView.scss
@@ -1,5 +1,7 @@
.collectionCarouselView-outer {
height: 100%;
+ position: relative;
+ overflow: hidden;
.collectionCarouselView-caption {
height: 50;
display: inline-block;
@@ -11,17 +13,26 @@
width: 100%;
user-select: none;
}
+ .message {
+ justify-content: center;
+ align-items: center;
+ display: flex;
+ height: 60%;
+ z-index: -1;
+ // margin: 15px;
+ }
}
+
.carouselView-back,
.carouselView-fwd,
.carouselView-star,
.carouselView-remove,
-.carouselView-check {
+.carouselView-check,
+.carouselView-add {
position: absolute;
display: flex;
- top: 42.5%;
width: 30;
- height: 15%;
+ height: 30;
align-items: center;
border-radius: 5px;
justify-content: center;
@@ -32,14 +43,21 @@
}
}
.carouselView-fwd {
+ top: 42.5%;
right: 20;
}
.carouselView-back {
+ top: 42.5%;
left: 20;
}
.carouselView-star {
top: 0;
- right: 20;
+ left: 0;
+}
+.carouselView-add {
+ position: absolute;
+ bottom: 0;
+ left: 0;
}
.carouselView-remove {
top: 80%;
@@ -49,6 +67,46 @@
top: 80%;
right: 52%;
}
+.carouselView-quiz {
+ position: absolute;
+ display: flex;
+ top: 5px;
+ right: 8px;
+ &:hover {
+ color: white;
+ }
+}
+
+.carouselView-practice {
+ position: absolute;
+ display: flex;
+ top: 22px;
+ right: 8px;
+ &:hover {
+ color: white;
+ }
+}
+.carouselView-starFilter {
+ position: absolute;
+ display: flex;
+ top: 40px;
+ right: 7px;
+ &:hover {
+ color: white;
+ }
+}
+
+.carouselView-menu {
+ position: absolute;
+ display: flex;
+ top: 2px;
+ right: 2px;
+ width: 30;
+ height: 60;
+ border-radius: 5px;
+ color: rgba(255, 255, 255, 0.5);
+ background: rgba(0, 0, 0, 0.1);
+}
.carouselView-back:hover,
.carouselView-fwd:hover {
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 4bec2d963..9f59322e8 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -1,6 +1,7 @@
/* eslint-disable react/jsx-props-no-spreading */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { computed, makeObservable } from 'mobx';
+import { Tooltip } from '@mui/material';
+import { action, computed, makeObservable, observable, trace } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { StopEvent, returnFalse, returnOne, returnTrue, returnZero } from '../../../ClientUtils';
@@ -8,8 +9,8 @@ import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
+import { Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
-import { ContextMenu } from '../ContextMenu';
import { StyleProp } from '../StyleProp';
import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
@@ -18,9 +19,15 @@ import './CollectionCarouselView.scss';
import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
enum cardMode {
- PRACTICE = 'practice',
+ // PRACTICE = 'practice',
STAR = 'star',
+ // QUIZ = 'quiz',
+ ALL = 'all',
+}
+enum practiceMode {
+ PRACTICE = 'practice',
QUIZ = 'quiz',
+ NORMAL = 'normal',
}
enum practiceVal {
MISSED = 'missed',
@@ -29,12 +36,22 @@ enum practiceVal {
@observer
export class CollectionCarouselView extends CollectionSubView() {
private _dropDisposer?: DragManager.DragDropDisposer;
+ @observable private _practiceMessage: string | undefined;
+ @observable private _filterMessage: string | undefined;
get practiceField() { return this.fieldKey + "_practice"; } // prettier-ignore
- get starField() { return this.fieldKey + "_star"; } // prettier-ignore
+ get sideField() { return "_" + this.fieldKey + "_usePath"; } // prettier-ignore
+ get starField() { return "star"; } // prettier-ignore
constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
+ // this.setModes();
+ this.layoutDoc.filterOp = cardMode.ALL;
+ Doc.setDocFilter(this.Document, 'star', undefined, 'match');
+ this.layoutDoc.practiceMode = practiceMode.NORMAL;
+ this.layoutDoc._carousel_index = 0;
+ this.carouselItems.forEach(item => { item.layout[this.practiceField] = undefined}); //prettier-ignore
+ console.log(this.carouselItems.length);
}
componentWillUnmount() {
@@ -49,16 +66,33 @@ export class CollectionCarouselView extends CollectionSubView() {
};
@computed get carouselItems() {
+ this.childLayoutPairs.map(pair => {
+ pair.layout.embedContainer = this.Document;
+ });
return this.childLayoutPairs.filter(pair => pair.layout.type !== DocumentType.LINK);
}
@computed get marginX() {
return NumCast(this.layoutDoc.caption_xMargin, 50);
}
+ @action setPracticeMessage = (mes: string | undefined) => {
+ this._practiceMessage = mes;
+ };
+ @action setFilterMessage = (mes: string | undefined) => {
+ this._filterMessage = mes;
+ };
+
+ setModes = () => {
+ this.layoutDoc.filterOp = cardMode.ALL;
+ Doc.setDocFilter(this.Document, 'data_star', undefined, 'match');
+ this.layoutDoc.practiceMode = practiceMode.NORMAL;
+ this.layoutDoc._carousel_index = 0;
+ };
+
move = (dir: number) => {
const moveToCardWithField = (match: (doc: Doc) => boolean): boolean => {
let startInd = (NumCast(this.layoutDoc._carousel_index) + dir) % this.carouselItems.length;
- while (!match(this.carouselItems?.[startInd].layout) && (startInd + dir + this.carouselItems.length) % this.carouselItems.length !== this.layoutDoc._carousel_index) {
+ while (!match(this.carouselItems?.[startInd].layout) && (startInd + this.carouselItems.length) % this.carouselItems.length !== this.layoutDoc._carousel_index) {
startInd = (startInd + dir + this.carouselItems.length) % this.carouselItems.length;
}
if (match(this.carouselItems?.[startInd].layout)) {
@@ -67,23 +101,28 @@ export class CollectionCarouselView extends CollectionSubView() {
}
return match(this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout);
};
- switch (StrCast(this.layoutDoc.filterOp)) {
- case cardMode.STAR: // go to a flashcard that is starred, skip the ones that aren't
+
+ switch (this.layoutDoc.practiceMode && this.layoutDoc.filterOp) {
+ case practiceMode.PRACTICE && cardMode.ALL:
+ if (!moveToCardWithField((doc: Doc) => doc[this.practiceField] !== practiceVal.CORRECT)) {
+ this._practiceMessage = 'Finished! Unselect practice mode to view all flashcards.';
+ this.carouselItems.forEach(item => { item.layout[this.practiceField] = undefined}); //prettier-ignore
+ }
+ break;
+ case !practiceMode.PRACTICE && cardMode.STAR:
if (!moveToCardWithField((doc: Doc) => !!doc[this.starField])) {
- this.layoutDoc.filterOp = undefined; // if there aren't any starred, show all cards
+ this._filterMessage = 'No starred items. Unselect this view to see all flashcards and star them.';
}
break;
- case cardMode.PRACTICE: // go to a new index that is missed, skip the ones that are correct
- if (!moveToCardWithField((doc: Doc) => doc[this.practiceField] !== practiceVal.CORRECT)) {
- this.layoutDoc.filterOp = undefined; // if all of the cards are correct, show all cards and exit practice mode
-
- this.carouselItems.forEach(item => { // reset all the practice values
- item.layout[this.practiceField] = undefined;
- });
+ case practiceMode.PRACTICE && cardMode.STAR:
+ if (!moveToCardWithField((doc: Doc) => doc[this.practiceField] !== practiceVal.CORRECT && doc[this.starField] === true)) {
+ this._filterMessage = 'No flashcards to show! Unselect mode to view all flashcards.';
+ this._practiceMessage = undefined;
}
break;
- default: moveToCardWithField(returnTrue);
- } // prettier-ignore
+ default:
+ moveToCardWithField(returnTrue);
+ }
};
/**
@@ -109,6 +148,8 @@ export class CollectionCarouselView extends CollectionSubView() {
e.stopPropagation();
const curDoc = this.carouselItems[NumCast(this.layoutDoc._carousel_index)];
curDoc.layout[this.starField] = curDoc.layout[this.starField] ? undefined : true;
+ // if (!curDoc.layout[this.starField]) this.move(1);
+ // this.layoutDoc._carousel_index = undefined;
};
/*
@@ -130,35 +171,59 @@ export class CollectionCarouselView extends CollectionSubView() {
onContentDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
onContentClick = () => ScriptCast(this.layoutDoc.onChildClick);
captionWidth = () => this._props.PanelWidth() - 2 * this.marginX;
- specificMenu = (): void => {
- const cm = ContextMenu.Instance;
-
- const revealOptions = cm.findByDescription('Filter Flashcards');
- const revealItems = revealOptions?.subitems ?? [];
- revealItems.push({description: 'All', event: () => {this.layoutDoc.filterOp = undefined;}, icon: 'layer-group',}); // prettier-ignore
- revealItems.push({description: 'Star', event: () => {this.layoutDoc.filterOp = cardMode.STAR;}, icon: 'star',}); // prettier-ignore
- revealItems.push({description: 'Practice Mode', event: () => {this.layoutDoc.filterOp = cardMode.PRACTICE;}, icon: 'check',}); // prettier-ignore
- revealItems.push({description: 'Quiz Cards', event: () => {this.layoutDoc.filterOp = cardMode.QUIZ;}, icon: 'pencil',}); // prettier-ignore
- !revealOptions && cm.addItem({ description: 'Filter Flashcards', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' });
+
+ setPracticeMode = (mode: practiceMode) => {
+ this.layoutDoc.practiceMode = mode;
+ this.carouselItems?.map(doc => (doc.layout[this.practiceField] = undefined));
+ switch (mode) {
+ case practiceMode.QUIZ:
+ this.carouselItems?.map(doc => (doc.layout[this.sideField] = undefined));
+ break;
+ case practiceMode.NORMAL:
+ this.setPracticeMessage(undefined);
+ break;
+ }
};
+
+ setFilterMode = (mode: cardMode) => {
+ this.layoutDoc.filterOp = mode;
+ switch (mode) {
+ case cardMode.STAR:
+ // Doc.setDocFilter(this.Document, 'data_star', true, 'match');
+ this.move(1);
+ break;
+ default:
+ this.setFilterMessage(undefined); // prettier-ignore
+ // Doc.setDocFilter(this.Document, 'data_star', true, 'remove');
+ }
+ };
+
@computed get content() {
+ trace();
+ if (this.layoutDoc._carousel_index === this.carouselItems.length && this.layoutDoc._carousel_index !== 0) {
+ this.move(1);
+ }
const index = NumCast(this.layoutDoc._carousel_index);
const curDoc = this.carouselItems?.[index];
const captionProps = { ...this._props, NativeScaling: returnOne, PanelWidth: this.captionWidth, fieldKey: 'caption', setHeight: undefined, setContentView: undefined };
const carouselShowsCaptions = StrCast(this.layoutDoc._layout_showCaption);
+
return !(curDoc?.layout instanceof Doc) ? null : (
<>
- <div className="collectionCarouselView-image" key="image">
+ <div className="collectionCarouselView-image">
<DocumentView
{...this._props}
NativeWidth={returnZero}
NativeHeight={returnZero}
fitWidth={undefined}
setContentViewBox={undefined}
+ childFilters={this.childDocFilters}
+ containerViewPath={this._props.docViewPath}
onDoubleClickScript={this.onContentDoubleClick}
onClickScript={this.onContentClick}
isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive}
isContentActive={(this._props.childContentsActive ?? this._props.isContentActive() === false) ? returnFalse : emptyFunction}
+ addDocument={this._props.addDocument}
hideCaptions={!!carouselShowsCaptions} // hide captions if the carousel is configured to show the captions
renderDepth={this._props.renderDepth + 1}
LayoutTemplate={this._props.childLayoutTemplate}
@@ -185,6 +250,25 @@ export class CollectionCarouselView extends CollectionSubView() {
</>
);
}
+
+ containsDifTypes = (): boolean => {
+ return this.carouselItems.filter(doc => !doc.layout._layout_isFlashcard).length !== 0;
+ };
+
+ addFlashcard() {
+ const newDoc = Docs.Create.ComparisonDocument('', { _layout_isFlashcard: true, _width: 300, _height: 300 });
+ this.addDocument?.(newDoc);
+ // DocUtils.copyDragFactory(newDoc);
+ // this._props.addDocument?.();
+ // newDoc.layout = this.layoutDoc;
+ // newDoc.data = this.dataDoc;
+ // Doc.AddDocToList()
+ // this._props.parent._props.addDocument();
+ // this.childLayoutPairs.push({ newDoc.layout, newDoc.data});
+ // this._props.addDocument?.(newDoc);
+ // console.log('HERE');
+ }
+
@computed get buttons() {
if (!this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)]) return null;
return (
@@ -195,54 +279,108 @@ export class CollectionCarouselView extends CollectionSubView() {
<div key="fwd" className="carouselView-fwd" onClick={this.advance}>
<FontAwesomeIcon icon="chevron-right" size="2x" />
</div>
- <div key="star" className="carouselView-star" onClick={this.star}>
- <FontAwesomeIcon icon="star" color={this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.starField] ? 'yellow' : 'gray'} size="1x" />
- </div>
- <div key="remove" className="carouselView-remove" onClick={e => this.setPracticeVal(e, practiceVal.MISSED)} style={{ visibility: this.layoutDoc.filterOp === cardMode.PRACTICE ? 'visible' : 'hidden' }}>
- <FontAwesomeIcon icon="xmark" color="red" size="1x" />
- </div>
- <div key="check" className="carouselView-check" onClick={e => this.setPracticeVal(e, practiceVal.CORRECT)} style={{ visibility: this.layoutDoc.filterOp === cardMode.PRACTICE ? 'visible' : 'hidden' }}>
- <FontAwesomeIcon icon="check" color="green" size="1x" />
- </div>
+ {!this.containsDifTypes() ? (
+ <div>
+ <Tooltip title="star">
+ <div key="star" className="carouselView-star" onClick={this.star}>
+ <FontAwesomeIcon icon="star" color={this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.starField] ? 'yellow' : 'gray'} size="1x" />
+ </div>
+ </Tooltip>
+ {/* <Tooltip title="add new flashcard to pile">
+ <div key="add" className="carouselView-add" onClick={this.addFlashcard}>
+ <FontAwesomeIcon icon="plus" color={this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.starField] ? 'yellow' : 'gray'} size="1x" />
+ </div>
+ </Tooltip> */}
+ </div>
+ ) : null}
+ {this.layoutDoc.practiceMode === practiceMode.PRACTICE ? (
+ <div>
+ <Tooltip title="Incorrect. View again later.">
+ <div key="remove" className="carouselView-remove" onClick={e => this.setPracticeVal(e, practiceVal.MISSED)}>
+ <FontAwesomeIcon icon="xmark" color="red" size="1x" />
+ </div>
+ </Tooltip>
+ <Tooltip title="Correct">
+ <div key="check" className="carouselView-check" onClick={e => this.setPracticeVal(e, practiceVal.CORRECT)}>
+ <FontAwesomeIcon icon="check" color="green" size="1x" />
+ </div>
+ </Tooltip>
+ </div>
+ ) : null}
</>
);
}
+ togglePracticeMode = (mode: practiceMode) => {
+ if (mode === this.layoutDoc.practiceMode) {
+ this.setPracticeMode(practiceMode.NORMAL);
+ // this.setPracticeMessage("undefined");
+ } else this.setPracticeMode(mode);
+ };
+ toggleFilterMode = () => { this.layoutDoc.filterOp === cardMode.STAR ? this.setFilterMode(cardMode.ALL) : this.setFilterMode(cardMode.STAR)}; //prettier-ignore
+ setColor = (mode: practiceMode | cardMode, which: string) => { return which === mode ? 'white' : 'light gray'}; //prettier-ignore
+
+ @computed get menu() {
+ return (
+ <div className="carouselView-menu">
+ <Tooltip title="Practice flashcards using GPT">
+ <div key="back" className="carouselView-quiz" onClick={e => this.togglePracticeMode(practiceMode.QUIZ)}>
+ <FontAwesomeIcon icon="file-pen" color={this.setColor(practiceMode.QUIZ, StrCast(this.layoutDoc.practiceMode))} size="1x" />
+ </div>
+ </Tooltip>
+ <Tooltip title={this.layoutDoc.practiceMode === practiceMode.PRACTICE ? 'Exit practice mode' : 'Practice flashcards manually'}>
+ <div key="back" className="carouselView-practice" onClick={e => this.togglePracticeMode(practiceMode.PRACTICE)}>
+ <FontAwesomeIcon icon="check" color={this.setColor(practiceMode.PRACTICE, StrCast(this.layoutDoc.practiceMode))} size="1x" />
+ </div>
+ </Tooltip>
+ <Tooltip title={this.layoutDoc.filterOp === cardMode.STAR ? 'Show all cards' : 'Show only starred cards'}>
+ <div key="back" className="carouselView-starFilter" onClick={e => this.toggleFilterMode()}>
+ <FontAwesomeIcon icon="filter" color={this.setColor(cardMode.STAR, StrCast(this.layoutDoc.filterOp))} size="1x" />
+ </div>
+ </Tooltip>
+ </div>
+ );
+ }
+
render() {
return (
<div
className="collectionCarouselView-outer"
ref={this.createDashEventsTarget}
- onContextMenu={this.specificMenu}
style={{
background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string,
color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string,
}}>
- {this.content}
- {/* Displays a message to the user to add more flashcards if they are in practice mode and no flashcards are there. */}
- <p
- style={{
- display: !this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)] && this.layoutDoc.filterOp === cardMode.PRACTICE ? 'flex' : 'none',
- justifyContent: 'center',
- alignItems: 'center',
- height: '100%',
- zIndex: '-1',
- }}>
- Add flashcards!
- </p>
- {/* Displays a message to the user that a flashcard was recently missed if they had previously gotten it wrong. */}
+ {!this._practiceMessage && !this._filterMessage ? (
+ this.content
+ ) : (
+ <p className="message">
+ {this._filterMessage}
+ {'\n'}
+ {this._practiceMessage}
+ </p>
+ )}
+ {!this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)] && this.layoutDoc.practiceMode === practiceMode.PRACTICE ? <p className="message">Add flashcards </p> : null}
<p
+ className="missed-message"
style={{
color: 'red',
+ fontWeight: 'bold',
zIndex: '999',
position: 'relative',
left: '10px',
top: '10px',
- display: this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)] ? (this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.practiceField] === practiceVal.MISSED ? 'block' : 'none') : 'none',
+ width: '10px',
+ display: this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)]
+ ? this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.practiceField] === practiceVal.MISSED && this.layoutDoc.practiceMode === practiceMode.PRACTICE && !this._practiceMessage
+ ? 'block'
+ : 'none'
+ : 'none',
}}>
Recently missed!
</p>
- {this.Document._chromeHidden ? null : this.buttons}
+ {!this.containsDifTypes() && this.carouselItems.length !== 0 ? this.menu : null}
+ {this.Document._chromeHidden || (!this._filterMessage && !this._practiceMessage) ? this.buttons : null}
</div>
);
}
diff --git a/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx b/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx
index e419e522c..94ec59ecb 100644
--- a/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx
+++ b/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx
@@ -167,7 +167,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
const [name, type] = ImageCast(doc[Doc.LayoutFieldKey(doc)]).url.href.split('.');
return CollectionCardView.imageUrlToBase64(`${name}_o.${type}`).then(hrefBase64 =>
!hrefBase64 ? undefined :
- gptImageLabel(hrefBase64).then(labels =>
+ gptImageLabel(hrefBase64,'Give three labels to describe this image.').then(labels =>
({ doc, labels }))) ; // prettier-ignore
}
});
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index ccb6bc9be..917aaaea8 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -433,14 +433,14 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
* Classifies images and assigns the labels as document fields.
*/
@undoBatch
- classifyImages = action(async () => {
+ classifyImages = async () => {
const groupButton = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MyImageGrouper);
if (groupButton) {
this._selectedDocs = this.marqueeSelect(false, DocumentType.IMG);
ImageLabelBoxData.Instance.setData(this._selectedDocs);
MainView.Instance.expandFlyout(groupButton);
}
- });
+ };
/**
* Groups images to most similar labels.