1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import React from 'react';
import { Doc, StrListCast } from '../../../fields/Doc';
import { StrCast } from '../../../fields/Types';
import { AudioAnnoState } from '../../../server/SharedMediaTypes';
import { undoable } from '../../util/UndoManager';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { TagItem } from '../TagsView';
import { DocumentView } from './DocumentView';
import './IconTagBox.scss';
import { Size, Toggle, ToggleType, Type } from '@dash/components';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { StyleProp } from '../StyleProp';
export interface IconTagProps {
Views: DocumentView[];
IsEditing: boolean | undefined;
}
/**
* Renders the icon tags that rest under the document. The icons rendered are determined by the values of
* each icon in the userdoc.
*/
@observer
export class IconTagBox extends ObservableReactComponent<IconTagProps> {
constructor(props: IconTagProps) {
super(props);
makeObservable(this);
}
@computed get View() { return this._props.Views.lastElement(); } // prettier-ignore
@computed get currentScale() { return this.View?.screenToLocalScale(); } // prettier-ignore
/**
* Sets or removes the specified tag
* @param tag tag name (should begin with '#')
* @param state flag to add or remove the metadata
*/
setIconTag = undoable((tag: string, state: boolean) => {
this._props.Views.forEach(view => {
state && TagItem.addTagToDoc(view.dataDoc, tag);
!state && TagItem.removeTagFromDoc(view.dataDoc, tag);
});
}, 'toggle card tag');
/**
* Returns a renderable version of the button Doc that is colorized to indicate
* whether the doc has the associated tag set on it or not.
* @param doc doc to test
* @param key metadata icon button
* @returns an icon for the metdata button
*/
getButtonIcon = (dv: DocumentView, key: Doc): JSX.Element => {
const icon = StrCast(key.icon) as IconProp;
const tag = StrCast(key.toolType);
const color = dv._props.styleProvider?.(dv.layoutDoc, dv.ComponentView?._props, StyleProp.FontColor) as string;
return (
<div>
{' '}
{/* tooltips require the wrapped item to be an element ref */}
<Toggle
tooltip={`Click to add/remove the tag ${tag}`}
toggleStatus={TagItem.docHasTag(dv.Document, tag)}
toggleType={ToggleType.BUTTON}
icon={<FontAwesomeIcon className={`fontIconBox-icon-${ToggleType.BUTTON}`} icon={icon} color={color} />}
size={Size.XSMALL}
type={Type.PRIM}
onClick={() => this.setIconTag(tag, !TagItem.docHasTag(this.View.Document, tag))}
color={color}
/>
</div>
);
};
/**
* Displays a button to play audio annotations on the document.
* NOTE: This should be generalized -- audio should
* @returns
*/
renderAudioButtons = (dv: DocumentView, anno: string) => {
const fcolor = dv._props.styleProvider?.(dv.layoutDoc, dv.ComponentView?._props, StyleProp.FontColor) as string;
const audioIconColors: { [key: string]: string } = { playing: 'green', stopped: fcolor ?? 'blue', recording: 'red' };
const audioAnnoState = (audioDoc: Doc) => StrCast(audioDoc.audioAnnoState, AudioAnnoState.stopped);
const color = audioIconColors[audioAnnoState(this.View.Document)];
return (
<Toggle
tooltip={`click to play:${anno}`}
toggleStatus={true}
toggleType={ToggleType.BUTTON}
icon={<FontAwesomeIcon className={`fontIconBox-icon-${ToggleType.BUTTON}`} icon="file-audio" color={color} />}
size={Size.XSMALL}
type={Type.PRIM}
onClick={() => this.View?.playAnnotation()}
color={color}
/>
);
};
/**
* Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups
*/
render() {
const buttons = Doc.MyFilterHotKeys
.map(key => ({ key, tag: StrCast(key.toolType) }))
.filter(({ tag }) => this._props.IsEditing || TagItem.docHasTag(this.View.Document, tag) || (DocumentView.Selected().length === 1 && this.View.IsSelected))
.map(({ key, tag }) => (
<Tooltip key={tag} title={<div className="dash-tooltip">Click to add/remove the {tag} tag</div>}>
{this.getButtonIcon(this.View, key)}
</Tooltip>
)); // prettier-ignore
const audioannos = StrListCast(this.View.Document[Doc.LayoutDataKey(this.View.Document) + '_audioAnnotations_text']);
return !buttons.length && !audioannos.length ? null : (
<div className="card-button-container" style={{ fontSize: '50px' }}>
{audioannos.length ? this.renderAudioButtons(this.View, audioannos.lastElement()) : null}
{buttons}
</div>
);
}
}
|