semantic-ui-react#Label TypeScript Examples
The following examples show how to use
semantic-ui-react#Label.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LobbyMeetingRoom.tsx From FLECT_Amazon_Chime_Meeting with Apache License 2.0 | 6 votes |
labelExampleCircular = () => (
<span>
{colors.map((color) => (
//@ts-ignore
<Label circular empty as="a" color={color} key={color} active={color===this.state.drawingStroke}
link onClick={()=>{
this.mainOverlayVideoRef.current!.setDrawingStroke(color);
this.mainOverlayVideoRef.current!.setErasing(false);
this.mainOverlayVideoRef.current!.setDrawingMode(true)
this.setState({
drawingStroke:color,
enableDrawing:true,
erasing:false,
})
}
} />
))}
</span>
)
Example #2
Source File: index.tsx From chartsy with GNU General Public License v3.0 | 6 votes |
Slider: React.FC<SliderProps> = ({ title, value, min, max, dispatch }) => {
return (
<div className="slider">
<div className="slider-info">
<p>{title}</p>
<Label horizontal>{value}</Label>
</div>
<input type="range" min={min} max={max} value={value} onChange={dispatch} />
</div>
);
}
Example #3
Source File: index.tsx From frontegg-react with MIT License | 6 votes |
InputChip = forwardRef<HTMLInputElement, IInputChip>(
({ chips, fullWidth, onDelete, className, ...inputProps }, ref) => {
const inputRef = useRef<HTMLInputElement>(null);
return (
<div
className={classNames('input-chip', className, { fluid: fullWidth })}
onClick={() => inputRef.current && inputRef.current.focus()}
>
{chips.map((chip, idx) => (
<Label as='div' key={idx} className='chip'>
{chip}
{!!onDelete && <Icon name='delete' onClick={() => onDelete(idx)} />}
</Label>
))}
<input {...inputProps} ref={ref} />
</div>
);
}
)
Example #4
Source File: index.tsx From frontegg-react with MIT License | 6 votes |
Tag: FC<TagProps> = (props) => {
const { children, onDelete, ...rest } = props;
return (
<Label {...mapper(rest)}>
{children}
{onDelete && <Icon name='delete' onClick={onDelete} />}
</Label>
);
}
Example #5
Source File: threshold_rewards.tsx From website with MIT License | 6 votes |
function ThresholdRewardsTab({eventData}) {
const {threshold_rewards} = eventData;
return (
<Table celled striped compact='very'>
<Table.Body>
{threshold_rewards.map(row => (
<Table.Row key={row.points}>
<Table.Cell>{row.points}</Table.Cell>
<Table.Cell>
{row.rewards.map(reward => (
<Label key={`reward_${reward.id}`} color="black">
<Image
src={getIconPath(reward.icon)}
size="small"
inline
spaced="right"
bordered
style={{
borderColor: getRarityColor(reward.rarity),
maxWidth: '27px',
maxHeight: '27px'
}}
alt={reward.full_name}
/>
{reward.full_name}
{reward.quantity > 1 ? ` x ${reward.quantity}` : ''}
</Label>
))}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
);
}
Example #6
Source File: ranked_rewards.tsx From website with MIT License | 6 votes |
function RankedRewardsTab({eventData}) {
const {ranked_brackets} = eventData;
return (
<Table celled striped compact='very'>
<Table.Body>
{ranked_brackets.map(row => (
<Table.Row key={`bracket_${row.first}_${row.last}`}>
<Table.Cell width={2}>{getBracketLabel(row)}</Table.Cell>
<Table.Cell width={14}>
{row.rewards.map(reward => (
<Label key={`reward_${reward.id}`} color="black">
<Image
src={getIconPath(reward.icon)}
size="small"
inline
spaced="right"
bordered
style={{
borderColor: getRarityColor(reward.rarity ?? 0),
maxWidth: '27px',
maxHeight: '27px'
}}
alt={reward.full_name}
/>
{reward.full_name}
{reward.quantity > 1 ? ` x ${reward.quantity}` : ''}
</Label>
))}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
);}
Example #7
Source File: commoncrewdata.tsx From website with MIT License | 6 votes |
render() {
const { title, value } = this.props;
return (
<Label size="large" style={{ marginBottom: '0.5em' }}>
{title}
<Label.Detail>{value}</Label.Detail>
</Label>
);
}
Example #8
Source File: OrgInfo.tsx From Riakuto-StartingReact-ja3.1 with Apache License 2.0 | 6 votes |
OrgInfo: VFC<{ org: Organization | null }> = ({ org = null }) =>
org ? (
<>
<Item.Group>
<Item>
<Item.Image src={org.avatarUrl} size="small" />
<Item.Content>
<Item.Header as="a">{org.name}</Item.Header>
<Item.Meta>{org.description}</Item.Meta>
<Item.Extra>
{org.location && (
<span>
<Icon name="map marker alternate" />
{org.location}
</span>
)}
{org.blog && (
<span>
<Icon name="globe" />
<a href={org.blog} target="_blank" rel="noopener noreferrer">
{org.blog}
</a>
</span>
)}
{org.isVerified && (
<Label basic color="teal">
verified
</Label>
)}
</Item.Extra>
</Item.Content>
</Item>
</Item.Group>
</>
) : (
<div />
)
Example #9
Source File: crewpage.tsx From website with MIT License | 5 votes |
renderEquipmentDetails(crew) {
if (!this.state.selectedEquipment) {
return <span />;
}
let es = crew.equipment_slots.find(es => es.symbol === this.state.selectedEquipment);
let equipment = this.state.items.find(item => item.symbol === es.symbol);
if (!equipment) {
console.error('Could not find equipment for slot', es);
return <span />;
}
if (!equipment.recipe) {
return (
<div>
<br />
<p>This item is not craftable, you can find it in these sources:</p>
<ItemSources item_sources={equipment.item_sources} />
</div>
);
}
return (
<div>
<Grid columns={4} centered padded>
{equipment.recipe.list.map(entry => {
let recipeEntry = this.state.items.find(item => item.symbol === entry.symbol);
return (
<Grid.Column key={recipeEntry.name + recipeEntry.rarity} textAlign='center'>
<Popup
trigger={
<Label as='a' style={{ background: CONFIG.RARITIES[recipeEntry.rarity].color }} image size='big'>
<img src={`${process.env.GATSBY_ASSETS_URL}${recipeEntry.imageUrl}`} />x{entry.count}
</Label>
}
header={CONFIG.RARITIES[recipeEntry.rarity].name + ' ' + recipeEntry.name}
content={<ItemSources item_sources={recipeEntry.item_sources} />}
wide
/>
</Grid.Column>
);
})}
</Grid>
</div>
);
}
Example #10
Source File: ColorfulBeads.tsx From Riakuto-StartingReact-ja3.1 with Apache License 2.0 | 5 votes |
ColorfulBeads: VFC<{ count?: number }> = ({ count = 0 }) => (
<Container className="beads-box">
{range(count).map((n: number) => (
<Label circular color={colors[n % colors.length]} key={n} />
))}
</Container>
)
Example #11
Source File: SettingsTab.tsx From watchparty with MIT License | 5 votes |
SettingRow = ({
icon,
name,
description,
checked,
disabled,
onChange,
content,
subOnly,
helpIcon,
}: {
icon: string;
name: string;
description?: React.ReactNode;
checked?: boolean;
disabled: boolean;
updateTS?: number;
onChange?: (e: React.FormEvent, data: CheckboxProps) => void;
content?: React.ReactNode;
subOnly?: boolean;
helpIcon?: React.ReactNode;
}) => {
return (
<React.Fragment>
<Divider inverted horizontal />
<div>
<div style={{ display: 'flex' }}>
<Icon size="large" name={icon as any} />
<div>
{name} {helpIcon}
{subOnly ? (
<Label size="mini" color="orange">
Subscriber only
</Label>
) : null}
</div>
{!content && (
<Radio
style={{ marginLeft: 'auto' }}
toggle
checked={checked}
disabled={disabled}
onChange={onChange}
/>
)}
</div>
<div className="smallText" style={{ marginBottom: '8px' }}>
{description}
</div>
{content}
</div>
</React.Fragment>
);
}
Example #12
Source File: SearchResult.tsx From watchparty with MIT License | 5 votes |
render() {
const result = this.props;
const setMedia = this.props.setMedia;
return (
<React.Fragment>
<Menu.Item
onClick={async (e) => {
this.props.launchMultiSelect([]);
let response = await window.fetch(
this.props.streamPath +
'/data?torrent=' +
encodeURIComponent(result.magnet!)
);
let metadata = await response.json();
// console.log(metadata);
if (
metadata.files.filter(
(file: any) => file.length > 10 * 1024 * 1024
).length > 1
) {
// Multiple large files, present user selection
const multiStreamSelection = metadata.files.map(
(file: any, i: number) => ({
...file,
url:
this.props.streamPath +
'/stream?torrent=' +
encodeURIComponent(result.magnet!) +
'&fileIndex=' +
i,
})
);
multiStreamSelection.sort((a: any, b: any) =>
a.name.localeCompare(b.name)
);
this.props.launchMultiSelect(multiStreamSelection);
} else {
this.props.launchMultiSelect(undefined);
setMedia(e, {
value:
this.props.streamPath +
'/stream?torrent=' +
encodeURIComponent(result.magnet!),
});
}
}}
>
<Label
circular
empty
color={Number(result.seeders) ? 'green' : 'red'}
/>
<Icon name="film" />
{result.name +
' - ' +
result.size +
' - ' +
result.seeders +
' peers'}
</Menu.Item>
</React.Fragment>
);
}
Example #13
Source File: event_information.tsx From website with MIT License | 4 votes |
function EventInformationTab({ eventData }) {
const { crewJson } = useStaticQuery(graphql`
query {
crewJson: allCrewJson {
edges {
node {
name
max_rarity
imageUrlPortrait
symbol
traits
traits_hidden
traits_named
base_skills {
security_skill {
core
}
command_skill {
core
}
diplomacy_skill {
core
}
engineering_skill {
core
}
medicine_skill {
core
}
science_skill {
core
}
}
}
}
}
}
`);
const crewData = crewJson.edges.map(edge => edge.node);
const crewMap = {};
crewData.forEach(crew => {
crewMap[crew.symbol] = crew;
})
const {
name,
description,
bonus_text,
content_types,
} = eventData;
const { bonus, featured } = getEventData(eventData, crewData);
const featuredCrewData = featured.map(symbol => {
const crew = crewMap[symbol];
return {
key: `crew_${crew.symbol}`,
name: crew.name,
image: getIconPath({file: crew.imageUrlPortrait}),
rarity: crew.max_rarity,
skills: Object.keys(crew.base_skills)
.filter(skill => !!crew.base_skills[skill])
.sort((a, b) => crew.base_skills[a].core > crew.base_skills[b].core ? -1 : 1)
.map(skill => ({
key: skill,
imageUrl: `${process.env.GATSBY_ASSETS_URL}atlas/icon_${skill}.png`
})),
traits: crew.traits_named,
};
});
const bonusCrew = crewData.filter(crew => bonus.includes(crew.symbol) && !featured.includes(crew.symbol));
return (
<>
<Card fluid raised>
<Card.Content>
<Card.Header>{name}</Card.Header>
<Card.Meta>{getEventType(content_types)}</Card.Meta>
<Card.Description>{description}</Card.Description>
</Card.Content>
<Card.Content extra>
<p>{bonus_text}</p>
</Card.Content>
</Card>
<Header as="h3">Featured Crew</Header>
<Card.Group>
{featuredCrewData.map(crew => (
<CrewCard key={crew.key} crew={crew} />
))}
</Card.Group>
<Header as="h3">Bonus Crew</Header>
{bonusCrew.length === 0 && (
<p>Bonus crew not yet determined for this event.</p>
)}
{sortCrew(bonusCrew).map(crew => (
<Label key={`crew_${crew.symbol}`} color="black" style={{ marginBottom: '5px' }}>
<Image
src={getIconPath({ file: crew.imageUrlPortrait })}
size="massive"
inline
spaced="right"
bordered
style={{
borderColor: getRarityColor(crew.max_rarity)
}}
alt={crew.name}
/>
{crew.name}
</Label>
))}
</>
);
}
Example #14
Source File: LobbyMeetingRoom.tsx From FLECT_Amazon_Chime_Meeting with Apache License 2.0 | 4 votes |
render(){
const props = this.props as any
const appState = props.appState as AppState
const gs = this.props as GlobalState
const thisAttendeeId = props.thisAttendeeId as string
const thisMeetingId = props.thisMeetingId as string
const attendeeInfo = appState.joinedMeetings[thisMeetingId].roster[thisAttendeeId]
let attendeeName = "no focused"
//let meetingShortId = thisMeetingId.substr(0,5)
const meetingName = gs.meetings.filter((x)=>{return x.meetingId === thisMeetingId})[0].meetingName
let muted = <div/>
if(attendeeInfo === undefined){
}else{
attendeeName = (attendeeInfo.name !== undefined && attendeeInfo.name !== null)? attendeeInfo.name!.substring(0,20) : "unknown"
muted = attendeeInfo.muted ? (<Icon name="mute" color="red" />) : (<Icon name="unmute"/>)
}
const focusedTileId = getTileId(thisAttendeeId, appState.joinedMeetings[thisMeetingId].videoTileStates)
if(focusedTileId > 0 && this.mainOverlayVideoRef.current !== null){
if(appState.joinedMeetings[thisMeetingId].videoTileStates[focusedTileId].localTile){
const videoElement = this.mainOverlayVideoRef.current.getVideoRef().current!
appState.joinedMeetings[thisMeetingId].meetingSession?.audioVideo.bindVideoElement(focusedTileId, videoElement)
videoElement.style.setProperty('-webkit-transform', 'scaleX(1)');
videoElement.style.setProperty('transform', 'scaleX(1)');
}else{
appState.joinedMeetings[thisMeetingId].meetingSession?.audioVideo.bindVideoElement(focusedTileId, this.mainOverlayVideoRef.current.getVideoRef().current!)
}
}else{
console.log("not focusedid", focusedTileId, this.mainOverlayVideoRef.current)
}
return(
<Grid>
<Grid.Row>
<Grid.Column>
<div>
<MainOverlayVideoElement {...props} ref={this.mainOverlayVideoRef}/>
</div>
<span>
{muted}
{attendeeName} @ {meetingName}
</span>
<span style={{paddingLeft:"10px"}}>
<Icon name="pencil" color={this.state.enableDrawing? "red":"grey"}
link onClick ={
()=>{
this.mainOverlayVideoRef.current!.setDrawingMode(!this.state.enableDrawing)
this.mainOverlayVideoRef.current!.setErasing(false)
this.setState({
enableDrawing:!this.state.enableDrawing,
erasing:false,
})
}
}
/>
{this.labelExampleCircular()}
<Icon name="eraser" color={this.state.erasing? "red":"grey"}
link onClick={
()=>{
this.mainOverlayVideoRef.current!.setErasing(true)
this.setState({
erasing:true,
enableDrawing:false
})
}
}
/>
<Icon name="file outline" link onClick={()=>{this.mainOverlayVideoRef.current!.clearDrawingCanvas()}} />
</span>
<span style={{paddingLeft:"10px"}}>
<Icon basic link name="long arrow alternate left" size="large"
onClick={() => {
props.setForegroundPosition(ForegroundPosition.BottomLeft)
}}
/>
<Icon basic link name="long arrow alternate right" size="large"
onClick={() => {
props.setForegroundPosition(ForegroundPosition.BottomRight)
}}
/>
<Icon basic link name="square outline" size="large"
onClick={() => {
props.setForegroundSize(ForegroundSize.Full)
}}
/>
<Icon basic link name="expand" size="large"
onClick={() => {
props.setForegroundSize(ForegroundSize.Large)
}}
/>
<Icon basic link name="compress" size="large"
onClick={() => {
props.setForegroundSize(ForegroundSize.Small)
}}
/>
</span>
<span style={{paddingLeft:"10px"}}>
<Label as="a" onClick={() => { props.setVirtualForeground(VirtualForegroundType.None) }} >
<Icon name="square outline" size="large"/>
None
</Label>
<Label as="a" onClick={() => { props.setVirtualForeground(VirtualForegroundType.Canny) }} >
<Icon name="chess board" size="large"/>
canny
</Label>
<Label as="a" onClick={() => { props.setVirtualForeground(VirtualForegroundType.Ascii) }} >
<Icon name="font" size="large"/>
ascii
</Label>
</span>
</Grid.Column>
</Grid.Row>
</Grid>
)
}
Example #15
Source File: profile.tsx From website with MIT License | 4 votes |
renderDesktop() {
const { playerData } = this.state;
const panes = [
{
menuItem: 'Crew',
render: () => <ProfileCrew playerData={this.state.playerData} />
},
{
menuItem: 'Crew (mobile)',
render: () => <ProfileCrewMobile playerData={this.state.playerData} isMobile={false} />
},
{
menuItem: 'Ships',
render: () => <ProfileShips playerData={this.state.playerData} />
},
{
menuItem: 'Items',
render: () => <ProfileItems playerData={this.state.playerData} />
},
{
menuItem: 'Other',
render: () => <ProfileOther playerData={this.state.playerData} />
},
{
menuItem: 'Charts & Stats',
render: () => <ProfileCharts playerData={this.state.playerData} />
}
];
return (
<Layout title={playerData.player.character.display_name}>
<Item.Group>
<Item>
<Item.Image
size='tiny'
src={`${process.env.GATSBY_ASSETS_URL}${playerData.player.character.crew_avatar
? playerData.player.character.crew_avatar.portrait
: 'crew_portraits_cm_empty_sm.png'
}`}
/>
<Item.Content>
<Item.Header>{playerData.player.character.display_name}</Item.Header>
<Item.Meta>
<Label>VIP {playerData.player.vip_level}</Label>
<Label>Level {playerData.player.character.level}</Label>
<Label>{playerData.calc.numImmortals} crew</Label>
<Label>{playerData.player.character.shuttle_bays} shuttles</Label>
</Item.Meta>
<Item.Description>
{playerData.player.fleet && (
<p>
Fleet{' '}
<Link to={`/fleet_info?fleetid=${playerData.player.fleet.id}`}>
<b>{playerData.player.fleet.slabel}</b>
</Link>{' '}
({playerData.player.fleet.rank}) Starbase level {playerData.player.fleet.nstarbase_level}{' '}
</p>
)}
</Item.Description>
</Item.Content>
</Item>
</Item.Group>
<Menu compact>
<Menu.Item>
{playerData.calc.lastModified ? <span>Last updated: {playerData.calc.lastModified.toLocaleString()}</span> : <span />}
</Menu.Item>
<Dropdown item text='Download'>
<Dropdown.Menu>
<Dropdown.Item onClick={() => this._exportExcel()}>Complete spreadsheet (XLSX)</Dropdown.Item>
<Dropdown.Item onClick={() => this._exportCrew()}>Crew table (CSV)</Dropdown.Item>
<Dropdown.Item onClick={() => this._exportShips()}>Ship table (CSV)</Dropdown.Item>
<Dropdown.Item onClick={() => this._exportItems()}>Item table (CSV)</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</Menu>
<Tab menu={{ secondary: true, pointing: true }} panes={panes} />
</Layout>
);
}
Example #16
Source File: fleet_info.tsx From website with MIT License | 4 votes |
render() {
const { fleet_id, errorMessage, fleet_data, factions, events } = this.state;
if (fleet_id === undefined || fleet_data === undefined || errorMessage !== undefined) {
return (
<Layout title='Fleet information'>
<Header as="h4">Fleet information</Header>
{errorMessage && (
<Message negative>
<Message.Header>Unable to load fleet profile</Message.Header>
<pre>{errorMessage.toString()}</pre>
</Message>
)}
{!errorMessage && (
<div>
<Icon loading name="spinner" /> Loading...
</div>
)}
<p>
Are you looking to share your player profile? Go to the <Link to={`/playertools`}>Player Tools page</Link> to
upload your player.json and access other useful player tools.
</p>
</Layout>
);
}
let imageUrl = 'icons_icon_faction_starfleet.png';
if (factions && factions[fleet_data.nicon_index]) {
imageUrl = factions[fleet_data.nicon_index].icon;
}
let event1;
let event2;
let event3;
if (events[0].event_name === fleet_data.leaderboard[0].event_name) {
event1 = events[0];
event2 = events[1];
event3 = events[2];
} else {
event1 = events.find(ev => ev.event_name === fleet_data.leaderboard[0].event_name);
event2 = events.find(ev => ev.event_name === fleet_data.leaderboard[1].event_name);
event3 = events.find(ev => ev.event_name === fleet_data.leaderboard[2].event_name);
}
return (
<Layout title={fleet_data.name}>
<Item.Group>
<Item>
<Item.Image size="tiny" src={`${process.env.GATSBY_ASSETS_URL}${imageUrl}`} />
<Item.Content>
<Item.Header>{fleet_data.name}</Item.Header>
<Item.Meta>
<Label>Starbase level: {fleet_data.nstarbase_level}</Label>
<Label>
Size: {fleet_data.cursize} / {fleet_data.maxsize}
</Label>
<Label>Created: {new Date(fleet_data.created).toLocaleDateString()}</Label>
<Label>
Enrollment {fleet_data.enrollment} (min level: {fleet_data.nmin_level})
</Label>
</Item.Meta>
</Item.Content>
</Item>
</Item.Group>
{event1 && <table>
<tbody>
<tr>
<th>
{' '}
<Link to={`/event_info?instance_id=${event1.instance_id}`}>
{fleet_data.leaderboard[0].event_name}
</Link>
</th>
<th>
{' '}
<Link to={`/event_info?instance_id=${event2.instance_id}`}>
{fleet_data.leaderboard[1].event_name}
</Link>
</th>
<th>
{' '}
<Link to={`/event_info?instance_id=${event3.instance_id}`}>
{fleet_data.leaderboard[2].event_name}
</Link>
</th>
</tr>
<tr>
<td><Image size="medium" src={`${process.env.GATSBY_ASSETS_URL}${event1.image}`} /></td>
<td><Image size="medium" src={`${process.env.GATSBY_ASSETS_URL}${event2.image}`} /></td>
<td><Image size="medium" src={`${process.env.GATSBY_ASSETS_URL}${event3.image}`} /></td>
</tr>
<tr>
<td align="center">Fleet rank: {fleet_data.leaderboard[0].fleet_rank}</td>
<td align="center">Fleet rank: {fleet_data.leaderboard[1].fleet_rank}</td>
<td align="center">Fleet rank: {fleet_data.leaderboard[2].fleet_rank}</td>
</tr>
</tbody>
</table>}
<Header as="h4">Members</Header>
<Table celled selectable striped collapsing unstackable compact="very">
<Table.Header>
<Table.Row>
<Table.HeaderCell width={3}>Name</Table.HeaderCell>
<Table.HeaderCell width={1}>Rank</Table.HeaderCell>
<Table.HeaderCell width={1}>Profile</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{fleet_data.members.map((member, idx) => (
<Table.Row key={idx}>
<Table.Cell>
<div
style={{
display: 'grid',
gridTemplateColumns: '60px auto',
gridTemplateAreas: `'icon stats' 'icon description'`,
gridGap: '1px'
}}
>
<div style={{ gridArea: 'icon' }}>
<img
width={48}
src={`${process.env.GATSBY_ASSETS_URL}${member.crew_avatar || 'crew_portraits_cm_empty_sm.png'}`}
/>
</div>
<div style={{ gridArea: 'stats' }}>
<span style={{ fontWeight: 'bolder', fontSize: '1.25em' }}>
{member.last_update ? (
<Link to={`/profile?dbid=${member.dbid}`}>{member.display_name}</Link>
) : (
<span>{member.display_name}</span>
)}
</span>
</div>
<div style={{ gridArea: 'description' }}>
{member.last_update && (
<Label size="tiny">
Last profile upload: {new Date(Date.parse(member.last_update)).toLocaleDateString()}
</Label>
)}
</div>
</div>
</Table.Cell>
<Table.Cell>{member.rank}</Table.Cell>
<Table.Cell>
{member.last_update
? `Last profile upload: ${new Date(Date.parse(member.last_update)).toLocaleDateString()}`
: 'Never'}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
</Layout>
);
}
Example #17
Source File: events.tsx From website with MIT License | 4 votes |
function EventsPage() {
const [eventsData, setEventsData] = React.useState<EventInstance[]>([]);
const [leaderboardData, setLeaderboardData] = React.useState(null);
const [loadingError, setLoadingError] = React.useState(null);
const [modalEventInstance, setModalEventInstance] = React.useState(null);
// load the events and leaderboard data once on component mount
React.useEffect(() => {
async function loadData() {
try {
const fetchEventResp = await fetch('/structured/event_instances.json')
const eventDataList = await fetchEventResp.json();
setEventsData(eventDataList.reverse());
const fetchLeaderboardResp = await fetch('/structured/event_leaderboards.json');
const leaderboardDataList = await fetchLeaderboardResp.json();
const keyedLeaderboard = {};
leaderboardDataList.forEach(entry => keyedLeaderboard[entry.instance_id] = entry);
setLeaderboardData(keyedLeaderboard);
}
catch (e) {
setLoadingError(e);
}
}
loadData();
}, []);
return (
<Layout>
<Container style={{ paddingTop: '4em', paddingBottom: '2em' }}>
<Header as='h2'>Events</Header>
{loadingError && (
<Message negative>
<Message.Header>Unable to load event information</Message.Header>
<pre>{loadingError.toString()}</pre>
</Message>
)}
<Grid stackable columns={3}>
{eventsData.map(eventInfo => (
<Grid.Column key={eventInfo.instance_id}>
<div
style={{ cursor: 'pointer' }}
onClick={() => setModalEventInstance(eventInfo)}
>
<Segment padded>
<Label attached="bottom">
{eventInfo.event_name}
</Label>
<LazyImage
src={`${process.env.GATSBY_ASSETS_URL}${eventInfo.image}`}
size="large"
onError={e => e.target.style.visibility = 'hidden'}
/>
</Segment>
</div>
</Grid.Column>
))}
</Grid>
{modalEventInstance !== null && (
<Modal
open
size="large"
onClose={() => setModalEventInstance(null)}
closeIcon
>
<Modal.Header>{modalEventInstance.event_name}</Modal.Header>
<Modal.Content scrolling>
<EventInfoModal
instanceId={modalEventInstance.instance_id}
image={modalEventInstance.image}
hasDetails={modalEventInstance.event_details}
leaderboard={leaderboardData[modalEventInstance.instance_id].leaderboard}
/>
</Modal.Content>
</Modal>
)}
</Container>
</Layout>
);
}
Example #18
Source File: event_info.tsx From website with MIT License | 4 votes |
render() {
const { event_instace, errorMessage, event_data } = this.state;
if (event_instace === undefined || event_data === undefined || errorMessage !== undefined) {
return (
<Layout title='Event information'>
<Header as='h4'>Event information</Header>
{errorMessage && (
<Message negative>
<Message.Header>Unable to load event information</Message.Header>
<pre>{errorMessage.toString()}</pre>
</Message>
)}
{!errorMessage && (
<div>
<Icon loading name='spinner' /> Loading...
</div>
)}
</Layout>
);
}
return (
<Layout title={event_data.ev_inst.event_name}>
<Header as='h3'>{event_data.ev_inst.event_name}</Header>
<Image size='large' src={`${process.env.GATSBY_ASSETS_URL}${event_data.ev_inst.image}`} />
{this.renderEventDetails()}
{this.renderEventLog()}
<Header as='h4'>Leaderboard</Header>
<Table celled selectable striped collapsing unstackable compact='very'>
<Table.Header>
<Table.Row>
<Table.HeaderCell width={3}>Name</Table.HeaderCell>
<Table.HeaderCell width={1}>Rank</Table.HeaderCell>
<Table.HeaderCell width={1}>Score</Table.HeaderCell>
<Table.HeaderCell width={2}>Fleet</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{event_data.ev_lead.leaderboard.map((member, idx) => (
<Table.Row key={idx}>
<Table.Cell>
<div
style={{
display: 'grid',
gridTemplateColumns: '60px auto',
gridTemplateAreas: `'icon stats' 'icon description'`,
gridGap: '1px'
}}>
<div style={{ gridArea: 'icon' }}>
<img
width={48}
src={`${process.env.GATSBY_ASSETS_URL}${member.avatar ? member.avatar.file.substr(1).replace(/\//g, '_') + '.png' : 'crew_portraits_cm_empty_sm.png'
}`}
/>
</div>
<div style={{ gridArea: 'stats' }}>
<span style={{ fontWeight: 'bolder', fontSize: '1.25em' }}>
{member.last_update ? (
<Link to={`/profile?dbid=${member.dbid}`}>{member.display_name}</Link>
) : (
<span>{member.display_name}</span>
)}
</span>
</div>
<div style={{ gridArea: 'description' }}>
Level {member.level}
{member.last_update && (
<Label size='tiny'>Last profile upload: {new Date(Date.parse(member.last_update)).toLocaleDateString()}</Label>
)}
</div>
</div>
</Table.Cell>
<Table.Cell>{member.rank}</Table.Cell>
<Table.Cell>{member.score}</Table.Cell>
<Table.Cell>
{member.fleetname ? <Link to={`/fleet_info?fleetid=${member.fleetid}`}>
<b>{member.fleetname}</b>
</Link> : <span>-</span>}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
{event_data.ev_flead &&
<div>
<Message>
<Message.Header>TODO: Fleet Leaderboard is experimental</Message.Header>
This data may be incomplete or out of date!
</Message>
<Header as='h4'>Fleet leaderboard</Header>
<Table celled selectable striped collapsing unstackable compact='very'>
<Table.Header>
<Table.Row>
<Table.HeaderCell width={3}>Name</Table.HeaderCell>
<Table.HeaderCell width={1}>Rank</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{event_data.ev_flead.fleet_ranks.map((fleet, idx) => (
<Table.Row key={idx}>
<Table.Cell>{fleet.fleet_rank}</Table.Cell>
<Table.Cell>
<Link to={`/fleet_info?fleetid=${fleet.id}`}>
<b>{fleet.name}</b>
</Link>
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
</div>}
</Layout>
);
}
Example #19
Source File: event_info.tsx From website with MIT License | 4 votes |
renderEventDetails() {
const { event_data } = this.state;
if (event_data === undefined || event_data.event_details === undefined) {
return <span />;
}
let event = event_data.event_details;
return (
<div>
<Message icon warning>
<Icon name='exclamation triangle' />
<Message.Content>
<Message.Header>Work in progress!</Message.Header>
This section is under development and not fully functional yet.
</Message.Content>
</Message>
<p>{event.description}</p>
<p>{event.rules}</p>
<Label>{event.bonus_text}</Label>
{event.content.map((cnt, idx) => {
let crew_bonuses = undefined;
if (cnt.shuttles) {
crew_bonuses = cnt.shuttles[0].crew_bonuses;
} else if (cnt.crew_bonuses) {
crew_bonuses = cnt.crew_bonuses;
} else if (cnt.bonus_crew && cnt.bonus_traits) {
// Skirmishes
crew_bonuses = {};
cnt.bonus_crew.forEach(element => {
crew_bonuses[element] = 10;
});
// TODO: crew from traits
} else if (cnt.special_crew) {
// Expeditions
crew_bonuses = {};
cnt.special_crew.forEach(element => {
crew_bonuses[element] = 50;
});
}
return (
<div key={idx}>
<Header as='h5'>Phase {idx + 1}</Header>
<Label>Type: {cnt.content_type}</Label>
<Header as='h6'>Bonus crew</Header>
{crew_bonuses && (
<p>
{Object.entries(crew_bonuses).map(([bonus, val], idx) => (
<span key={idx}>
{bonus} ({val}),
</span>
))}
</p>
)}
</div>
);
})}
<Header as='h4'>Threshold rewards</Header>
<Table celled selectable striped collapsing unstackable compact='very'>
<Table.Header>
<Table.Row>
<Table.HeaderCell width={2}>Points</Table.HeaderCell>
<Table.HeaderCell width={4}>Reward</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{event.threshold_rewards.filter(reward => reward.rewards && reward.rewards.length > 0).map((reward, idx) => (
<Table.Row key={idx}>
<Table.Cell>{reward.points}</Table.Cell>
<Table.Cell>
{reward.rewards[0].quantity} {reward.rewards[0].full_name}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
<Header as='h4'>Ranked rewards</Header>
<Table celled selectable striped collapsing unstackable compact='very'>
<Table.Header>
<Table.Row>
<Table.HeaderCell width={2}>Ranks</Table.HeaderCell>
<Table.HeaderCell width={4}>Rewards</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{event.ranked_brackets.map((bracket, idx) => (
<Table.Row key={idx}>
<Table.Cell>
{bracket.first} - {bracket.last}
</Table.Cell>
<Table.Cell>
{bracket.rewards.map((reward, idx) => (
<span key={idx}>
{reward.quantity} {reward.full_name},
</span>
))}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>
<Header as='h4'>Quest</Header>
{event.quest ? event.quest.map((quest, idx) => (
<div key={idx}>
{quest && quest.screens && quest.screens.map((screen, idx) => (
<p key={idx}>
<b>{screen.speaker_name}: </b>
{screen.text}
</p>
))}
</div>
)) : <span>Mini-events don't include quest information.</span>}
<Message>
<Message.Header>TODO: Leaderboard out of date</Message.Header>
If this event is currently active, the leaderboard below is out of date (updated only a couple of times a week).
</Message>
</div>
);
}
Example #20
Source File: App.tsx From watchparty with MIT License | 4 votes |
render() {
const sharer = this.state.participants.find((p) => p.isScreenShare);
const controls = (
<Controls
key={this.state.controlsTimestamp}
togglePlay={this.togglePlay}
onSeek={this.onSeek}
fullScreen={this.fullScreen}
toggleMute={this.toggleMute}
toggleSubtitle={this.toggleSubtitle}
setVolume={this.setVolume}
jumpToLeader={this.jumpToLeader}
paused={this.state.currentMediaPaused}
muted={this.isMuted()}
subtitled={this.isSubtitled()}
currentTime={this.getCurrentTime()}
duration={this.getDuration()}
disabled={!this.haveLock()}
leaderTime={this.isHttp() ? this.getLeaderTime() : undefined}
isPauseDisabled={this.isPauseDisabled()}
/>
);
const subscribeButton = (
<SubscribeButton
user={this.props.user}
isSubscriber={this.props.isSubscriber}
isCustomer={this.props.isCustomer}
/>
);
const displayRightContent =
this.state.showRightBar || this.state.fullScreen;
const rightBar = (
<Grid.Column
width={displayRightContent ? 4 : 1}
style={{ display: 'flex', flexDirection: 'column' }}
className={`${
this.state.fullScreen
? 'fullHeightColumnFullscreen'
: 'fullHeightColumn'
}`}
>
<Input
inverted
fluid
label={'My name is:'}
value={this.state.myName}
onChange={this.updateName}
style={{ visibility: displayRightContent ? '' : 'hidden' }}
icon={
<Icon
onClick={() => this.updateName(null, { value: generateName() })}
name="refresh"
inverted
circular
link
/>
}
/>
{
<Menu
inverted
widths={3}
style={{
marginTop: '4px',
marginBottom: '4px',
visibility: displayRightContent ? '' : 'hidden',
}}
>
<Menu.Item
name="chat"
active={this.state.currentTab === 'chat'}
onClick={() => {
this.setState({ currentTab: 'chat', unreadCount: 0 });
}}
as="a"
>
Chat
{this.state.unreadCount > 0 && (
<Label circular color="red">
{this.state.unreadCount}
</Label>
)}
</Menu.Item>
<Menu.Item
name="people"
active={this.state.currentTab === 'people'}
onClick={() => this.setState({ currentTab: 'people' })}
as="a"
>
People
<Label
circular
color={
getColorForString(
this.state.participants.length.toString()
) as SemanticCOLORS
}
>
{this.state.participants.length}
</Label>
</Menu.Item>
<Menu.Item
name="settings"
active={this.state.currentTab === 'settings'}
onClick={() => this.setState({ currentTab: 'settings' })}
as="a"
>
{/* <Icon name="setting" /> */}
Settings
</Menu.Item>
</Menu>
}
<Chat
chat={this.state.chat}
nameMap={this.state.nameMap}
pictureMap={this.state.pictureMap}
socket={this.socket}
scrollTimestamp={this.state.scrollTimestamp}
getMediaDisplayName={this.getMediaDisplayName}
hide={this.state.currentTab !== 'chat' || !displayRightContent}
isChatDisabled={this.state.isChatDisabled}
owner={this.state.owner}
user={this.props.user}
ref={this.chatRef}
/>
{this.state.state === 'connected' && (
<VideoChat
socket={this.socket}
participants={this.state.participants}
nameMap={this.state.nameMap}
pictureMap={this.state.pictureMap}
tsMap={this.state.tsMap}
rosterUpdateTS={this.state.rosterUpdateTS}
hide={this.state.currentTab !== 'people' || !displayRightContent}
owner={this.state.owner}
user={this.props.user}
/>
)}
<SettingsTab
hide={this.state.currentTab !== 'settings' || !displayRightContent}
user={this.props.user}
roomLock={this.state.roomLock}
setRoomLock={this.setRoomLock}
socket={this.socket}
isSubscriber={this.props.isSubscriber}
roomId={this.state.roomId}
isChatDisabled={this.state.isChatDisabled}
setIsChatDisabled={this.setIsChatDisabled}
owner={this.state.owner}
setOwner={this.setOwner}
vanity={this.state.vanity}
setVanity={this.setVanity}
roomLink={this.state.roomLink}
password={this.state.password}
setPassword={this.setPassword}
clearChat={this.clearChat}
roomTitle={this.state.roomTitle}
setRoomTitle={this.setRoomTitle}
roomDescription={this.state.roomDescription}
setRoomDescription={this.setRoomDescription}
roomTitleColor={this.state.roomTitleColor}
setRoomTitleColor={this.setRoomTitleColor}
mediaPath={this.state.mediaPath}
setMediaPath={this.setMediaPath}
/>
</Grid.Column>
);
return (
<React.Fragment>
{!this.state.isAutoPlayable && (
<Modal inverted basic open>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<Button
primary
size="large"
onClick={() => {
this.setState({ isAutoPlayable: true });
this.setMute(false);
this.setVolume(1);
}}
icon
labelPosition="left"
>
<Icon name="volume up" />
Click to unmute
</Button>
</div>
</Modal>
)}
{this.state.multiStreamSelection && (
<MultiStreamModal
streams={this.state.multiStreamSelection}
setMedia={this.setMedia}
resetMultiSelect={this.resetMultiSelect}
/>
)}
{this.state.isVBrowserModalOpen && (
<VBrowserModal
isSubscriber={this.props.isSubscriber}
subscribeButton={subscribeButton}
closeModal={() => this.setState({ isVBrowserModalOpen: false })}
startVBrowser={this.startVBrowser}
user={this.props.user}
beta={this.props.beta}
/>
)}
{this.state.isScreenShareModalOpen && (
<ScreenShareModal
closeModal={() => this.setState({ isScreenShareModalOpen: false })}
startScreenShare={this.setupScreenShare}
/>
)}
{this.state.isFileShareModalOpen && (
<FileShareModal
closeModal={() => this.setState({ isFileShareModalOpen: false })}
startFileShare={this.setupFileShare}
/>
)}
{this.state.isSubtitleModalOpen && (
<SubtitleModal
closeModal={() => this.setState({ isSubtitleModalOpen: false })}
socket={this.socket}
currentSubtitle={this.state.currentSubtitle}
src={this.state.currentMedia}
haveLock={this.haveLock}
getMediaDisplayName={this.getMediaDisplayName}
beta={this.props.beta}
/>
)}
{this.state.error && <ErrorModal error={this.state.error} />}
{this.state.isErrorAuth && (
<PasswordModal
savedPasswords={this.state.savedPasswords}
roomId={this.state.roomId}
/>
)}
{this.state.errorMessage && (
<Message
negative
header="Error"
content={this.state.errorMessage}
style={{
position: 'fixed',
bottom: '10px',
right: '10px',
zIndex: 1000,
}}
></Message>
)}
{this.state.successMessage && (
<Message
positive
header="Success"
content={this.state.successMessage}
style={{
position: 'fixed',
bottom: '10px',
right: '10px',
zIndex: 1000,
}}
></Message>
)}
<TopBar
user={this.props.user}
isCustomer={this.props.isCustomer}
isSubscriber={this.props.isSubscriber}
roomTitle={this.state.roomTitle}
roomDescription={this.state.roomDescription}
roomTitleColor={this.state.roomTitleColor}
/>
{
<Grid stackable celled="internally">
<Grid.Row id="theaterContainer">
<Grid.Column
width={this.state.showRightBar ? 12 : 15}
className={
this.state.fullScreen
? 'fullHeightColumnFullscreen'
: 'fullHeightColumn'
}
>
<div
style={{
display: 'flex',
flexDirection: 'column',
height: '100%',
}}
>
{!this.state.fullScreen && (
<React.Fragment>
<ComboBox
setMedia={this.setMedia}
playlistAdd={this.playlistAdd}
playlistDelete={this.playlistDelete}
playlistMove={this.playlistMove}
currentMedia={this.state.currentMedia}
getMediaDisplayName={this.getMediaDisplayName}
launchMultiSelect={this.launchMultiSelect}
streamPath={this.props.streamPath}
mediaPath={this.state.mediaPath}
disabled={!this.haveLock()}
playlist={this.state.playlist}
/>
<Separator />
<div
className="mobileStack"
style={{ display: 'flex', gap: '4px' }}
>
{this.screenShareStream && (
<Button
fluid
className="toolButton"
icon
labelPosition="left"
color="red"
onClick={this.stopScreenShare}
disabled={sharer?.id !== this.socket?.id}
>
<Icon name="cancel" />
Stop Share
</Button>
)}
{!this.screenShareStream &&
!sharer &&
!this.isVBrowser() && (
<Popup
content={`Share a tab or an application. Make sure to check "Share audio" for best results.`}
trigger={
<Button
fluid
className="toolButton"
disabled={!this.haveLock()}
icon
labelPosition="left"
color={'instagram'}
onClick={() => {
this.setState({
isScreenShareModalOpen: true,
});
}}
>
<Icon name={'slideshare'} />
Screenshare
</Button>
}
/>
)}
{!this.screenShareStream &&
!sharer &&
!this.isVBrowser() && (
<Popup
content="Launch a shared virtual browser"
trigger={
<Button
fluid
className="toolButton"
disabled={!this.haveLock()}
icon
labelPosition="left"
color="green"
onClick={() => {
this.setState({
isVBrowserModalOpen: true,
});
}}
>
<Icon name="desktop" />
VBrowser
</Button>
}
/>
)}
{this.isVBrowser() && (
<Popup
content="Choose the person controlling the VBrowser"
trigger={
<Dropdown
icon="keyboard"
labeled
className="icon"
style={{ height: '36px' }}
button
value={this.state.controller}
placeholder="No controller"
clearable
onChange={this.changeController}
selection
disabled={!this.haveLock()}
options={this.state.participants.map((p) => ({
text: this.state.nameMap[p.id] || p.id,
value: p.id,
}))}
></Dropdown>
}
/>
)}
{this.isVBrowser() && (
<Dropdown
icon="desktop"
labeled
className="icon"
style={{ height: '36px' }}
button
disabled={!this.haveLock()}
value={this.state.vBrowserResolution}
onChange={(_e, data) =>
this.setState({
vBrowserResolution: data.value as string,
})
}
selection
options={[
{
text: '1080p (Plus only)',
value: '1920x1080@30',
disabled: !this.state.isVBrowserLarge,
},
{
text: '720p',
value: '1280x720@30',
},
{
text: '576p',
value: '1024x576@60',
},
{
text: '486p',
value: '864x486@60',
},
{
text: '360p',
value: '640x360@60',
},
]}
></Dropdown>
)}
{this.isVBrowser() && (
<Button
fluid
className="toolButton"
icon
labelPosition="left"
color="red"
disabled={!this.haveLock()}
onClick={this.stopVBrowser}
>
<Icon name="cancel" />
Stop VBrowser
</Button>
)}
{!this.screenShareStream &&
!sharer &&
!this.isVBrowser() && (
<Popup
content="Stream your own video file"
trigger={
<Button
fluid
className="toolButton"
disabled={!this.haveLock()}
icon
labelPosition="left"
onClick={() => {
this.setState({
isFileShareModalOpen: true,
});
}}
>
<Icon name="file" />
File
</Button>
}
/>
)}
{false && (
<SearchComponent
setMedia={this.setMedia}
playlistAdd={this.playlistAdd}
type={'youtube'}
streamPath={this.props.streamPath}
disabled={!this.haveLock()}
/>
)}
{Boolean(this.props.streamPath) && (
<SearchComponent
setMedia={this.setMedia}
playlistAdd={this.playlistAdd}
type={'stream'}
streamPath={this.props.streamPath}
launchMultiSelect={this.launchMultiSelect}
disabled={!this.haveLock()}
/>
)}
</div>
<Separator />
</React.Fragment>
)}
<div style={{ flexGrow: 1 }}>
<div id="playerContainer">
{(this.state.loading ||
!this.state.currentMedia ||
this.state.nonPlayableMedia) && (
<div
id="loader"
className="videoContent"
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{this.state.loading && (
<Dimmer active>
<Loader>
{this.isVBrowser()
? 'Launching virtual browser. This can take up to a minute.'
: ''}
</Loader>
</Dimmer>
)}
{!this.state.loading && !this.state.currentMedia && (
<Message
color="yellow"
icon="hand point up"
header="You're not watching anything!"
content="Pick something to watch above."
/>
)}
{!this.state.loading &&
this.state.nonPlayableMedia && (
<Message
color="red"
icon="frown"
header="It doesn't look like this is a media file!"
content="Maybe you meant to launch a VBrowser if you're trying to visit a web page?"
/>
)}
</div>
)}
<iframe
style={{
display:
this.isYouTube() && !this.state.loading
? 'block'
: 'none',
}}
title="YouTube"
id="leftYt"
className="videoContent"
allowFullScreen
frameBorder="0"
allow="autoplay"
src="https://www.youtube.com/embed/?enablejsapi=1&controls=0&rel=0"
/>
{this.isVBrowser() &&
this.getVBrowserPass() &&
this.getVBrowserHost() ? (
<VBrowser
username={this.socket.id}
password={this.getVBrowserPass()}
hostname={this.getVBrowserHost()}
controlling={this.state.controller === this.socket.id}
setLoadingFalse={this.setLoadingFalse}
resolution={this.state.vBrowserResolution}
doPlay={this.doPlay}
setResolution={(data: string) =>
this.setState({ vBrowserResolution: data })
}
/>
) : (
<video
style={{
display:
(this.isVideo() && !this.state.loading) ||
this.state.fullScreen
? 'block'
: 'none',
width: '100%',
maxHeight:
'calc(100vh - 62px - 36px - 36px - 8px - 41px - 16px)',
}}
id="leftVideo"
onEnded={this.onVideoEnded}
playsInline
></video>
)}
</div>
</div>
{this.state.currentMedia && controls}
{Boolean(this.state.total) && (
<div>
<Progress
size="tiny"
color="green"
inverted
value={this.state.downloaded}
total={this.state.total}
// indicating
label={
Math.min(
(this.state.downloaded / this.state.total) * 100,
100
).toFixed(2) +
'% - ' +
formatSpeed(this.state.speed) +
' - ' +
this.state.connections +
' connections'
}
></Progress>
</div>
)}
</div>
<Button
style={{
position: 'absolute',
top: '50%',
right: 'calc(0% - 18px)',
zIndex: 900,
}}
circular
size="mini"
icon={this.state.showRightBar ? 'angle right' : 'angle left'}
onClick={() =>
this.setState({ showRightBar: !this.state.showRightBar })
}
/>
</Grid.Column>
{rightBar}
</Grid.Row>
</Grid>
}
</React.Fragment>
);
}
Example #21
Source File: Controls.tsx From watchparty with MIT License | 4 votes |
render() {
const {
togglePlay,
onSeek,
fullScreen,
toggleMute,
toggleSubtitle,
jumpToLeader,
currentTime,
duration,
leaderTime,
isPauseDisabled,
disabled,
subtitled,
paused,
} = this.props;
const { muted, volume } = this.state;
const isBehind = leaderTime && leaderTime - currentTime > 5;
return (
<div className="controls">
<Icon
size="large"
onClick={() => {
togglePlay();
}}
className="control action"
disabled={disabled || isPauseDisabled}
name={paused ? 'play' : 'pause'}
/>
<Popup
content={
(isBehind ? "We've detected that your stream is behind. " : '') +
'Click to sync to leader.'
}
trigger={
<Icon
size="large"
onClick={jumpToLeader}
className={`control action ${isBehind ? 'glowing' : ''}`}
name={'angle double right'}
/>
}
/>
<div className="control">{formatTimestamp(currentTime)}</div>
<Progress
size="tiny"
color="blue"
onClick={
duration < Infinity && !this.props.disabled ? onSeek : undefined
}
onMouseOver={this.onMouseOver}
onMouseOut={this.onMouseOut}
onMouseMove={this.onMouseMove}
className="control action"
inverted
style={{
flexGrow: 1,
marginTop: 0,
marginBottom: 0,
position: 'relative',
minWidth: '50px',
}}
value={currentTime}
total={duration}
>
{duration < Infinity && this.state.showTimestamp && (
<div
style={{
position: 'absolute',
bottom: '0px',
left: `calc(${this.state.posTimestamp * 100 + '% - 27px'})`,
pointerEvents: 'none',
}}
>
<Label basic color="blue" pointing="below">
<div style={{ width: '34px' }}>
{formatTimestamp(this.state.currTimestamp)}
</div>
</Label>
</div>
)}
</Progress>
<div className="control">{formatTimestamp(duration)}</div>
<Icon
size="large"
onClick={() => {
toggleSubtitle();
}}
className="control action"
name={subtitled ? 'closed captioning' : 'closed captioning outline'}
title="Captions"
/>
<Icon
size="large"
onClick={() => fullScreen(false)}
className="control action"
style={{ transform: 'rotate(90deg)' }}
name="window maximize outline"
title="Theater Mode"
/>
<Icon
size="large"
onClick={() => fullScreen(true)}
className="control action"
name="expand"
title="Fullscreen"
/>
<Icon
size="large"
onClick={() => {
toggleMute();
this.setState({ muted: !this.state.muted });
}}
className="control action"
name={muted ? 'volume off' : 'volume up'}
title="Mute"
/>
<div style={{ width: '100px', marginRight: '10px' }}>
<Slider
value={volume}
color="blue"
settings={{
min: 0,
max: 1,
step: 0.01,
onChange: (value: number) => {
this.setState({ volume: value });
this.props.setVolume(value);
},
}}
/>
</div>
</div>
);
}
Example #22
Source File: AppHeader.tsx From peterportal-client with MIT License | 4 votes |
AppHeader: FC<{}> = props => {
const dispatch = useAppDispatch();
const sidebarOpen = useAppSelector(state => state.ui.sidebarOpen);
const location = useLocation();
const [week, setWeek] = useState('');
let splitLocation = location.pathname.split('/');
let coursesActive = splitLocation.length > 0 && splitLocation[splitLocation.length - 1] == 'courses' || splitLocation.length > 1 && splitLocation[1] == 'course';
let professorsActive = splitLocation.length > 0 && splitLocation[splitLocation.length - 1] == 'professors' || splitLocation.length > 1 && splitLocation[1] == 'professor';
useEffect(() => {
// Get the current week data
axios.get<WeekData>('/schedule/api/currentWeek')
.then(res => {
// case for break and finals week
if (res.data.week == -1) {
setWeek(res.data.display);
}
// case when school is in session
else {
setWeek('Week ' + res.data.week + ' • ' + res.data.quarter);
}
});
}, [])
let toggleMenu = () => {
dispatch(setSidebarStatus(!sidebarOpen));
}
return (
<header className='navbar'>
<div className='navbar-nav'>
<div className='navbar-left'>
{/* Hamburger Menu */}
<div className='navbar-menu'>
<List className='navbar-menu-icon' onClick={toggleMenu} />
</div>
{/* Toggle Course and Professor */}
{(coursesActive || professorsActive) && <div className='navbar-toggle'>
<div className='desktop-toggle'>
<div className={`navbar-toggle-item ${coursesActive ? 'active' : ''}`}>
<a href='/search/courses'>
Courses
</a>
</div>
<div className={`navbar-toggle-item ${professorsActive ? 'active' : ''}`}>
<a href='/search/professors'>
Professors
</a>
</div>
</div>
<div className='mobile-toggle'>
{coursesActive === true && (
<div className={`navbar-toggle-item active`}>
<a href='/search/professors'>
Professors
</a>
</div>
)}
{professorsActive === true && (
<div className={`navbar-toggle-item active`}>
<a href='/search/courses'>
Courses
</a>
</div>
)}
</div>
</div>
}
</div>
{/* Logo */}
<div className='navbar-logo'>
<a href='/'>
<img alt='PeterPortal' id='peterportal-logo' src={Logo}></img>
</a>
</div>
{/* Week */}
<div style={{ display: 'flex', alignItems: 'center' }}>
<div className='beta' style={{ margin: "auto 12px" }}>
<Popup style={{ padding: "36px", width: "400px" }} position='bottom right' trigger={<Label as='a' color='yellow' image>beta<Label.Detail>v1.1</Label.Detail></Label>} flowing hoverable >
<Grid centered columns={1}>
<Grid.Column textAlign='left'>
<h4>Beta Disclaimer</h4>
<p>
Please note that this is a beta version of PeterPortal, which is still undergoing development.
Some content on this web application may not be accurate. Users are encouraged to double check details.
<br />
<br />
Should you encounter any bugs, glitches, lack of functionality or other problems on the application,
please let us know immediately so we can rectify these accordingly. Your help in this regard is greatly appreciated.
</p>
<div className='feedback'>
<a className="ui button" href="https://github.com/icssc-projects/peterportal-client/issues/new" target="_blank" rel="noopener noreferrer">
<Icon name='github' />Report an issue
</a>
<a className="ui button" href="https://forms.gle/JjwBmELq26daroTh9" target="_blank" rel="noopener noreferrer">
<Icon name='clipboard list' />Feedback
</a>
</div>
</Grid.Column>
</Grid>
</Popup>
</div>
<p className='school-term' style={{ height: '1rem', lineHeight: '1rem' }}>
{week}
</p>
</div>
</div>
</header>
);
}
Example #23
Source File: commoncrewdata.tsx From website with MIT License | 4 votes |
renderOtherRanks(crew, roster = false) {
let v = [];
let g = [];
let b = [];
const skillName = short => CONFIG.SKILLS[CONFIG.SKILLS_SHORT.find(c => c.short === short).name];
const rankHandler = rank => roster
? roster.filter(c => c.ranks[rank] && crew.ranks[rank] > c.ranks[rank]).length + 1
: crew.ranks[rank];
const tripletHandler = rank => roster
? roster.filter(c => c.ranks[rank] &&
c.ranks[rank].name == crew.ranks[rank].name &&
crew.ranks[rank].rank > c.ranks[rank].rank).length + 1
: crew.ranks[rank].rank;
// Need to filter by skills first before sorting by voyage triplet
const tripletFilter = crew.ranks.voyTriplet
? crew.ranks.voyTriplet.name.split('/')
.map(s => 'skill:'+s.trim())
.reduce((prev, curr) => prev+' '+curr)
: '';
for (let rank in crew.ranks) {
if (rank.startsWith('V_')) {
v.push(
<Statistic key={rank}>
<Statistic.Label>{rank.substr(2).replace('_', ' / ')}</Statistic.Label>
<Statistic.Value>{rankLinker(roster, rankHandler(rank), crew.symbol, 'ranks.'+rank)}</Statistic.Value>
</Statistic>
);
} else if (rank.startsWith('G_')) {
g.push(
<Statistic key={rank}>
<Statistic.Label>{rank.substr(2).replace('_', ' / ')}</Statistic.Label>
<Statistic.Value>{rankLinker(roster, rankHandler(rank), crew.symbol, 'ranks.'+rank)}</Statistic.Value>
</Statistic>
);
} else if (rank.startsWith('B_') && crew.ranks[rank]) {
b.push(
<Statistic key={rank}>
<Statistic.Label>{skillName(rank.substr(2))}</Statistic.Label>
<Statistic.Value>{rankLinker(roster, rankHandler(rank), crew.symbol, CONFIG.SKILLS_SHORT.find(c => c.short === rank.substr(2)).name, 'descending')}</Statistic.Value>
</Statistic>
);
}
}
return (
<React.Fragment>
<Segment>
<Header as="h5">Base ranks</Header>
<Statistic.Group widths="three" size={'mini'} style={{ paddingBottom: '0.5em' }}>
{b}
</Statistic.Group>
</Segment>
<Segment>
<Header as="h5">Voyage skill ranks</Header>
{crew.ranks.voyTriplet && (
<React.Fragment>
<Statistic.Group widths="one" size={'mini'}>
<Statistic>
<Statistic.Label>{crew.ranks.voyTriplet.name}</Statistic.Label>
<Statistic.Value>{rankLinker(roster, tripletHandler('voyTriplet'), crew.symbol, 'ranks.voyRank', 'ascending', tripletFilter)}</Statistic.Value>
</Statistic>
</Statistic.Group>
<Divider />
</React.Fragment>
)}
<Statistic.Group widths="three" size={'mini'} style={{ paddingBottom: '0.5em' }}>
{v}
</Statistic.Group>
</Segment>
<Segment>
<Header as="h5">Gauntlet pair ranks</Header>
<Statistic.Group widths="three" size={'mini'} style={{ paddingBottom: '0.5em' }}>
{g}
</Statistic.Group>
</Segment>
</React.Fragment>
);
}
Example #24
Source File: commoncrewdata.tsx From website with MIT License | 4 votes |
render() {
const { markdownRemark, crew, compact, crewDemands, roster } = this.props;
let panels = [
{
index: 0,
key: 0,
title: getCoolStats(crew, false),
content: { content: <div style={{ paddingBottom: '1em' }}>{this.renderOtherRanks(crew)}</div> }
}
];
if (roster && roster.length > 0) {
panels.push(
{
index: 1,
key: 1,
title: this.rosterComparisonTitle(crew, roster),
content: { content: <div style={{ paddingBottom: '1em' }}>{this.renderOtherRanks(crew, roster)}</div> }
});
}
return (
<React.Fragment>
{compact ? (
<Segment>
<Grid columns={2}>
<Grid.Column width={4}>
<Image src={`${process.env.GATSBY_ASSETS_URL}${crew.imageUrlFullBody}`} size="tiny" />
</Grid.Column>
<Grid.Column width={12}>
<CrewStat
skill_name="security_skill"
data={crew.base_skills.security_skill}
scale={compact ? 0.75 : 1}
/>
<CrewStat skill_name="command_skill" data={crew.base_skills.command_skill} scale={compact ? 0.75 : 1} />
<CrewStat
skill_name="diplomacy_skill"
data={crew.base_skills.diplomacy_skill}
scale={compact ? 0.75 : 1}
/>
<CrewStat skill_name="science_skill" data={crew.base_skills.science_skill} scale={compact ? 0.75 : 1} />
<CrewStat
skill_name="medicine_skill"
data={crew.base_skills.medicine_skill}
scale={compact ? 0.75 : 1}
/>
<CrewStat
skill_name="engineering_skill"
data={crew.base_skills.engineering_skill}
scale={compact ? 0.75 : 1}
/>
</Grid.Column>
</Grid>
</Segment>
) : (
<Segment>
<CrewStat skill_name="security_skill" data={crew.base_skills.security_skill} scale={compact ? 0.75 : 1} />
<CrewStat skill_name="command_skill" data={crew.base_skills.command_skill} scale={compact ? 0.75 : 1} />
<CrewStat skill_name="diplomacy_skill" data={crew.base_skills.diplomacy_skill} scale={compact ? 0.75 : 1} />
<CrewStat skill_name="science_skill" data={crew.base_skills.science_skill} scale={compact ? 0.75 : 1} />
<CrewStat skill_name="medicine_skill" data={crew.base_skills.medicine_skill} scale={compact ? 0.75 : 1} />
<CrewStat
skill_name="engineering_skill"
data={crew.base_skills.engineering_skill}
scale={compact ? 0.75 : 1}
/>
</Segment>
)}
{crew.skill_data && crew.skill_data.length > 0 && (
<Accordion
defaultActiveIndex={-1}
panels={[
{
index: 0,
key: 0,
title: 'Other fuse levels',
content: {
content: (
<Segment.Group raised>
{crew.skill_data.map((sk: any, idx: number) => (
<Segment key={idx}>
<Rating
defaultRating={sk.rarity}
maxRating={crew.max_rarity}
icon="star"
size="small"
disabled
/>
<CrewStat skill_name="security_skill" data={sk.base_skills.security_skill} scale={0.75} />
<CrewStat skill_name="command_skill" data={sk.base_skills.command_skill} scale={0.75} />
<CrewStat skill_name="diplomacy_skill" data={sk.base_skills.diplomacy_skill} scale={0.75} />
<CrewStat skill_name="science_skill" data={sk.base_skills.science_skill} scale={0.75} />
<CrewStat skill_name="medicine_skill" data={sk.base_skills.medicine_skill} scale={0.75} />
<CrewStat
skill_name="engineering_skill"
data={sk.base_skills.engineering_skill}
scale={0.75}
/>
</Segment>
))}
</Segment.Group>
)
}
}
]}
/>
)}
{crew.flavor && !compact && <p>{crew.flavor}</p>}
{compact && (
<div style={{ textAlign: 'center' }}>
<StatLabel title="Voyage rank" value={crew.ranks.voyRank} />
<StatLabel title="Gauntlet rank" value={crew.ranks.gauntletRank} />
<StatLabel title="Big book tier" value={formatTierLabel(markdownRemark.frontmatter.bigbook_tier)} />
{markdownRemark.frontmatter.events !== null && (
<StatLabel title="Events" value={markdownRemark.frontmatter.events} />
)}
</div>
)}
{!compact && (
<>
<Statistic.Group size="tiny">
{markdownRemark.frontmatter.events !== null && (
<Statistic>
<Statistic.Label>Events</Statistic.Label>
<Statistic.Value>{markdownRemark.frontmatter.events}</Statistic.Value>
</Statistic>
)}
<Statistic>
<Statistic.Label>Big Book Tier</Statistic.Label>
<Statistic.Value>{formatTierLabel(markdownRemark.frontmatter.bigbook_tier)}</Statistic.Value>
</Statistic>
<Statistic>
<Statistic.Label>CAB Rating <CABExplanation /></Statistic.Label>
<Statistic.Value>{crew.cab_ov ?? 'None'}</Statistic.Value>
</Statistic>
{!compact && markdownRemark.frontmatter.in_portal !== null && (
<Statistic color={markdownRemark.frontmatter.in_portal ? 'green' : 'red'}>
<Statistic.Label>Portal</Statistic.Label>
<Statistic.Value>{markdownRemark.frontmatter.in_portal ? 'YES' : 'NO'}</Statistic.Value>
</Statistic>
)}
</Statistic.Group>
<Statistic.Group style={{ paddingBottom: '2em' }} size="tiny">
<Statistic>
<Statistic.Label>CAB Rank <CABExplanation /></Statistic.Label>
<Statistic.Value>{crew.cab_ov_rank ? rankLinker(false, crew.cab_ov_rank, crew.symbol, 'cab_ov', 'descending', 'rarity:'+crew.max_rarity) : 'None'}</Statistic.Value>
</Statistic>
<Statistic>
<Statistic.Label>Voyage Rank</Statistic.Label>
<Statistic.Value>{rankLinker(false, crew.ranks.voyRank, crew.symbol, 'ranks.voyRank')}</Statistic.Value>
</Statistic>
<Statistic>
<Statistic.Label>Gauntlet Rank</Statistic.Label>
<Statistic.Value>{rankLinker(false, crew.ranks.gauntletRank, crew.symbol, 'ranks.gauntletRank')}</Statistic.Value>
</Statistic>
</Statistic.Group>
</>
)}
{crewDemands && (
<p>
<b>{crewDemands.factionOnlyTotal}</b>
{' faction items, '}
<span style={{ display: 'inline-block' }}>
<img src={`${process.env.GATSBY_ASSETS_URL}atlas/energy_icon.png`} height={14} />
</span>{' '}
<b>{crewDemands.totalChronCost}</b>
{', '}
<span style={{ display: 'inline-block' }}>
<img src={`${process.env.GATSBY_ASSETS_URL}currency_sc_currency_0.png`} height={16} />
</span>{' '}
<b>{crewDemands.craftCost}</b>
</p>
)}
<Accordion
exclusive={false}
panels={panels}
/>
<p>
<b>Traits: </b>
{crew.traits_named
.map(trait => (
<a key={trait} href={`/?search=trait:${trait}`}>
{trait}
</a>
))
.reduce((prev, curr) => [prev, ', ', curr])}
{', '}
{crew.traits_hidden
.map(trait => (
<a style={{ color: 'lightgray' }} key={trait} href={`/?search=trait:${trait}`}>
{trait}
</a>
))
.reduce((prev, curr) => [prev, ', ', curr])}
</p>
{crew.cross_fuse_targets && crew.cross_fuse_targets.symbol && (
<p>
Can cross-fuse with{' '}
<Link to={`/crew/${crew.cross_fuse_targets.symbol}/`}>{crew.cross_fuse_targets.name}</Link>.
</p>
)}
{crew.collections.length > 0 && (
<p>
<b>Collections: </b>
{crew.collections
.map(col => (
<Link key={col} to={`/collections/#${encodeURIComponent(col)}`}>
{col}
</Link>
))
.reduce((prev, curr) => [prev, ', ', curr])}
</p>
)}
<p>
<b>Date added: </b>{new Date(crew.date_added).toLocaleDateString("en-US")} (<b>Obtained: </b>{crew.obtained})
</p>
{crew.nicknames && crew.nicknames.length > 0 && (
<p>
<b>Also known as: </b>
{crew.nicknames
.map((nick, idx) => (
<span key={idx}>{nick.cleverThing}{nick.creator ? <> (coined by <i>{nick.creator}</i>)</> : ''}</span>
))
.reduce((prev, curr) => [prev, ', ', curr])}
</p>
)}
</React.Fragment>
);
}
Example #25
Source File: SettingsTab.tsx From watchparty with MIT License | 4 votes |
SettingsTab = ({
hide,
user,
roomLock,
setRoomLock,
socket,
isSubscriber,
owner,
vanity,
setVanity,
roomLink,
password,
setPassword,
isChatDisabled,
setIsChatDisabled,
clearChat,
roomTitle,
roomDescription,
roomTitleColor,
mediaPath,
setMediaPath,
}: SettingsTabProps) => {
const [updateTS, setUpdateTS] = useState(0);
const [permModalOpen, setPermModalOpen] = useState(false);
const [validVanity, setValidVanity] = useState(true);
const [validVanityLoading, setValidVanityLoading] = useState(false);
const [adminSettingsChanged, setAdminSettingsChanged] = useState(false);
const [roomTitleInput, setRoomTitleInput] = useState<string | undefined>(undefined);
const [roomDescriptionInput, setRoomDescriptionInput] = useState<
string | undefined
>(undefined);
const [roomTitleColorInput, setRoomTitleColorInput] = useState<
string | undefined
>('');
const setRoomState = useCallback(
async (data: any) => {
const token = await user?.getIdToken();
socket.emit('CMD:setRoomState', {
uid: user?.uid,
token,
...data,
});
},
[socket, user]
);
const setRoomOwner = useCallback(
async (data: any) => {
const token = await user?.getIdToken();
socket.emit('CMD:setRoomOwner', {
uid: user?.uid,
token,
...data,
});
},
[socket, user]
);
const checkValidVanity = useCallback(
async (input: string) => {
if (!input) {
setValidVanity(true);
return;
}
setValidVanity(false);
setValidVanityLoading(true);
const response = await axios.get(serverPath + '/resolveRoom/' + input);
const data = response.data;
setValidVanityLoading(false);
if (
data &&
data.vanity &&
data.vanity !== roomLink.split('/').slice(-1)[0]
) {
// Already exists and doesn't match current room
setValidVanity(false);
} else {
setValidVanity(true);
}
},
[setValidVanity, roomLink]
);
const disableLocking =
!Boolean(user) || Boolean(roomLock && roomLock !== user?.uid);
const disableOwning = !Boolean(user) || Boolean(owner && owner !== user?.uid);
return (
<div
style={{
display: hide ? 'none' : 'block',
color: 'white',
overflow: 'scroll',
padding: '8px',
}}
>
{permModalOpen && (
<PermanentRoomModal
closeModal={() => setPermModalOpen(false)}
></PermanentRoomModal>
)}
<div className="sectionHeader">Room Settings</div>
{!user && (
<Message color="yellow" size="tiny">
You need to be signed in to change these settings.
</Message>
)}
<SettingRow
icon={roomLock ? 'lock' : 'lock open'}
name={`Lock Room`}
description="Only the person who locked the room can control the video."
checked={Boolean(roomLock)}
disabled={disableLocking && disableOwning}
onChange={(_e, data) => setRoomLock(data.checked)}
/>
{
<SettingRow
icon={'clock'}
name={`Make Room Permanent`}
description={
'Prevent this room from expiring. This also unlocks additional room features.'
}
helpIcon={
<Icon
name="help circle"
onClick={() => setPermModalOpen(true)}
style={{ cursor: 'pointer' }}
></Icon>
}
checked={Boolean(owner)}
disabled={disableOwning}
onChange={(_e, data) => setRoomOwner({ undo: !data.checked })}
/>
}
{owner && owner === user?.uid && (
<div className="sectionHeader">Admin Settings</div>
)}
{owner && owner === user?.uid && (
<SettingRow
icon={'key'}
name={`Set Room Password`}
description="Users must know this password in order to join the room."
content={
<Input
value={password}
size="mini"
onChange={(e) => {
setAdminSettingsChanged(true);
setPassword(e.target.value);
}}
fluid
/>
}
disabled={false}
/>
)}
{owner && owner === user?.uid && (
<SettingRow
icon={'folder'}
name={`Set Room Media Source`}
description="Set a media source URL with files to replace the default examples. Supports S3 buckets and nginx file servers."
content={
<Input
value={mediaPath}
size="mini"
onChange={(e) => {
setAdminSettingsChanged(true);
setMediaPath(e.target.value);
}}
fluid
/>
}
disabled={false}
/>
)}
{owner && owner === user?.uid && (
<SettingRow
icon={'i cursor'}
name={`Disable Chat`}
description="Prevent users from sending messages in chat."
checked={Boolean(isChatDisabled)}
disabled={false}
onChange={(_e, data) => {
setAdminSettingsChanged(true);
setIsChatDisabled(Boolean(data.checked));
}}
/>
)}
{owner && owner === user?.uid && (
<SettingRow
icon={'i delete'}
name={`Clear Chat`}
description="Delete all existing chat messages"
disabled={false}
content={
<Button
color="red"
icon
labelPosition="left"
onClick={() => clearChat()}
>
<Icon name="delete" />
Delete Messages
</Button>
}
/>
)}
{owner && owner === user?.uid && (
<SettingRow
icon={'linkify'}
name={`Set Custom Room URL`}
description="Set a custom URL for this room. Inappropriate names may be revoked."
checked={Boolean(roomLock)}
disabled={!isSubscriber}
subOnly={true}
content={
<React.Fragment>
<Input
value={vanity}
disabled={!isSubscriber}
onChange={(e) => {
setAdminSettingsChanged(true);
checkValidVanity(e.target.value);
setVanity(e.target.value);
}}
label={<Label>{`${window.location.origin}/r/`}</Label>}
loading={validVanityLoading}
fluid
size="mini"
icon
action={
validVanity ? (
<Icon name="checkmark" color="green" />
) : (
<Icon name="close" color="red" />
)
}
></Input>
</React.Fragment>
}
/>
)}
{owner && owner === user?.uid && (
<SettingRow
icon={'pencil'}
name={`Set Room Title, Description & Color`}
description="Set the room title, description and title color to be displayed in the top bar."
disabled={!isSubscriber}
subOnly={true}
content={
<React.Fragment>
<div style={{ display: 'flex', marginBottom: 2 }}>
<Input
style={{ marginRight: 3, flexGrow: 1 }}
value={roomTitleInput ?? roomTitle}
disabled={!isSubscriber}
maxLength={roomTitleMaxCharLength}
onChange={(e) => {
setAdminSettingsChanged(true);
setRoomTitleInput(e.target.value);
}}
placeholder={`Title (max. ${roomTitleMaxCharLength} characters)`}
fluid
size="mini"
icon
></Input>
<Popup
content={
<React.Fragment>
<h5>Edit Title Color</h5>
<HexColorPicker
color={
roomTitleColorInput ||
roomTitleColor ||
defaultRoomTitleColor
}
onChange={(e) => {
setAdminSettingsChanged(true);
setRoomTitleColorInput(e);
}}
/>
<div
style={{
marginTop: 8,
paddingLeft: 4,
borderLeft: `24px solid ${roomTitleColorInput}`,
}}
>
{roomTitleColorInput?.toUpperCase()}
</div>
</React.Fragment>
}
on="click"
trigger={
<Button
icon
color="teal"
size="tiny"
style={{ margin: 0 }}
disabled={!isSubscriber}
>
<Icon name="paint brush" />
</Button>
}
/>
</div>
<Input
style={{ marginBottom: 2 }}
value={roomDescriptionInput ?? roomDescription}
disabled={!isSubscriber}
maxLength={roomDescriptionMaxCharLength}
onChange={(e) => {
setAdminSettingsChanged(true);
setRoomDescriptionInput(e.target.value);
}}
placeholder={`Description (max. ${roomDescriptionMaxCharLength} characters)`}
fluid
size="mini"
icon
></Input>
</React.Fragment>
}
/>
)}
<div
style={{
borderTop: '3px dashed white',
marginTop: 10,
marginBottom: 10,
}}
/>
{owner && owner === user?.uid && (
<Button
primary
disabled={!validVanity || !adminSettingsChanged}
labelPosition="left"
icon
fluid
onClick={() => {
setRoomState({
vanity: vanity,
password: password,
isChatDisabled: isChatDisabled,
roomTitle: roomTitleInput ?? roomTitle,
roomDescription: roomDescriptionInput ?? roomDescription,
roomTitleColor:
roomTitleColorInput || roomTitleColor || defaultRoomTitleColor,
mediaPath: mediaPath,
});
setAdminSettingsChanged(false);
}}
>
<Icon name="save" />
Save Admin Settings
</Button>
)}
<div className="sectionHeader">Local Settings</div>
<SettingRow
updateTS={updateTS}
icon="bell"
name="Disable chat notification sound"
description="Don't play a sound when a chat message is sent while you're on another tab"
checked={Boolean(getCurrentSettings().disableChatSound)}
disabled={false}
onChange={(_e, data) => {
updateSettings(
JSON.stringify({
...getCurrentSettings(),
disableChatSound: data.checked,
})
);
setUpdateTS(Number(new Date()));
}}
/>
</div>
);
}
Example #26
Source File: ProfileWidgetPlus.tsx From communitymap-ui with Apache License 2.0 | 4 votes |
ProfileWidgetPlus: React.FC = () => {
const user = useAuth();
const { dialogs } = useMyDirectMessages();
const unreadDialogs =
dialogs?.filter((dlg) => dlg.lastMsgId !== dlg.lastReadBy[user?.uid || ''])
.length || 0;
const [login, setLogin] = useState(false);
useEffect(() => {
if (user && login) {
setLogin(false);
}
}, [user, login]);
const [showProfile, setShowProfile] = useState(false);
const signOut = () => getFirebaseApp().auth().signOut();
return (
<div id="profile-widget">
{login && <Login title="" onClose={() => setLogin(false)} />}
{showProfile && !!user && (
<Modal open closeIcon onClose={() => setShowProfile(false)}>
<Modal.Header>Your profile</Modal.Header>
<Modal.Content>
<EditUserProfile user={user} />
</Modal.Content>
</Modal>
)}
{user ? (
<Dropdown
trigger={
<Button className="profile-button" icon size="large">
<Icon.Group>
<Icon name="user outline" />
{unreadDialogs > 0 && (
<Icon
corner="top right"
className="has-unread-messages"
name="mail"
color="red"
/>
)}
</Icon.Group>
</Button>
}
pointing="top right"
icon={null}
>
<Dropdown.Menu>
<Dropdown.Item disabled>{user.email}</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item onClick={() => setShowProfile(true)}>
<Icon name="user" />
Profile
</Dropdown.Item>
<Dropdown.Item as={Link} to="/my-messages">
<Icon name="mail" />
Messages
{unreadDialogs > 0 && (
<Label className="user-menu-label" color="blue">
{unreadDialogs}
</Label>
)}
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item as={Link} to="/terms">
Terms of Service
</Dropdown.Item>
<Dropdown.Item as={Link} to="/privacy">
Privacy Policy
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item onClick={signOut}>
<Icon name="log out" />
Log out
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
) : (
// <Button primary size="large" onClick={() => setLogin(true)}>
// Sign in
// </Button>
<Dropdown
trigger={
<Button className="profile-button" icon size="large">
<Icon name="bars" />
</Button>
}
pointing="top right"
icon={null}
>
<Dropdown.Menu>
<Dropdown.Item as={Link} to="/terms">
Terms of Service
</Dropdown.Item>
<Dropdown.Item as={Link} to="/privacy">
Privacy Policy
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item onClick={() => setLogin(true)}>
<Icon name="sign in" />
Sign in
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
)}
</div>
);
}
Example #27
Source File: CourseQuarterIndicator.tsx From peterportal-client with MIT License | 4 votes |
CourseQuarterIndicator: FC<CourseQuarterIndicatorProps> = (props) => {
return (
<div style={{ display: 'flex', marginLeft: 'auto' }}>
{props.terms.length > 0 && (
<Popup
trigger={
<div style={{ display: 'inline' }}>
{props.terms.includes('2020 Fall') && (
<span style={{ float: 'right', marginLeft: '4px' }}>
<Label circular color='yellow' empty />
</span>
)}
{props.terms.includes('2020 Summer2') && (
<span style={{ float: 'right', marginLeft: '4px' }}>
<Label circular color='violet' empty />
</span>
)}
{props.terms.includes('2020 Summer10wk') && (
<span style={{ float: 'right', marginLeft: '4px' }}>
<Label circular color='green' empty />
</span>
)}
{props.terms.includes('2020 Summer1') && (
<span style={{ float: 'right', marginLeft: '4px' }}>
<Label circular color='orange' empty />
</span>
)}
{props.terms.includes('2020 Spring') && (
<span style={{ float: 'right', marginLeft: '4px' }}>
<Label circular color='teal' empty />
</span>
)}
</div>
}
content={
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h5 style={{ marginBottom: '4px' }}>Offered in:</h5>
{props.terms.includes('2020 Fall') && (
<div style={{ float: 'right' }}>
<Label circular color='yellow' empty />
<span style={{ marginLeft: '6px' }}>Fall 2020</span>
</div>
)}
{props.terms.includes('2020 Summer2') && (
<div style={{ float: 'right' }}>
<Label circular color='violet' empty />
<span style={{ marginLeft: '6px' }}>SS II 2020</span>
</div>
)}
{props.terms.includes('2020 Summer10wk') && (
<div style={{ float: 'right' }}>
<Label circular color='green' empty />
<span style={{ marginLeft: '6px' }}>SS 10wk 2020</span>
</div>
)}
{props.terms.includes('2020 Summer1') && (
<div style={{ float: 'right' }}>
<Label circular color='orange' empty />
<span style={{ marginLeft: '6px' }}>SS I 2020</span>
</div>
)}
{props.terms.includes('2020 Spring') && (
<div style={{ float: 'right' }}>
<Label circular color='teal' empty />
<span style={{ marginLeft: '6px' }}>Spring 2020</span>
</div>
)}
</div>
}
basic
position='bottom right'
/>
)}
</div>
)
}