forked from Github/frigate
Initial Recordings UI
This commit is contained in:
committed by
Blake Blackshear
parent
abbc608ee4
commit
5461308d30
@@ -66,7 +66,7 @@ export default function Button({
|
||||
|
||||
let classes = `whitespace-nowrap flex items-center space-x-1 ${className} ${ButtonTypes[type]} ${
|
||||
ButtonColors[disabled ? 'disabled' : color][type]
|
||||
} font-sans inline-flex font-bold uppercase text-xs px-2 py-2 rounded outline-none focus:outline-none ring-opacity-50 transition-shadow transition-colors ${
|
||||
} font-sans inline-flex font-bold uppercase text-xs px-1.5 md:px-2 py-2 rounded outline-none focus:outline-none ring-opacity-50 transition-shadow transition-colors ${
|
||||
disabled ? 'cursor-not-allowed' : 'focus:ring-2 cursor-pointer'
|
||||
}`;
|
||||
|
||||
|
||||
26
web/src/components/Calendar.jsx
Normal file
26
web/src/components/Calendar.jsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { h } from 'preact';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
export default function Calendar({ date, hours = 0, events = 0, selected = false }) {
|
||||
const bg = selected ? 'bg-blue-500 bg-opacity-80' : 'bg-gray-500';
|
||||
return (
|
||||
<div className="min-w-20 min-h-20 md:min-w-32 md:min-h-32 p-1.5 mb-1 font-medium text-xs md:text-base">
|
||||
<div className="w-20 md:w-32 flex-none rounded-lg text-center shadow-md">
|
||||
<div className="block rounded-lg overflow-hidden text-center text-black">
|
||||
<div className={`${bg} text-white py-0.5`}>{format(date, 'MMM yyyy')}</div>
|
||||
<div className="pt-0.5 bg-white">
|
||||
<span className="text-2xl md:text-5xl font-bold leading-tight">{format(date, 'd')}</span>
|
||||
</div>
|
||||
<div className="text-center bg-white pt-0.5">
|
||||
<span className="md:text-sm">{format(date, 'EEEE')}</span>
|
||||
</div>
|
||||
<div className="pb-0.5 border-l border-r border-b border-white text-center bg-white hidden md:block">
|
||||
<span className="md:text-xs leading-normal">
|
||||
{hours} hrs, {events} events
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
65
web/src/components/Carousel.jsx
Normal file
65
web/src/components/Carousel.jsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import { h, Component } from 'preact';
|
||||
import Flickity from 'flickity';
|
||||
import 'flickity/css/flickity.css';
|
||||
|
||||
export default class Carousel extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.carousel = null;
|
||||
this.flkty = null;
|
||||
}
|
||||
|
||||
create() {
|
||||
if (this.carousel) {
|
||||
this.flkty = new Flickity(this.carousel, this.props.options);
|
||||
|
||||
if (this.props.flickityRef) {
|
||||
this.props.flickityRef(this.flkty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.flkty) {
|
||||
this.flkty.destroy();
|
||||
this.flkty = null;
|
||||
this.carousel = null;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUpdate() {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.create();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.create();
|
||||
}
|
||||
|
||||
render(props) {
|
||||
return h(
|
||||
this.props.elementType,
|
||||
{
|
||||
className: this.props.className,
|
||||
ref: (c) => {
|
||||
this.carousel = c;
|
||||
},
|
||||
},
|
||||
this.props.children
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Carousel.defaultProps = {
|
||||
options: {},
|
||||
className: '',
|
||||
elementType: 'div',
|
||||
};
|
||||
51
web/src/components/VideoPlayer.jsx
Normal file
51
web/src/components/VideoPlayer.jsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { h, Component } from 'preact';
|
||||
import videojs from 'video.js';
|
||||
import 'videojs-playlist';
|
||||
import 'video.js/dist/video-js.css';
|
||||
|
||||
const defaultOptions = {
|
||||
controls: true,
|
||||
fluid: true,
|
||||
};
|
||||
|
||||
export default class VideoPlayer extends Component {
|
||||
componentDidMount() {
|
||||
const { options, onReady = () => {} } = this.props;
|
||||
const videoJsOptions = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
};
|
||||
const self = this;
|
||||
this.player = videojs(this.videoNode, videoJsOptions, function onPlayerReady() {
|
||||
onReady(this);
|
||||
this.on('error', () => {
|
||||
console.error('VIDEOJS: ERROR: currentSources:', this.currentSources());
|
||||
});
|
||||
this.on('play', () => {
|
||||
console.log('VIDEOJS: currentSources:', this.currentSources());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.player) {
|
||||
this.player.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style } = this.props;
|
||||
return (
|
||||
<div style={style}>
|
||||
<div data-vjs-player>
|
||||
<video playsinline ref={(node) => (this.videoNode = node)} className="video-js" />
|
||||
<div className="vjs-playlist" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user