Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • dev-old
  • dev-old-david
  • develop
  • lars-tests
  • master
  • master-old
  • topic/filesystem-fallbacks
  • topic/tank_connection
  • topic/tank_connection_david
  • user/equinox/docker
10 results

Target

Select target project
  • aura/engine
  • hermannschwaerzler/engine
  • sumpfralle/aura-engine
3 results
Select Git revision
  • 122-synchronized-ci
  • feat-use-docker-main-tag
  • fix-aura-sysuser
  • fix-broken-pipe-153
  • fix-docker-release
  • fix-push-latest-with-tag
  • fix-streamchannel-retries
  • gitlab-templates
  • improve-test-coverage-137
  • improve-test-coverage-143
  • main
  • orm-less-scheduling
  • remove-mailer
  • update-changelog-alpha3
  • virtual-timeslots-131
  • 1.0.0-alpha1
  • 1.0.0-alpha2
  • 1.0.0-alpha3
  • 1.0.0-alpha4
  • 1.0.0-alpha5
20 results
Show changes
Showing
with 676 additions and 0 deletions
<script>
import { onMount } from 'svelte';
export let apiUrl = "http://localhost:3333/api/v1";
let time = new Date();
let queryCurrent = "/clock";
let data;
let currentTrack = null;
let timeLeft;
// these automatically update when `time`
// changes, because of the `$:` prefix
$: hours = time.getHours();
$: minutes = time.getMinutes();
$: seconds = time.getSeconds();
data = fetchApi(queryCurrent);
onMount(() => {
const interval = setInterval(() => {
time = new Date();
timeLeft -= 1;
if (timeLeft <= 0 || data == null) {
currentTrack = null;
data = null;
data = fetchApi(queryCurrent);
}
}, 1000);
return () => {
clearInterval(interval);
};
});
async function fetchApi(query) {
let response = await fetch(apiUrl+query);
let data;
try {
data = await response.json();
} catch(e) {
console.log("Error while converting response to JSON!", e);
throw new Error(response.statusText);
}
if (response.ok) {
return data;
} else {
console.log("Error:", data);
throw new Error(data.message);
}
}
function setCurrentTrack(info) {
if (currentTrack == null && info != null && info.track != null) {
currentTrack = info;
let t = time - Date.parse(info.track_start);
t = parseInt(t/1000);
timeLeft = info.track.duration - t - 4;
}
return "";
}
function displayTitle(info) {
if (info != null && info.track != null) {
let artist = "";
if (info.track.artist != "")
artist = info.track.artist + " - ";
return artist + info.track.title;
}
return "";
}
function formatTime(seconds) {
if (seconds != null && Number.isInteger(seconds)) {
let d = new Date(null);
d.setSeconds(seconds);
let s;
if (seconds > 3600)
s = d.toISOString().substr(11, 8);
else
s = d.toISOString().substr(14, 5);
return s;
}
return "";
}
function displayShowName(show) {
let name = ""
if (show == null || show.name == null) {
name = '<span class="error">No show scheduled!</span>';
} else {
name = show.name;
}
return name;
}
function displayShowSchedule(schedule) {
let str = "";
if (schedule != null && schedule.schedule_start != null) {
let scheduleStart = ""
let scheduleEnd = "";
if (schedule.schedule_start != null) {
let scheduleStart = new Date(Date.parse(schedule.schedule_start));
scheduleStart = scheduleStart.toLocaleTimeString(navigator.language, {
hour: '2-digit',
minute:'2-digit'
});
str = "(" + scheduleStart;
}
if (schedule.schedule_end != null) {
scheduleEnd = new Date(Date.parse(schedule.schedule_end));
scheduleEnd = scheduleEnd.toLocaleTimeString(navigator.language, {
hour: '2-digit',
minute:'2-digit'
});
str = str + " - " + scheduleEnd + ")";
} else {
str += ")";
}
}
return str;
}
</script>
<style>
#studio-clock {
width: calc(100% - 200px);
margin:100px;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
border: 2px solid #333;
flex-direction: row;
}
#left-column {
width: 30%;
padding: 25px;
}
#right-column {
width: 70%;
padding: 25px;
}
#current-schedule,
#next-schedule {
margin: 0 0 40px 20px;
}
#track-list {
border: 2px solid #333;
margin: 20px 20px 40px 20px;
padding: 10px;
}
.play-icon,
.track-time-left {
margin: 12px;
}
.active {
color: green;
}
svg {
width: 100%;
height: 100%;
}
.clock-face {
stroke: #333;
fill: white;
}
.minor {
stroke: #999;
stroke-width: 0.5;
}
.major {
stroke: #333;
stroke-width: 1;
}
.hour {
stroke: #333;
}
.minute {
stroke: #666;
}
.second, .second-counterweight {
stroke: rgb(180,0,0);
}
.second-counterweight {
stroke-width: 3;
}
footer {
width: 100%;
text-align: center;
font-size: 0.8em;
color: gray;
}
</style>
<div id="studio-clock">
<div id="left-column" class="column">
<svg viewBox='-50 -50 100 100'>
<circle class='clock-face' r='48'/>
<!-- markers -->
{#each [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55] as minute}
<line
class='major'
y1='35'
y2='45'
transform='rotate({30 * minute})'
/>
{#each [1, 2, 3, 4] as offset}
<line
class='minor'
y1='42'
y2='45'
transform='rotate({6 * (minute + offset)})'
/>
{/each}
{/each}
<!-- hour hand -->
<line
class='hour'
y1='2'
y2='-20'
transform='rotate({30 * hours + minutes / 2})'
/>
<!-- minute hand -->
<line
class='minute'
y1='4'
y2='-30'
transform='rotate({6 * minutes + seconds / 10})'
/>
<!-- second hand -->
<g transform='rotate({6 * seconds})'>
<line class='second' y1='10' y2='-38'/>
<line class='second-counterweight' y1='10' y2='2'/>
</g>
</svg>
</div>
<div id="right-column" class="column">
{#await data}
<div class="spinner-border mt-5" role="status">
<span class="sr-only">Loading...</span>
</div>
{:then value}
{setCurrentTrack(value)}
<!-- <h2>&#9654; Playing</h2> -->
{#if value.current.show}
<div id="current-schedule">
<h1 class="schedule-title">{@html displayShowName(value.current.show)} {displayShowSchedule(value.current)}</h1>
<div class="schedule-details">
<b>Type:</b> {value.current.type}, <b>Host:</b> {value.current.host}</div>
</div>
<div id="track-list">
<div id="current-track">
<h2>
<span class="play-icon">&#9654;</span>
<span class="active track-title">{displayTitle(value)}</span>
<span class="track-time-left">({formatTime(timeLeft)})</span>
</h2>
</div>
</div>
<div id="next-schedule">
<h2 class="schedule-title">Next: {@html displayShowName(value.next.show)} {displayShowSchedule(value)}</h2>
<div class="schedule-details">
<b>Type:</b> {value.next.type}, <b>Host:</b> {value.next.host}
</div>
</div>
{/if}
{:catch error}
<p style="color:red">{error}</p>
{/await}
</div>
</div>
<footer>Studio Clock is powered by <a href="https://gitlab.servus.at/autoradio">Aura Engine</a></footer>
\ No newline at end of file
import StudioClock from './StudioClock.svelte';
const clock = new StudioClock({
target: document.body,
props: {
name: 'world'
}
});
export default clock;
\ No newline at end of file
/node_modules/
/public/build/
.DS_Store
# Aura Player
A collection of JavaScript components to integrate Aura to your Website.
Provided components:
- Track Service
## Requirements
Node 13
## Install
npn install
## Run
npm start
## Resources
* Svelte Docs - https://svelte.dev/docs
\ No newline at end of file
This diff is collapsed.
{
"name": "aura-player",
"version": "1.0.0",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^6.0.0",
"rollup": "^1.12.0",
"rollup-plugin-commonjs": "^10.0.0",
"rollup-plugin-livereload": "^1.0.0",
"rollup-plugin-svelte": "^5.0.3",
"rollup-plugin-terser": "^5.1.2",
"svelte": "^3.0.0"
},
"dependencies": {
"sirv-cli": "^0.4.4"
}
}
This diff is collapsed.
This diff is collapsed.
contrib/aura-player/public/favicon.png

3.05 KiB

html, body {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
color: #333;
margin: 0;
padding: 8px;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
a {
color: rgb(0,100,200);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:visited {
color: rgb(0,80,160);
}
label {
display: block;
}
input, button, select, textarea {
font-family: inherit;
font-size: inherit;
padding: 0.4em;
margin: 0 0 0.5em 0;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 2px;
}
input:disabled {
color: #ccc;
}
input[type="range"] {
height: 0;
}
button {
color: #333;
background-color: #f4f4f4;
outline: none;
}
button:disabled {
color: #999;
}
button:not(:disabled):active {
background-color: #ddd;
}
button:focus {
border-color: #666;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel="stylesheet" href="/bootstrap.css">
<!--<link rel='stylesheet' href='/global.css'>-->
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file — better for performance
css: css => {
css.write('public/build/bundle.css');
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration —
// consult the documentation for details:
// https://github.com/rollup/rollup-plugin-commonjs
resolve({
browser: true,
dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/')
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}
\ No newline at end of file
<script>
import TrackService from './TrackService.svelte';
let queryTrackservice = "trackservice";
let result;
async function getData(query) {
// FIXME Configure DataURL and Port
let response = await fetch(`http://localhost:3333/api/v1/${query}`);
let data = await response.json();
if (response.ok) {
return data;
} else {
throw new Error(data)
}
}
result = getData(queryTrackservice);
</script>
<div class="container mt-5">
<div class="row">
<div class="col-md"></div>
<div class="col-md-8 text-center">
<h1 class="display-4">Track Service</h1>
{#await result}
<div class="spinner-border mt-5" role="status">
<span class="sr-only">Loading...</span>
</div>
{:then value}
<TrackService data={value} />
{:catch error}
<p style="color:red">{error.message}</p>
{/await}
</div>
<div class="col-md"></div>
</div>
</div>
\ No newline at end of file
<style>
.card {
margin-bottom: 38px;
}
card.active-track {
border: 3px solid greenyellow;
}
</style>
<script>
import { fly } from 'svelte/transition';
export let data;
let currentDate = "";
function getDate(item) {
let track_date = "";
if (item.track_start != null)
track_date = item.track_start.split('T')[0];
if (currentDate != track_date) {
currentDate = track_date;
let date = new Date(currentDate);
let options = {
weekday: "long", year: "numeric", month: "short",
day: "numeric"
};
return date.toLocaleDateString("de-at", options);
} else {
return "";
}
}
function getTime(item) {
let date = new Date(item.track_start);
let options = {
hour: "2-digit", minute: "2-digit"
};
return date.toLocaleTimeString("de-at", options);
}
function isActive(item) {
if (item.track.duration != null && parseInt(item.track.duration) > 0) {
let startDate = new Date(item.track_start);
let endDate = new Date(startDate.getTime() + item.track.duration*1000);
let now = new Date();
if (startDate < now < endDate) {
return "active-track";
} else {
return "";
}
} else {
return "";
}
}
function printDuration(item) {
if (item.track.duration != null && parseInt(item.track.duration) > 0) {
return "("+item.track.duration+")";
} else {
return "";
}
}
</script>
{#each data as item}
<h4>{getDate(item)}</h4>
<div class="card mt-5 {isActive(item)}" transition:fly="{{ y: 150, duration: 500 }}">
<div class="card-body">
<h5 class="card-title"><b>{getTime(item)}</b> | {item.track.artist} - {item.track.title} {printDuration(item)}</h5>
</div>
</div>
{/each}
<footer>Track Service is powered by <a href="https://gitlab.servus.at/autoradio">Aura</a></footer>
\ No newline at end of file
import App from './App.svelte';
const app = new App({
target: document.body
});
export default app;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
}
\ No newline at end of file