add: Task Status

This commit is contained in:
Simon Hardt
2021-05-31 23:19:02 +02:00
parent 98fb1349a1
commit e12fbfa2aa
12 changed files with 1222 additions and 147 deletions

View File

@@ -8,6 +8,8 @@
#include <fstream>
#include <functional>
#include <soci/boost-optional.h>
#include <ctre.hpp>
#include <fmt/chrono.h>
#include <fmt/ostream.h>
@@ -30,7 +32,9 @@ void Api::RegisterServerHandles(httplib::Server& server)
server.Get("/api/files", std::bind_front(&Api::files, this));
server.Get("/api/file/([A-E0-9]+)", std::bind_front(&Api::file, this));
server.Get("/api/file/([A-F0-9]+)", std::bind_front(&Api::file, this));
server.Get("/api/status/([A-F0-9]+)", std::bind_front(&Api::status, this));
server.Options("/(.*)", [this](httplib::Request const& rq, httplib::Response& rp) {});
@@ -205,6 +209,70 @@ void Api::file(const httplib::Request& rq, httplib::Response& rs)
rs.set_content("File Not Found", "text/plain");
}
}
void Api::status(httplib::Request const& rq, httplib::Response& rs)
{
if (!rq.matches[1].matched)
{
rs.status = 404;
rs.set_content("Parameter error", "text/plain");
return;
}
std::string hash = rq.matches[1];
boost::optional<Task> data;
sql << "SELECT * FROM Tasks WHERE hash=:hash", soci::use(hash, "hash"), soci::into(data);
/*soci::rowset<Task> data = (sql.prepare << "SELECT * "
"FROM Tasks "
"WHERE hash=:hash ",
soci::use(hash, "hash"));*/
json response;
auto& status = response["status"];
if (data)
{
auto const& el = data.value();
status["name"] = fmt::format("Task {}", el.hash);
status["source"] = el.url;
status["status"] = magic_enum::enum_name(el.status);
status["status_id"] = static_cast<int>(el.status);
status["timestamp"] = el.timestamp;
status["task_file_type"] =
fmt::format("{}: {}", el.audio_only ? "Audio" : "Video", el.format.value_or("Auto"));
status["id"] = el.hash;
if (el.status == FileStatus::COMPLETE)
{
boost::optional<File> file_data;
sql << "SELECT * FROM Files WHERE hash=:hash", soci::use(hash, "hash"),
soci::into(file_data);
if (file_data)
{
auto const& file = file_data.value();
auto& file_status = status["file"];
file_status["timestamp"] = file.timestamp;
file_status["name"] = file.filename;
file_status["format"] =
fmt::format("{}: {}", el.audio_only ? "Audio" : "Video", file.format);
}
}
} else
{
rs.status = 404;
response["error"] = fmt::format("File '{}' not found!", hash);
}
rs.set_content(response.dump(), "application/json");
}
void Api::set_cross_headers(httplib::Response& rs)
{
rs.set_header("Access-Control-Allow-Origin", "*");

View File

@@ -18,6 +18,8 @@ public: // Endpoints
void files(httplib::Request const& rq, httplib::Response& rs);
void file(httplib::Request const& rq, httplib::Response& rs);
void status(httplib::Request const& rq, httplib::Response& rs);
void set_cross_headers(httplib::Response& rs);
};

View File

@@ -97,10 +97,11 @@ struct Task
inline std::ostream& operator<<(std::ostream& os, Task const& file)
{
return os << fmt::format("Task [{}][{}] url: {} ",
file.id,
return os << fmt::format("Task [{}] url: {} Audio: {} Format: {}",
magic_enum::enum_name(file.status),
file.url);
file.url,
file.audio_only,
file.format.value_or("Auto"));
}
namespace soci

View File

@@ -2,9 +2,13 @@ POST 127.0.0.1:80/api/add
Content-Type: text/json
{
"url": "https://www.youtube.com/watch?v=ZWIwLMpgcbI"
"url": "https://www.youtube.com/watch?v=izc1XLbU5Vk"
}
###
GET 127.0.0.1:80/api/queue
GET 127.0.0.1:80/api/files
###
GET 127.0.0.1:80/api/status/C3F953D7

View File

@@ -7,8 +7,10 @@
"dependencies": {
"direct": {
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
"andrewMacmurray/elm-delay": "4.0.0",
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/file": "1.0.5",
"elm/html": "1.0.0",
"elm/http": "2.0.0",
"elm/json": "1.1.3",
@@ -17,7 +19,6 @@
},
"indirect": {
"elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/time": "1.0.0",
"elm/virtual-dom": "1.0.2"
}

View File

@@ -4598,7 +4598,185 @@ function _Url_percentDecode(string)
{
return $elm$core$Maybe$Nothing;
}
}var $author$project$Main$LinkClicked = function (a) {
}
// DECODER
var _File_decoder = _Json_decodePrim(function(value) {
// NOTE: checks if `File` exists in case this is run on node
return (typeof File !== 'undefined' && value instanceof File)
? $elm$core$Result$Ok(value)
: _Json_expecting('a FILE', value);
});
// METADATA
function _File_name(file) { return file.name; }
function _File_mime(file) { return file.type; }
function _File_size(file) { return file.size; }
function _File_lastModified(file)
{
return $elm$time$Time$millisToPosix(file.lastModified);
}
// DOWNLOAD
var _File_downloadNode;
function _File_getDownloadNode()
{
return _File_downloadNode || (_File_downloadNode = document.createElement('a'));
}
var _File_download = F3(function(name, mime, content)
{
return _Scheduler_binding(function(callback)
{
var blob = new Blob([content], {type: mime});
// for IE10+
if (navigator.msSaveOrOpenBlob)
{
navigator.msSaveOrOpenBlob(blob, name);
return;
}
// for HTML5
var node = _File_getDownloadNode();
var objectUrl = URL.createObjectURL(blob);
node.href = objectUrl;
node.download = name;
_File_click(node);
URL.revokeObjectURL(objectUrl);
});
});
function _File_downloadUrl(href)
{
return _Scheduler_binding(function(callback)
{
var node = _File_getDownloadNode();
node.href = href;
node.download = '';
node.origin === location.origin || (node.target = '_blank');
_File_click(node);
});
}
// IE COMPATIBILITY
function _File_makeBytesSafeForInternetExplorer(bytes)
{
// only needed by IE10 and IE11 to fix https://github.com/elm/file/issues/10
// all other browsers can just run `new Blob([bytes])` directly with no problem
//
return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
}
function _File_click(node)
{
// only needed by IE10 and IE11 to fix https://github.com/elm/file/issues/11
// all other browsers have MouseEvent and do not need this conditional stuff
//
if (typeof MouseEvent === 'function')
{
node.dispatchEvent(new MouseEvent('click'));
}
else
{
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
document.body.appendChild(node);
node.dispatchEvent(event);
document.body.removeChild(node);
}
}
// UPLOAD
var _File_node;
function _File_uploadOne(mimes)
{
return _Scheduler_binding(function(callback)
{
_File_node = document.createElement('input');
_File_node.type = 'file';
_File_node.accept = A2($elm$core$String$join, ',', mimes);
_File_node.addEventListener('change', function(event)
{
callback(_Scheduler_succeed(event.target.files[0]));
});
_File_click(_File_node);
});
}
function _File_uploadOneOrMore(mimes)
{
return _Scheduler_binding(function(callback)
{
_File_node = document.createElement('input');
_File_node.type = 'file';
_File_node.multiple = true;
_File_node.accept = A2($elm$core$String$join, ',', mimes);
_File_node.addEventListener('change', function(event)
{
var elmFiles = _List_fromArray(event.target.files);
callback(_Scheduler_succeed(_Utils_Tuple2(elmFiles.a, elmFiles.b)));
});
_File_click(_File_node);
});
}
// CONTENT
function _File_toString(blob)
{
return _Scheduler_binding(function(callback)
{
var reader = new FileReader();
reader.addEventListener('loadend', function() {
callback(_Scheduler_succeed(reader.result));
});
reader.readAsText(blob);
return function() { reader.abort(); };
});
}
function _File_toBytes(blob)
{
return _Scheduler_binding(function(callback)
{
var reader = new FileReader();
reader.addEventListener('loadend', function() {
callback(_Scheduler_succeed(new DataView(reader.result)));
});
reader.readAsArrayBuffer(blob);
return function() { reader.abort(); };
});
}
function _File_toUrl(blob)
{
return _Scheduler_binding(function(callback)
{
var reader = new FileReader();
reader.addEventListener('loadend', function() {
callback(_Scheduler_succeed(reader.result));
});
reader.readAsDataURL(blob);
return function() { reader.abort(); };
});
}
var $author$project$Main$LinkClicked = function (a) {
return {$: 'LinkClicked', a: a};
};
var $author$project$Main$UrlChanged = function (a) {
@@ -5399,6 +5577,9 @@ var $author$project$Main$FilesPageMsg = function (a) {
var $author$project$Main$HomePageMsg = function (a) {
return {$: 'HomePageMsg', a: a};
};
var $author$project$Main$StatusPageMsg = function (a) {
return {$: 'StatusPageMsg', a: a};
};
var $mdgriffith$elm_ui$Internal$Model$Unkeyed = function (a) {
return {$: 'Unkeyed', a: a};
};
@@ -11998,18 +12179,6 @@ var $author$project$MainPage$audioOnlyCheckbox = function (isChecked) {
$mdgriffith$elm_ui$Element$text('Video'))
])));
};
var $mdgriffith$elm_ui$Internal$Model$Below = {$: 'Below'};
var $mdgriffith$elm_ui$Element$createNearby = F2(
function (loc, element) {
if (element.$ === 'Empty') {
return $mdgriffith$elm_ui$Internal$Model$NoAttribute;
} else {
return A2($mdgriffith$elm_ui$Internal$Model$Nearby, loc, element);
}
});
var $mdgriffith$elm_ui$Element$below = function (element) {
return A2($mdgriffith$elm_ui$Element$createNearby, $mdgriffith$elm_ui$Internal$Model$Below, element);
};
var $mdgriffith$elm_ui$Internal$Model$Button = {$: 'Button'};
var $elm$json$Json$Encode$bool = _Json_wrap;
var $elm$html$Html$Attributes$boolProperty = F2(
@@ -12422,6 +12591,8 @@ var $author$project$MainPage$formatButton = F3(
$mdgriffith$elm_ui$Element$Border$roundEach(corners),
$mdgriffith$elm_ui$Element$Border$widthEach(borders),
$mdgriffith$elm_ui$Element$Border$color($author$project$Color$color.blue),
$mdgriffith$elm_ui$Element$width(
$mdgriffith$elm_ui$Element$px(80)),
$mdgriffith$elm_ui$Element$Background$color(
_Utils_eq(state, $mdgriffith$elm_ui$Element$Input$Selected) ? $author$project$Color$color.lightBlue : $author$project$Color$color.white)
]),
@@ -12452,7 +12623,7 @@ var $author$project$MainPage$videoFormatName = function (format) {
case 'OGG':
return 'ogg';
default:
return 'wav';
return 'webm';
}
};
var $author$project$MainPage$formatName = function (format) {
@@ -12497,16 +12668,6 @@ var $mdgriffith$elm_ui$Element$Input$HiddenLabel = function (a) {
var $mdgriffith$elm_ui$Element$Input$labelHidden = $mdgriffith$elm_ui$Element$Input$HiddenLabel;
var $mdgriffith$elm_ui$Element$Input$OnLeft = {$: 'OnLeft'};
var $mdgriffith$elm_ui$Element$Input$labelLeft = $mdgriffith$elm_ui$Element$Input$Label($mdgriffith$elm_ui$Element$Input$OnLeft);
var $mdgriffith$elm_ui$Internal$Model$MoveY = function (a) {
return {$: 'MoveY', a: a};
};
var $mdgriffith$elm_ui$Internal$Flag$moveY = $mdgriffith$elm_ui$Internal$Flag$flag(26);
var $mdgriffith$elm_ui$Element$moveDown = function (y) {
return A2(
$mdgriffith$elm_ui$Internal$Model$TransformComponent,
$mdgriffith$elm_ui$Internal$Flag$moveY,
$mdgriffith$elm_ui$Internal$Model$MoveY(y));
};
var $mdgriffith$elm_ui$Element$paddingXY = F2(
function (x, y) {
if (_Utils_eq(x, y)) {
@@ -12856,9 +13017,21 @@ var $mdgriffith$elm_ui$Element$Input$autofill = A2(
$mdgriffith$elm_ui$Internal$Model$Attr,
$elm$html$Html$Attributes$attribute('autocomplete'));
var $mdgriffith$elm_ui$Internal$Model$Behind = {$: 'Behind'};
var $mdgriffith$elm_ui$Element$createNearby = F2(
function (loc, element) {
if (element.$ === 'Empty') {
return $mdgriffith$elm_ui$Internal$Model$NoAttribute;
} else {
return A2($mdgriffith$elm_ui$Internal$Model$Nearby, loc, element);
}
});
var $mdgriffith$elm_ui$Element$behindContent = function (element) {
return A2($mdgriffith$elm_ui$Element$createNearby, $mdgriffith$elm_ui$Internal$Model$Behind, element);
};
var $mdgriffith$elm_ui$Internal$Model$MoveY = function (a) {
return {$: 'MoveY', a: a};
};
var $mdgriffith$elm_ui$Internal$Flag$moveY = $mdgriffith$elm_ui$Internal$Flag$flag(26);
var $mdgriffith$elm_ui$Element$moveUp = function (y) {
return A2(
$mdgriffith$elm_ui$Internal$Model$TransformComponent,
@@ -13609,18 +13782,7 @@ var $author$project$MainPage$view = function (model) {
$mdgriffith$elm_ui$Element$Input$text,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$spacing(12),
$mdgriffith$elm_ui$Element$below(
A2(
$mdgriffith$elm_ui$Element$el,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Font$color($author$project$Color$color.red),
$mdgriffith$elm_ui$Element$Font$size(14),
$mdgriffith$elm_ui$Element$alignRight,
$mdgriffith$elm_ui$Element$moveDown(6)
]),
$mdgriffith$elm_ui$Element$text('This one is wrong')))
$mdgriffith$elm_ui$Element$spacing(12)
]),
{
label: A2(
@@ -13747,6 +13909,237 @@ var $author$project$MainPage$view = function (model) {
})
]));
};
var $author$project$Status$Download = function (a) {
return {$: 'Download', a: a};
};
var $mdgriffith$elm_ui$Internal$Flag$fontWeight = $mdgriffith$elm_ui$Internal$Flag$flag(13);
var $mdgriffith$elm_ui$Element$Font$bold = A2($mdgriffith$elm_ui$Internal$Model$Class, $mdgriffith$elm_ui$Internal$Flag$fontWeight, $mdgriffith$elm_ui$Internal$Style$classes.bold);
var $author$project$Status$cardShadow = $mdgriffith$elm_ui$Element$Border$shadow(
{
blur: 8,
color: A4($mdgriffith$elm_ui$Element$rgba, 0, 0, 0, 0.2),
offset: _Utils_Tuple2(0, 4),
size: 4
});
var $author$project$Status$cardShadowOver = $mdgriffith$elm_ui$Element$Border$shadow(
{
blur: 16,
color: A4($mdgriffith$elm_ui$Element$rgba, 0, 0, 0, 0.2),
offset: _Utils_Tuple2(0, 4),
size: 8
});
var $author$project$Status$card = F2(
function (attr, element) {
return A2(
$mdgriffith$elm_ui$Element$el,
$elm$core$List$concat(
_List_fromArray(
[
attr,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Border$rounded(15),
$author$project$Status$cardShadow,
$mdgriffith$elm_ui$Element$mouseOver(
_List_fromArray(
[$author$project$Status$cardShadowOver])),
$mdgriffith$elm_ui$Element$padding(20)
])
])),
element);
});
var $author$project$Status$innerCard = F2(
function (attr, element) {
return A2(
$mdgriffith$elm_ui$Element$el,
$elm$core$List$concat(
_List_fromArray(
[
attr,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Border$roundEach(
{bottomLeft: 15, bottomRight: 15, topLeft: 15, topRight: 15}),
$mdgriffith$elm_ui$Element$padding(5)
])
])),
element);
});
var $elm$html$Html$Attributes$rel = _VirtualDom_attribute('rel');
var $mdgriffith$elm_ui$Element$link = F2(
function (attrs, _v0) {
var url = _v0.url;
var label = _v0.label;
return A4(
$mdgriffith$elm_ui$Internal$Model$element,
$mdgriffith$elm_ui$Internal$Model$asEl,
$mdgriffith$elm_ui$Internal$Model$NodeName('a'),
A2(
$elm$core$List$cons,
$mdgriffith$elm_ui$Internal$Model$Attr(
$elm$html$Html$Attributes$href(url)),
A2(
$elm$core$List$cons,
$mdgriffith$elm_ui$Internal$Model$Attr(
$elm$html$Html$Attributes$rel('noopener noreferrer')),
A2(
$elm$core$List$cons,
$mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$shrink),
A2(
$elm$core$List$cons,
$mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink),
A2(
$elm$core$List$cons,
$mdgriffith$elm_ui$Internal$Model$htmlClass($mdgriffith$elm_ui$Internal$Style$classes.contentCenterX + (' ' + ($mdgriffith$elm_ui$Internal$Style$classes.contentCenterY + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.link)))),
attrs))))),
$mdgriffith$elm_ui$Internal$Model$Unkeyed(
_List_fromArray(
[label])));
});
var $mdgriffith$elm_ui$Element$Font$underline = $mdgriffith$elm_ui$Internal$Model$htmlClass($mdgriffith$elm_ui$Internal$Style$classes.underline);
var $author$project$Status$statusView = function (status) {
return A2(
$author$project$Status$card,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill),
$mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink)
]),
A2(
$mdgriffith$elm_ui$Element$column,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill)
]),
_List_fromArray(
[
A2(
$mdgriffith$elm_ui$Element$row,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill),
$mdgriffith$elm_ui$Element$height(
$mdgriffith$elm_ui$Element$px(40))
]),
_List_fromArray(
[
A2(
$mdgriffith$elm_ui$Element$el,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Font$size(28),
$mdgriffith$elm_ui$Element$alignLeft
]),
$mdgriffith$elm_ui$Element$text(status.name)),
A2(
$mdgriffith$elm_ui$Element$el,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Font$size(28),
$mdgriffith$elm_ui$Element$alignRight
]),
$mdgriffith$elm_ui$Element$text(
$elm$core$String$concat(
_List_fromArray(
['[', status.status, ']']))))
])),
A2(
$mdgriffith$elm_ui$Element$link,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Font$bold,
$mdgriffith$elm_ui$Element$Font$underline,
$mdgriffith$elm_ui$Element$Font$color($author$project$Color$color.blue),
$mdgriffith$elm_ui$Element$Font$size(16),
$mdgriffith$elm_ui$Element$padding(2)
]),
{
label: $mdgriffith$elm_ui$Element$text(status.source),
url: status.source
}),
A2(
$mdgriffith$elm_ui$Element$el,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$height(
$mdgriffith$elm_ui$Element$px(10))
]),
$mdgriffith$elm_ui$Element$none),
function () {
var _v0 = status.file;
if (_v0.$ === 'Just') {
var file = _v0.a;
return A2(
$author$project$Status$innerCard,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill),
$mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink),
$mdgriffith$elm_ui$Element$Background$color($author$project$Color$color.grey)
]),
A2(
$mdgriffith$elm_ui$Element$row,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill),
$mdgriffith$elm_ui$Element$spacing(20)
]),
_List_fromArray(
[
A2(
$mdgriffith$elm_ui$Element$Input$button,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Background$color($author$project$Color$color.blue),
$mdgriffith$elm_ui$Element$Font$color($author$project$Color$color.white),
$mdgriffith$elm_ui$Element$Border$color($author$project$Color$color.red),
A2($mdgriffith$elm_ui$Element$paddingXY, 32, 16),
$mdgriffith$elm_ui$Element$Border$rounded(15)
]),
{
label: $mdgriffith$elm_ui$Element$text('Download'),
onPress: $elm$core$Maybe$Just(
$author$project$Status$Download(status.id))
}),
A2(
$mdgriffith$elm_ui$Element$el,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$Font$size(16)
]),
$mdgriffith$elm_ui$Element$text(file.filename))
])));
} else {
return $mdgriffith$elm_ui$Element$none;
}
}()
])));
};
var $author$project$Status$view = function (model) {
return A2(
$mdgriffith$elm_ui$Element$column,
_List_fromArray(
[
$mdgriffith$elm_ui$Element$width(
$mdgriffith$elm_ui$Element$px(800)),
$mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink),
$mdgriffith$elm_ui$Element$centerX,
$mdgriffith$elm_ui$Element$centerY,
$mdgriffith$elm_ui$Element$spacing(36)
]),
_List_fromArray(
[
function () {
var _v0 = model.status;
if (_v0.$ === 'Just') {
var status = _v0.a;
return $author$project$Status$statusView(status);
} else {
return $mdgriffith$elm_ui$Element$text('Test');
}
}()
]));
};
var $author$project$Main$view = function (model) {
return A2(
$mdgriffith$elm_ui$Element$layout,
@@ -13769,6 +14162,12 @@ var $author$project$Main$view = function (model) {
$mdgriffith$elm_ui$Element$map,
$author$project$Main$FilesPageMsg,
$author$project$Files$view(pageModel));
case 'StatusPage':
var pageModel = _v0.a;
return A2(
$mdgriffith$elm_ui$Element$map,
$author$project$Main$StatusPageMsg,
$author$project$Status$view(pageModel));
default:
return A2(
$mdgriffith$elm_ui$Element$el,
@@ -13797,11 +14196,21 @@ var $author$project$Main$FilesPage = function (a) {
var $author$project$Main$Home = function (a) {
return {$: 'Home', a: a};
};
var $author$project$Main$StatusPage = function (a) {
return {$: 'StatusPage', a: a};
};
var $elm$core$Platform$Cmd$batch = _Platform_batch;
var $author$project$Files$initModel = {error: $elm$core$Maybe$Nothing, files: _List_Nil, filter: ''};
var $author$project$Files$QueryRequestResult = function (a) {
return {$: 'QueryRequestResult', a: a};
};
var $author$project$Globals$api = 'http://127.0.0.1/api/';
var $author$project$Globals$apiEndpoint = function (path) {
return $elm$core$String$concat(
_List_fromArray(
[$author$project$Globals$api, path]));
};
var $author$project$Globals$apiFiles = $author$project$Globals$apiEndpoint('files');
var $elm$json$Json$Decode$decodeString = _Json_runOnString;
var $elm$http$Http$BadStatus_ = F2(
function (a, b) {
@@ -14475,9 +14884,21 @@ var $author$project$Files$queueDecoder = A3(
var $author$project$Files$queryFiles = $elm$http$Http$get(
{
expect: A2($elm$http$Http$expectJson, $author$project$Files$QueryRequestResult, $author$project$Files$queueDecoder),
url: 'http://127.0.0.1/api/files'
url: $author$project$Globals$apiFiles
});
var $author$project$Files$init = _Utils_Tuple2($author$project$Files$initModel, $author$project$Files$queryFiles);
var $author$project$Status$Reload = {$: 'Reload'};
var $author$project$Status$send = function (msg) {
return A2(
$elm$core$Task$perform,
$elm$core$Basics$identity,
$elm$core$Task$succeed(msg));
};
var $author$project$Status$init = function (file_id) {
return _Utils_Tuple2(
{file_id: file_id, status: $elm$core$Maybe$Nothing},
$author$project$Status$send($author$project$Status$Reload));
};
var $author$project$MainPage$initModel = {
form: {audio_only: false, format: $author$project$MainPage$Auto, url: ''}
};
@@ -14498,13 +14919,21 @@ var $author$project$Main$initCurrentPage = function (_v0) {
return _Utils_Tuple2(
$author$project$Main$Home(pageModel),
A2($elm$core$Platform$Cmd$map, $author$project$Main$HomePageMsg, pageCmd));
default:
case 'Files':
var _v4 = $author$project$Files$init;
var pageModel = _v4.a;
var pageCmd = _v4.b;
return _Utils_Tuple2(
$author$project$Main$FilesPage(pageModel),
A2($elm$core$Platform$Cmd$map, $author$project$Main$FilesPageMsg, pageCmd));
default:
var file = _v2.a;
var _v5 = $author$project$Status$init(file);
var pageModel = _v5.a;
var pageCmd = _v5.b;
return _Utils_Tuple2(
$author$project$Main$StatusPage(pageModel),
A2($elm$core$Platform$Cmd$map, $author$project$Main$StatusPageMsg, pageCmd));
}
}();
var currentPage = _v1.a;
@@ -14520,6 +14949,9 @@ var $author$project$Main$initCurrentPage = function (_v0) {
var $author$project$Route$NotFound = {$: 'NotFound'};
var $author$project$Route$Files = {$: 'Files'};
var $author$project$Route$Home = {$: 'Home'};
var $author$project$Route$Status = function (a) {
return {$: 'Status', a: a};
};
var $elm$url$Url$Parser$Parser = function (a) {
return {$: 'Parser', a: a};
};
@@ -14597,6 +15029,52 @@ var $elm$url$Url$Parser$s = function (str) {
}
});
};
var $elm$url$Url$Parser$slash = F2(
function (_v0, _v1) {
var parseBefore = _v0.a;
var parseAfter = _v1.a;
return $elm$url$Url$Parser$Parser(
function (state) {
return A2(
$elm$core$List$concatMap,
parseAfter,
parseBefore(state));
});
});
var $elm$url$Url$Parser$custom = F2(
function (tipe, stringToSomething) {
return $elm$url$Url$Parser$Parser(
function (_v0) {
var visited = _v0.visited;
var unvisited = _v0.unvisited;
var params = _v0.params;
var frag = _v0.frag;
var value = _v0.value;
if (!unvisited.b) {
return _List_Nil;
} else {
var next = unvisited.a;
var rest = unvisited.b;
var _v2 = stringToSomething(next);
if (_v2.$ === 'Just') {
var nextValue = _v2.a;
return _List_fromArray(
[
A5(
$elm$url$Url$Parser$State,
A2($elm$core$List$cons, next, visited),
rest,
params,
frag,
value(nextValue))
]);
} else {
return _List_Nil;
}
}
});
});
var $elm$url$Url$Parser$string = A2($elm$url$Url$Parser$custom, 'STRING', $elm$core$Maybe$Just);
var $elm$url$Url$Parser$top = $elm$url$Url$Parser$Parser(
function (state) {
return _List_fromArray(
@@ -14609,7 +15087,14 @@ var $author$project$Route$matchRoute = $elm$url$Url$Parser$oneOf(
A2(
$elm$url$Url$Parser$map,
$author$project$Route$Files,
$elm$url$Url$Parser$s('files'))
$elm$url$Url$Parser$s('files')),
A2(
$elm$url$Url$Parser$map,
$author$project$Route$Status,
A2(
$elm$url$Url$Parser$slash,
$elm$url$Url$Parser$s('status'),
$elm$url$Url$Parser$string))
]));
var $elm$url$Url$Parser$getFirstMatch = function (states) {
getFirstMatch:
@@ -14838,8 +15323,8 @@ var $author$project$MainPage$formDecoder = A3(
$elm$json$Json$Decode$string,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'id',
$elm$json$Json$Decode$int,
'file_id',
$elm$json$Json$Decode$string,
$elm$json$Json$Decode$succeed($author$project$MainPage$PostFormResponse)));
var $author$project$MainPage$formPostEncoder = function (form) {
return $elm$json$Json$Encode$object(
@@ -14877,8 +15362,10 @@ var $elm$http$Http$post = function (r) {
return $elm$http$Http$request(
{body: r.body, expect: r.expect, headers: _List_Nil, method: 'POST', timeout: $elm$core$Maybe$Nothing, tracker: $elm$core$Maybe$Nothing, url: r.url});
};
var $author$project$MainPage$update = F2(
function (msg, model) {
var $author$project$MainPage$update = F3(
function (navKey, msg, model) {
_v0$5:
while (true) {
switch (msg.$) {
case 'UpdateForm':
var new_form = msg.a;
@@ -14910,7 +15397,7 @@ var $author$project$MainPage$update = F2(
$elm$core$Platform$Cmd$none);
case 'PostForm':
var form = msg.a;
return _Utils_Tuple2(
return (!$elm$core$String$isEmpty(form.url)) ? _Utils_Tuple2(
model,
$elm$http$Http$post(
{
@@ -14918,22 +15405,224 @@ var $author$project$MainPage$update = F2(
$author$project$MainPage$formPostEncoder(form)),
expect: A2($elm$http$Http$expectJson, $author$project$MainPage$PostResult, $author$project$MainPage$formDecoder),
url: 'http://127.0.0.1/api/add'
}));
})) : _Utils_Tuple2(model, $elm$core$Platform$Cmd$none);
case 'PostResult':
if (msg.a.$ === 'Ok') {
var data = msg.a.a;
return _Utils_Tuple2(
model,
A2(
$elm$browser$Browser$Navigation$pushUrl,
navKey,
$elm$core$String$concat(
_List_fromArray(
['/status/', data.id]))));
} else {
break _v0$5;
}
default:
break _v0$5;
}
}
return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none);
});
var $elm$core$Process$sleep = _Process_sleep;
var $andrewMacmurray$elm_delay$Delay$after = F2(
function (time, msg) {
return A2(
$elm$core$Task$perform,
$elm$core$Basics$always(msg),
$elm$core$Process$sleep(time));
});
var $author$project$Globals$apiDownloadFile = function (id) {
return $elm$core$String$concat(
_List_fromArray(
[
$author$project$Globals$apiEndpoint('file/'),
id
]));
};
var $author$project$Status$StatusRequestResult = function (a) {
return {$: 'StatusRequestResult', a: a};
};
var $author$project$Globals$apiStatus = function (id) {
return $elm$core$String$concat(
_List_fromArray(
[
$author$project$Globals$apiEndpoint('status/'),
id
]));
};
var $author$project$Status$StatusResponse = function (status) {
return {status: status};
};
var $author$project$Status$Status = F8(
function (file, name, source, status, status_id, format, timestamp, id) {
return {file: file, format: format, id: id, name: name, source: source, status: status, status_id: status_id, timestamp: timestamp};
});
var $author$project$Status$File = F3(
function (format, filename, timestamp) {
return {filename: filename, format: format, timestamp: timestamp};
});
var $author$project$Status$fileDecoder = A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'timestamp',
$elm$json$Json$Decode$int,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'name',
$elm$json$Json$Decode$string,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'format',
$elm$json$Json$Decode$string,
$elm$json$Json$Decode$succeed($author$project$Status$File))));
var $elm$json$Json$Decode$decodeValue = _Json_run;
var $elm$json$Json$Decode$null = _Json_decodeNull;
var $elm$json$Json$Decode$oneOf = _Json_oneOf;
var $elm$json$Json$Decode$value = _Json_decodeValue;
var $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optionalDecoder = F3(
function (pathDecoder, valDecoder, fallback) {
var nullOr = function (decoder) {
return $elm$json$Json$Decode$oneOf(
_List_fromArray(
[
decoder,
$elm$json$Json$Decode$null(fallback)
]));
};
var handleResult = function (input) {
var _v0 = A2($elm$json$Json$Decode$decodeValue, pathDecoder, input);
if (_v0.$ === 'Ok') {
var rawValue = _v0.a;
var _v1 = A2(
$elm$json$Json$Decode$decodeValue,
nullOr(valDecoder),
rawValue);
if (_v1.$ === 'Ok') {
var finalResult = _v1.a;
return $elm$json$Json$Decode$succeed(finalResult);
} else {
var finalErr = _v1.a;
return $elm$json$Json$Decode$fail(
$elm$json$Json$Decode$errorToString(finalErr));
}
} else {
return $elm$json$Json$Decode$succeed(fallback);
}
};
return A2($elm$json$Json$Decode$andThen, handleResult, $elm$json$Json$Decode$value);
});
var $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optional = F4(
function (key, valDecoder, fallback, decoder) {
return A2(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$custom,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optionalDecoder,
A2($elm$json$Json$Decode$field, key, $elm$json$Json$Decode$value),
valDecoder,
fallback),
decoder);
});
var $author$project$Status$statusDecoder = A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'id',
$elm$json$Json$Decode$string,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'timestamp',
$elm$json$Json$Decode$int,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'task_file_type',
$elm$json$Json$Decode$string,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'status_id',
$elm$json$Json$Decode$int,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'status',
$elm$json$Json$Decode$string,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'source',
$elm$json$Json$Decode$string,
A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'name',
$elm$json$Json$Decode$string,
A4(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optional,
'file',
A2($elm$json$Json$Decode$map, $elm$core$Maybe$Just, $author$project$Status$fileDecoder),
$elm$core$Maybe$Nothing,
$elm$json$Json$Decode$succeed($author$project$Status$Status)))))))));
var $author$project$Status$statusResponseDecoder = A3(
$NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required,
'status',
$author$project$Status$statusDecoder,
$elm$json$Json$Decode$succeed($author$project$Status$StatusResponse));
var $author$project$Status$queryStatus = function (id) {
return $elm$http$Http$get(
{
expect: A2($elm$http$Http$expectJson, $author$project$Status$StatusRequestResult, $author$project$Status$statusResponseDecoder),
url: $author$project$Globals$apiStatus(id)
});
};
var $elm$time$Time$Posix = function (a) {
return {$: 'Posix', a: a};
};
var $elm$time$Time$millisToPosix = $elm$time$Time$Posix;
var $elm$file$File$Download$url = function (href) {
return A2(
$elm$core$Task$perform,
$elm$core$Basics$never,
_File_downloadUrl(href));
};
var $author$project$Status$update = F2(
function (msg, model) {
switch (msg.$) {
case 'Reload':
return _Utils_Tuple2(
model,
$author$project$Status$queryStatus(model.file_id));
case 'StatusRequestResult':
if (msg.a.$ === 'Ok') {
var res = msg.a.a;
return _Utils_Tuple2(
_Utils_update(
model,
{
status: $elm$core$Maybe$Just(res.status)
}),
A2($andrewMacmurray$elm_delay$Delay$after, 1000, $author$project$Status$Reload));
} else {
return _Utils_Tuple2(
_Utils_update(
model,
{status: $elm$core$Maybe$Nothing}),
$elm$core$Platform$Cmd$none);
}
default:
var file_id = msg.a;
return _Utils_Tuple2(
model,
$elm$file$File$Download$url(
$author$project$Globals$apiDownloadFile(file_id)));
}
});
var $author$project$Main$update = F2(
function (msg, model) {
var _v0 = _Utils_Tuple2(msg, model.page);
_v0$4:
_v0$5:
while (true) {
switch (_v0.a.$) {
case 'HomePageMsg':
if (_v0.b.$ === 'Home') {
var subMsg = _v0.a.a;
var pageModel = _v0.b.a;
var _v1 = A2($author$project$MainPage$update, subMsg, pageModel);
var _v1 = A3($author$project$MainPage$update, model.navKey, subMsg, pageModel);
var updatePageModel = _v1.a;
var updateCmd = _v1.b;
return _Utils_Tuple2(
@@ -14944,7 +15633,7 @@ var $author$project$Main$update = F2(
}),
A2($elm$core$Platform$Cmd$map, $author$project$Main$HomePageMsg, updateCmd));
} else {
break _v0$4;
break _v0$5;
}
case 'FilesPageMsg':
if (_v0.b.$ === 'FilesPage') {
@@ -14961,7 +15650,24 @@ var $author$project$Main$update = F2(
}),
A2($elm$core$Platform$Cmd$map, $author$project$Main$FilesPageMsg, updateCmd));
} else {
break _v0$4;
break _v0$5;
}
case 'StatusPageMsg':
if (_v0.b.$ === 'StatusPage') {
var subMsg = _v0.a.a;
var pageModel = _v0.b.a;
var _v3 = A2($author$project$Status$update, subMsg, pageModel);
var updatePageModel = _v3.a;
var updateCmd = _v3.b;
return _Utils_Tuple2(
_Utils_update(
model,
{
page: $author$project$Main$StatusPage(updatePageModel)
}),
A2($elm$core$Platform$Cmd$map, $author$project$Main$StatusPageMsg, updateCmd));
} else {
break _v0$5;
}
case 'LinkClicked':
var urlRequest = _v0.a.a;

View File

@@ -2,15 +2,13 @@ module Files exposing (..)
import Debug exposing (toString)
import Element exposing (..)
import Element.Background as Background
import Element.Border as Border
import Element.Font as Font
import Element.Input as Input
import Element.Region as Region
import Globals exposing (apiFiles)
import Http
import Json.Decode exposing (Decoder, int, list, string, succeed)
import Json.Decode.Pipeline exposing (required)
import String exposing (left)
type alias File =
@@ -100,7 +98,7 @@ update msg model =
queryFiles : Cmd Msg
queryFiles =
Http.get
{ url = "http://127.0.0.1/api/files"
{ url = apiFiles
, expect = Http.expectJson QueryRequestResult queueDecoder
}

View File

@@ -0,0 +1,21 @@
module Globals exposing (..)
api : String
api =
"http://127.0.0.1/api/"
apiEndpoint : String -> String
apiEndpoint path =
String.concat [ api, path ]
apiStatus : String -> String
apiStatus id = String.concat [apiEndpoint "status/", id]
apiDownloadFile : String -> String
apiDownloadFile id = String.concat [apiEndpoint "file/", id]
apiFiles : String
apiFiles = apiEndpoint "files"

View File

@@ -8,7 +8,8 @@ import Element.Region as Region
import Files
import Html exposing (Html)
import MainPage
import Route exposing (Route)
import Route exposing (Route(..))
import Status
import Url exposing (Url)
@@ -23,12 +24,7 @@ type Page
= NotFound
| Home MainPage.Model
| FilesPage Files.Model
--initModel : Model
--initModel =
-- PageMain MainPage.initModel
| StatusPage Status.Model
init : () -> Url -> Nav.Key -> ( Model, Cmd Msg )
@@ -64,6 +60,13 @@ initCurrentPage ( model, existingCmds ) =
Files.init
in
( FilesPage pageModel, Cmd.map FilesPageMsg pageCmd )
Route.Status file ->
let
( pageModel, pageCmd ) =
Status.init file
in
( StatusPage pageModel, Cmd.map StatusPageMsg pageCmd )
in
( { model | page = currentPage }
, Cmd.batch [ existingCmds, mappedPageCmds ]
@@ -79,6 +82,7 @@ type Msg
| UrlChanged Url
| HomePageMsg MainPage.Msg
| FilesPageMsg Files.Msg
| StatusPageMsg Status.Msg
@@ -91,7 +95,7 @@ update msg model =
( HomePageMsg subMsg, Home pageModel ) ->
let
( updatePageModel, updateCmd ) =
MainPage.update subMsg pageModel
MainPage.update model.navKey subMsg pageModel
in
( { model | page = Home updatePageModel }
, Cmd.map HomePageMsg updateCmd
@@ -106,6 +110,15 @@ update msg model =
, Cmd.map FilesPageMsg updateCmd
)
( StatusPageMsg subMsg, StatusPage pageModel ) ->
let
( updatePageModel, updateCmd ) =
Status.update subMsg pageModel
in
( { model | page = StatusPage updatePageModel }
, Cmd.map StatusPageMsg updateCmd
)
( LinkClicked urlRequest, _ ) ->
case urlRequest of
Browser.Internal url ->
@@ -141,6 +154,9 @@ view model =
FilesPage pageModel ->
Files.view pageModel |> Element.map FilesPageMsg
StatusPage pageModel ->
Status.view pageModel |> Element.map StatusPageMsg
_ ->
el
[ Region.heading 1

View File

@@ -1,5 +1,6 @@
module MainPage exposing (Model, Msg, initModel, update, view)
import Browser.Navigation as Nav
import Color exposing (..)
import Element exposing (..)
import Element.Background as Background
@@ -7,13 +8,11 @@ import Element.Border as Border
import Element.Font as Font
import Element.Input as Input
import Element.Region as Region
import Html exposing (form)
import Http
import Json.Decode exposing (Decoder, int, string, succeed)
import Json.Decode.Pipeline exposing (required)
import Json.Encode as Encode
import List exposing (map3)
import Tuple exposing (mapBoth)
import Html exposing (form)
type alias Form =
@@ -53,13 +52,21 @@ type AudioFormats
| AAC
| WAV
audioFormatName : AudioFormats -> String
audioFormatName format =
case format of
MP3 -> "mp3"
OPUS -> "opus"
AAC -> "aac"
WAV -> "wav"
MP3 ->
"mp3"
OPUS ->
"opus"
AAC ->
"aac"
WAV ->
"wav"
type VideoFormats
@@ -68,38 +75,54 @@ type VideoFormats
| OGG
| WEBM
videoFormatName : VideoFormats -> String
videoFormatName format =
case format of
FLV -> "flv"
MP4 -> "mp4"
OGG -> "ogg"
WEBM -> "wav"
FLV ->
"flv"
MP4 ->
"mp4"
OGG ->
"ogg"
WEBM ->
"webm"
type Format
= Auto
| AudioFormat AudioFormats
| VideoFormat VideoFormats
formatName : Format -> String
formatName format =
case format of
Auto -> "Auto"
AudioFormat audio -> audioFormatName audio
VideoFormat video -> videoFormatName video
Auto ->
"Auto"
AudioFormat audio ->
audioFormatName audio
VideoFormat video ->
videoFormatName video
-- -- Request -- --
type alias PostFormResponse =
{ id : Int, status : String }
{ id : String, status : String }
formDecoder : Decoder PostFormResponse
formDecoder =
succeed PostFormResponse
|> required "id" int
|> required "file_id" string
|> required "status" string
@@ -115,8 +138,9 @@ formPostEncoder form =
[]
, if form.format == Auto then
[]
else
[( "format", Encode.string <| formatName form.format )]
[ ( "format", Encode.string <| formatName form.format ) ]
]
@@ -124,8 +148,8 @@ formPostEncoder form =
-- -- Update -- --
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
update : Nav.Key -> Msg -> Model -> ( Model, Cmd Msg )
update navKey msg model =
case msg of
UpdateForm new_form ->
( { model | form = new_form }, Cmd.none )
@@ -151,6 +175,7 @@ update msg model =
( { model | form = new_form }, Cmd.none )
PostForm form ->
if not (String.isEmpty form.url) then
( model
, Http.post
{ url = "http://127.0.0.1/api/add"
@@ -159,6 +184,12 @@ update msg model =
}
)
else
( model, Cmd.none )
PostResult (Ok data) ->
( model, Nav.pushUrl navKey <| String.concat [ "/status/", data.id ] )
_ ->
( model, Cmd.none )
@@ -254,6 +285,7 @@ formatButton position label state =
, Border.roundEach corners
, Border.widthEach borders
, Border.color color.blue
, width (px 80)
, Background.color <|
if state == Input.Selected then
color.lightBlue
@@ -269,6 +301,7 @@ formatButton position label state =
formatOption format position =
Input.optionWith format <| formatButton position <| formatName format
view : Model -> Element Msg
view model =
Element.column
@@ -287,15 +320,6 @@ view model =
(text "localTube")
, Input.text
[ spacing 12
, below
(el
[ Font.color color.red
, Font.size 14
, alignRight
, moveDown 6
]
(text "This one is wrong")
)
]
{ text = model.form.url
, placeholder = Just (Input.placeholder [] (text "http://youtube.com"))
@@ -335,7 +359,7 @@ view model =
[ formatOption (VideoFormat FLV) Mid
, formatOption (VideoFormat MP4) Mid
, formatOption (VideoFormat OGG) Mid
, formatOption (VideoFormat WEBM)Last
, formatOption (VideoFormat WEBM) Last
]
]
}

View File

@@ -8,6 +8,7 @@ type Route
= NotFound
| Home
| Files
| Status String
parseUrl : Url -> Route
@@ -25,4 +26,5 @@ matchRoute =
oneOf
[ map Home top
, map Files (s "files")
, map Status (s "status" </> string)
]

View File

@@ -0,0 +1,232 @@
module Status exposing (Model, Msg, init, queryStatus, update, view)
import Color exposing (color)
import Debug exposing (toString)
import Delay
import Element exposing (..)
import Element.Background as Background
import Element.Border as Border
import Element.Font as Font
import Element.Input as Input
import File.Download exposing (url)
import Files exposing (Msg(..))
import Globals exposing (apiDownloadFile, apiStatus)
import Http
import Json.Decode exposing (Decoder, int, list, string, succeed)
import Json.Decode.Pipeline exposing (optional, required)
import Route exposing (Route(..))
import String exposing (right)
import Task
-- Messages
type Msg
= Reload
| StatusRequestResult (Result Http.Error StatusResponse)
| Download String
-- Model
type alias Model =
{ file_id : String
, status : Maybe Status
}
init : String -> ( Model, Cmd Msg )
init file_id =
( { file_id = file_id, status = Nothing }, send Reload )
-- Request
type alias File =
{ format : String
, filename : String
, timestamp : Int
}
type alias Status =
{ file : Maybe File
, name : String
, source : String
, status : String
, status_id : Int
, format : String
, timestamp : Int
, id : String
}
type alias StatusResponse =
{ status : Status }
fileDecoder : Decoder File
fileDecoder =
succeed File
|> required "format" string
|> required "name" string
|> required "timestamp" int
statusDecoder : Decoder Status
statusDecoder =
succeed Status
|> optional "file" (Json.Decode.map Just fileDecoder) Nothing
|> required "name" string
|> required "source" string
|> required "status" string
|> required "status_id" int
|> required "task_file_type" string
|> required "timestamp" int
|> required "id" string
statusResponseDecoder : Decoder StatusResponse
statusResponseDecoder =
succeed StatusResponse
|> required "status" statusDecoder
queryStatus : String -> Cmd Msg
queryStatus id =
Http.get
{ url = apiStatus id
, expect = Http.expectJson StatusRequestResult statusResponseDecoder
}
-- Update
cardShadow : Attr decorative msg
cardShadow =
Border.shadow
{ offset = ( 0, 4 )
, size = 4
, blur = 8
, color = rgba 0 0 0 0.2
}
cardShadowOver : Attr decorative msg
cardShadowOver =
Border.shadow
{ offset = ( 0, 4 )
, size = 8
, blur = 16
, color = rgba 0 0 0 0.2
}
card : List (Attribute msg) -> Element msg -> Element msg
card attr element =
el
(List.concat
[ attr
, [ Border.rounded 15, cardShadow, mouseOver [ cardShadowOver ], padding 20 ]
]
)
element
innerCard : List (Attribute msg) -> Element msg -> Element msg
innerCard attr element =
el
(List.concat
[ attr
, [ Border.roundEach { topLeft = 15, topRight = 15, bottomLeft = 15, bottomRight = 15 }, padding 5 ]
]
)
element
send : msg -> Cmd msg
send msg =
Task.succeed msg
|> Task.perform identity
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Reload ->
( model, queryStatus model.file_id )
StatusRequestResult (Ok res) ->
( { model | status = Just res.status }, Delay.after 1000 Reload )
StatusRequestResult _ ->
( { model | status = Nothing }, Cmd.none )
Download file_id ->
( model, url <| apiDownloadFile file_id )
-- View
--Just (Download.
statusView : Status -> Element Msg
statusView status =
card [ width fill, height shrink ]
(Element.column
[ width fill ]
[ row [ width fill, height <| px 40 ]
[ el [ Font.size 28, alignLeft ] <| text status.name
, el [ Font.size 28, alignRight ] <| text (String.concat [ "[", status.status, "]" ])
]
, link [ Font.bold, Font.underline, Font.color color.blue, Font.size 16, padding 2 ]
{ url = status.source, label = text status.source }
, el [ height <| px 10 ] none
, case status.file of
Just file ->
innerCard [ width fill, height shrink, Background.color color.grey ] <|
row [ width fill, spacing 20 ]
[ Input.button
[ Background.color color.blue
, Font.color color.white
, Border.color color.red
, paddingXY 32 16
, Border.rounded 15
]
{ onPress = Just <| Download status.id
, label = Element.text "Download"
}
, el [ Font.size 16 ] <| text file.filename
]
Nothing ->
Element.none
]
)
view : Model -> Element Msg
view model =
Element.column
[ width (px 800)
, height shrink
, centerX
, centerY
, spacing 36
]
[ case model.status of
Just status ->
statusView status
Nothing ->
Element.text "Test"
]