From f52cb919cf1bc0b1c3202eacc57a28e1fb1a3f2b Mon Sep 17 00:00:00 2001
From: Daniel Brendel
Date: Sun, 25 Sep 2022 12:35:24 +0200
Subject: [PATCH] New widget: Steam Workshop
---
README.md | 8 +-
app/config/routes.php | 2 +-
app/controller/api.php | 22 +
app/controller/index.php | 12 -
app/models/HitsModel.php | 3 +-
app/modules/SteamApp.php | 2 +-
app/modules/SteamServer.php | 2 +-
app/modules/SteamUser.php | 2 +-
app/modules/SteamWorkshop.php | 53 ++
app/resources/css/steam_workshop.dev.css | 133 ++++
app/resources/js/steam_workshop.dev.js | 285 ++++++++
app/views/generator.php | 677 ------------------
app/views/index.php | 142 +++-
app/views/layout.php | 1 +
app/views/navbar.php | 4 +
build_ver.bat | 9 +
public/css/steamwidgets/v1/steam_workshop.css | 133 ++++
public/js/steamwidgets/v1/steam_workshop.js | 285 ++++++++
18 files changed, 1075 insertions(+), 700 deletions(-)
create mode 100644 app/modules/SteamWorkshop.php
create mode 100644 app/resources/css/steam_workshop.dev.css
create mode 100644 app/resources/js/steam_workshop.dev.js
delete mode 100644 app/views/generator.php
create mode 100644 public/css/steamwidgets/v1/steam_workshop.css
create mode 100644 public/js/steamwidgets/v1/steam_workshop.js
diff --git a/README.md b/README.md
index e49a070..ba08927 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ SteamWidgets offers the possibility to comfortably render Steam related widgets
document with as less effort as possible.
## Current featured widgets
-- Steam App Widget: Renders a widget of a Steam app/game
-- Steam Server Widget: Renders a widget of a Steam game server
-- Steam User Widget: Renders a widget of a Steam user
-
+- Steam App Widget: Renders widgets of a Steam app/game
+- Steam Server Widget: Renders widgets of a Steam game server
+- Steam User Widget: Renders widgets of a Steam user
+- Steam Workshop Widget: Renders widgets of a Steam workshop item
diff --git a/app/config/routes.php b/app/config/routes.php
index f4a80be..cc5bc98 100644
--- a/app/config/routes.php
+++ b/app/config/routes.php
@@ -17,10 +17,10 @@
return [
array('/', 'GET', 'index@index'),
- array('/generator', 'GET', 'index@generator'),
array('/api/query/app', 'GET', 'api@queryAppInfo'),
array('/api/query/server', 'GET', 'api@queryServerInfo'),
array('/api/query/user', 'GET', 'api@queryUserInfo'),
+ array('/api/query/workshop', 'GET', 'api@queryWorkshopInfo'),
array('/api/resource/query', 'GET', 'api@queryResource'),
array('/stats/{pw}', 'GET', 'stats@index'),
array('/stats/query/{pw}', 'ANY', 'stats@query'),
diff --git a/app/controller/api.php b/app/controller/api.php
index c7f3767..872c476 100644
--- a/app/controller/api.php
+++ b/app/controller/api.php
@@ -81,6 +81,28 @@ class ApiController extends BaseController {
}
}
+ /**
+ * Query Steam workshop data
+ *
+ * @param Asatru\Controller\ControllerArg $request
+ * @return Asatru\View\JsonHandler
+ */
+ public function queryWorkshopInfo($request)
+ {
+ try {
+ $itemid = $request->params()->query('itemid', null);
+
+ $data = SteamWorkshop::querySteamData($itemid);
+
+ //Save hit
+ HitsModel::addHit(HitsModel::HITTYPE_MODULE_WORKSHOP);
+
+ return json(array('code' => 200, 'itemid' => $itemid, 'data' => $data));
+ } catch (\Exception $e) {
+ return json(array('code' => 500, 'msg' => $e->getMessage()));
+ }
+ }
+
/**
* Query JavaScript or CSS resource for component
*
diff --git a/app/controller/index.php b/app/controller/index.php
index e258326..833d357 100644
--- a/app/controller/index.php
+++ b/app/controller/index.php
@@ -27,16 +27,4 @@ class IndexController extends BaseController {
//Generate and return a view by using the helper
return parent::view(['content', 'index']);
}
-
- /**
- * Handles URL: /generator
- *
- * @param Asatru\Controller\ControllerArg $request
- * @return Asatru\View\ViewHandler
- */
- public function generator($request)
- {
- //Generate and return a view by using the helper
- return view('generator', []);
- }
}
diff --git a/app/models/HitsModel.php b/app/models/HitsModel.php
index d09064b..ed981d1 100644
--- a/app/models/HitsModel.php
+++ b/app/models/HitsModel.php
@@ -10,6 +10,7 @@ class HitsModel extends \Asatru\Database\Model
const HITTYPE_MODULE_APP = 'mod_app';
const HITTYPE_MODULE_SERVER = 'mod_server';
const HITTYPE_MODULE_USER = 'mod_user';
+ const HITTYPE_MODULE_WORKSHOP = 'mod_workshop';
/**
* Validate hit type
@@ -21,7 +22,7 @@ class HitsModel extends \Asatru\Database\Model
public static function validateHitType($type)
{
try {
- $types = [self::HITTYPE_MODULE_APP, self::HITTYPE_MODULE_SERVER, self::HITTYPE_MODULE_USER];
+ $types = [self::HITTYPE_MODULE_APP, self::HITTYPE_MODULE_SERVER, self::HITTYPE_MODULE_USER, self::HITTYPE_MODULE_WORKSHOP];
if (!in_array($type, $types)) {
throw new Exception('Invalid hit type: ' . $type);
diff --git a/app/modules/SteamApp.php b/app/modules/SteamApp.php
index a20c5ed..9b215c0 100644
--- a/app/modules/SteamApp.php
+++ b/app/modules/SteamApp.php
@@ -1,7 +1,7 @@
response->result)) && ($obj->response->result) && (isset($obj->response->resultcount)) && ($obj->response->resultcount == 1)) {
+ $obj->response->publishedfiledetails[0]->creator_data = null;
+
+ try {
+ $obj->response->publishedfiledetails[0]->creator_data = SteamUser::querySteamData(env('STEAM_API_KEY'), $obj->response->publishedfiledetails[0]->creator);
+ } catch (\Exception $e) {
+ }
+
+ return $obj->response->publishedfiledetails[0];
+ }
+
+ throw new \Exception('Invalid data response');
+ }
+}
diff --git a/app/resources/css/steam_workshop.dev.css b/app/resources/css/steam_workshop.dev.css
new file mode 100644
index 0000000..d61bc30
--- /dev/null
+++ b/app/resources/css/steam_workshop.dev.css
@@ -0,0 +1,133 @@
+.steam-workshop {
+ position: relative;
+ min-width: 360px;
+ max-width: 555px;
+ height: 205px;
+ background-color: rgb(22, 32, 45);
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+ border-radius: 25px;
+ margin-top: 20px;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+.steam-workshop-preview {
+ position: relative;
+ display: inline-block;
+ min-width: 205px;
+ height: 205px;
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ border-top-left-radius: 25px;
+ border-bottom-left-radius: 25px;
+}
+
+.steam-workshop-info {
+ position: relative;
+ display: inline-block;
+ width: 55%;
+ margin-left: 20px;
+ top: -20px;
+}
+
+.steam-workshop-info-title {
+ margin-bottom: 10px;
+ color: rgb(220, 220, 220);
+ font-size: 1.1em;
+ font-family: Verdana, Arial, sans-serif;
+}
+
+.steam-workshop-info-description {
+ margin-bottom: 10px;
+ color: rgb(150, 150, 150);
+ font-size: 0.8em;
+ font-family: Verdana, Arial, sans-serif;
+}
+
+.steam-workshop-info-stats {
+ margin-bottom: 12px;
+}
+
+.steam-workshop-info-stats-item {
+}
+
+.steam-workshop-info-stats-item-count {
+ display: inline-block;
+ min-width: 50px;
+ color: rgb(59, 135, 185);
+}
+
+.steam-workshop-info-stats-item-label {
+ display: inline-block;
+ text-transform: uppercase;
+ color: rgb(100, 100, 100);
+}
+
+.steam-workshop-info-footer {
+}
+
+.steam-workshop-info-footer-author {
+ display: inline-block;
+ width: 69%;
+}
+
+.steam-workshop-info-footer-author a {
+ color: rgb(50, 115, 220);
+}
+
+.steam-workshop-info-footer-author a:hover {
+ color: rgb(50, 115, 220);
+ text-decoration: underline;
+}
+
+.steam-workshop-info-footer-action {
+ display: inline-block;
+}
+
+.steam-workshop-info-footer-action a {
+ color: #D2E885;
+ background: linear-gradient(to bottom, #a4d007 5%, #536904 95%);
+ border-radius: 5px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 10px;
+ padding-right: 10px;
+ text-decoration: none;
+ font-size: 0.9em;
+ font-family: 'Motiva Sans', sans-serif;
+}
+
+.steam-workshop-info-footer-action a:hover {
+ color: rgb(250, 250, 250);
+}
+
+@media screen and (max-width: 465px) {
+ .steam-workshop {
+ min-width: unset;
+ width: 350px;
+ min-height: 205px;
+ height: unset;
+ }
+
+ .steam-workshop-preview {
+ min-width: unset;
+ width: 350px;
+ height: 350px;
+ border-top-right-radius: 25px;
+ border-bottom-left-radius: unset;
+ }
+
+ .steam-workshop-info {
+ width: 100%;
+ height: 195px;
+ top: unset;
+ }
+
+ .steam-workshop-info-title {
+ margin-top: 5px;
+ }
+
+ .steam-workshop-info-footer-author {
+ width: 64%;
+ }
+}
\ No newline at end of file
diff --git a/app/resources/js/steam_workshop.dev.js b/app/resources/js/steam_workshop.dev.js
new file mode 100644
index 0000000..4e671eb
--- /dev/null
+++ b/app/resources/js/steam_workshop.dev.js
@@ -0,0 +1,285 @@
+/**
+ * SteamWidgets - Steam Widgets for your website
+ *
+ * Module: Steam Workshop Widget
+ *
+ * Visit: https://github.com/danielbrendel
+ */
+
+ const STEAMWIDGETS_WORKSHOP_ENDPOINT = 'http://localhost:8000';
+ const STEAMWIDGETS_WORKSHOP_VERSION = 'v1';
+
+ /**
+ * Class SteamWorkshopElem
+ *
+ * Handle custom HTML element to render Steam workshop widgets
+ */
+ class SteamWorkshopElem extends HTMLElement
+ {
+ DESCRIPTION_MAX_LEN = 40;
+
+ storedData = {};
+ oldHeader = '';
+
+ connectedCallback()
+ {
+ var itemid = (typeof this.attributes.itemid !== 'undefined') ? this.attributes.itemid.value : null;
+ var views = (typeof this.attributes.views !== 'undefined') ? this.attributes.views.value : 'Views';
+ var subscriptions = (typeof this.attributes.subscriptions !== 'undefined') ? this.attributes.subscriptions.value : 'Subscriptions';
+ var favorites = (typeof this.attributes.favorites !== 'undefined') ? this.attributes.favorites.value : 'Favorites';
+ var author = (typeof this.attributes.author !== 'undefined') ? this.attributes.author.value : 'By :creator';
+ var viewtext = (typeof this.attributes.viewtext !== 'undefined') ? this.attributes.viewtext.value : 'View item';
+ var showImage = (typeof this.attributes['show-image'] !== 'undefined') ? parseInt(this.attributes['show-image'].value) : 1;
+ var styleBorder = (typeof this.attributes['style-border'] !== 'undefined') ? this.attributes['style-border'].value : null;
+ var styleShadow = (typeof this.attributes['style-shadow'] !== 'undefined') ? parseInt(this.attributes['style-shadow'].value) : 1;
+
+ if (itemid !== null) {
+ this.storedData = {
+ itemid: itemid,
+ views: views,
+ subscriptions: subscriptions,
+ favorites: favorites,
+ author: author,
+ viewtext: viewtext,
+ showImage: showImage,
+ styleBorder: styleBorder,
+ styleShadow: styleShadow
+ };
+
+ this.setupWidget(
+ itemid,
+ views,
+ subscriptions,
+ favorites,
+ author,
+ viewtext,
+ showImage,
+ styleBorder,
+ styleShadow
+ );
+ }
+ }
+
+ setupWidget(itemid, views, subscriptions, favorites, author, viewtext, showImage, styleBorder, styleShadow)
+ {
+ var req = new XMLHttpRequest();
+ var self = this;
+
+ req.onreadystatechange = function() {
+ if (req.readyState == XMLHttpRequest.DONE) {
+ let json = JSON.parse(req.responseText);
+
+ if (!document.getElementById('steamwidgets-workshop-styles')) {
+ let link = document.createElement('link');
+ link.id = 'steamwidgets-workshop-styles';
+ link.rel = 'stylesheet';
+ link.type = 'text/css';
+ link.href = STEAMWIDGETS_WORKSHOP_ENDPOINT + '/api/resource/query?type=css&module=workshop&version=' + STEAMWIDGETS_WORKSHOP_VERSION;
+ document.getElementsByTagName('head')[0].appendChild(link);
+ }
+
+ let description = json.data.description;
+ if (description.length >= self.DESCRIPTION_MAX_LEN) {
+ description = description.substr(0, self.DESCRIPTION_MAX_LEN - 3) + '...';
+ }
+
+ author = author.replace(':creator', json.data.creator_data.personaname);
+
+ let html = `
+
+
+
+
+
` + json.data.title + `
+
+
` + description + `
+
+
+
+
` + self.readableCount(json.data.views) + `
+
` + views + `
+
+
+
+
` + self.readableCount(json.data.subscriptions) + `
+
`+ subscriptions + `
+
+
+
+
` + self.readableCount(json.data.favorited) + `
+
`+ favorites + `
+
+
+
+
+
+
+ `;
+
+ self.innerHTML = html;
+ }
+ };
+ req.open('GET', STEAMWIDGETS_WORKSHOP_ENDPOINT + '/api/query/workshop?itemid=' + itemid, true);
+ req.send();
+ }
+
+ updateWidget()
+ {
+ this.setupWidget(
+ this.storedData.itemid,
+ this.storedData.views,
+ this.storedData.subscriptions,
+ this.storedData.favorites,
+ this.storedData.author,
+ this.storedData.viewtext,
+ this.storedData.showImage,
+ this.storedData.styleBorder,
+ this.storedData.styleShadow
+ );
+ }
+
+ changeLang(views, subscriptions, favorites, author, viewtext)
+ {
+ this.storedData.views = views;
+ this.storedData.subscriptions = subscriptions;
+ this.storedData.favorites = favorites;
+ this.storedData.author = author;
+ this.storedData.viewtext = viewtext;
+
+ this.setupWidget(
+ this.storedData.itemid,
+ this.storedData.views,
+ this.storedData.subscriptions,
+ this.storedData.favorites,
+ this.storedData.author,
+ this.storedData.viewtext,
+ this.storedData.showImage,
+ this.storedData.styleBorder,
+ this.storedData.styleShadow
+ );
+ }
+
+ setImageVisibility(visibility)
+ {
+ this.storedData.showImage = visibility;
+
+ this.setupWidget(
+ this.storedData.itemid,
+ this.storedData.views,
+ this.storedData.subscriptions,
+ this.storedData.favorites,
+ this.storedData.author,
+ this.storedData.viewtext,
+ this.storedData.showImage,
+ this.storedData.styleBorder,
+ this.storedData.styleShadow
+ );
+ }
+
+ readableCount(count)
+ {
+ const COUNT_MILLION = 1000000;
+ const COUNT_HUNDREDTHOUSAND = 100000;
+ const COUNT_TENTHOUSAND = 10000;
+ const COUNT_THOUSAND = 1000;
+
+ if (count >= COUNT_MILLION) {
+ return (Math.round(count / COUNT_MILLION, 1)).toString() + 'M';
+ } else if ((count < COUNT_MILLION) && (count >= COUNT_HUNDREDTHOUSAND)) {
+ return (Math.round(count / COUNT_THOUSAND, 1)).toString() + 'K';
+ } else if ((count < COUNT_HUNDREDTHOUSAND) && (count >= COUNT_TENTHOUSAND)) {
+ return (Math.round(count / COUNT_THOUSAND, 1)).toString() + 'K';
+ } else if ((count < COUNT_TENTHOUSAND) && (count >= COUNT_THOUSAND)) {
+ return (Math.round(count / COUNT_THOUSAND, 1)).toString() + 'K';
+ } else {
+ return count.toString();
+ }
+ }
+ }
+
+ window.customElements.define('steam-workshop', SteamWorkshopElem);
+
+ /**
+ * Class SteamWorkshop
+ *
+ * Dynamically create a Steam workshop widgets via JavaScript
+ */
+ class SteamWorkshop
+ {
+ elem = null;
+ selident = null;
+ cfg = {};
+
+ constructor(selector, config = {})
+ {
+ this.selident = selector;
+ this.cfg = config;
+
+ var itemid = (typeof config.itemid !== 'undefined') ? config.itemid : null;
+ var views = (typeof config.views !== 'undefined') ? config.views : 'Views';
+ var subscriptions = (typeof config.subscriptions !== 'undefined') ? config.subscriptions : 'Subscriptions';
+ var favorites = (typeof config.favorites !== 'undefined') ? config.favorites : 'Favorites';
+ var author = (typeof config.author !== 'undefined') ? config.author : 'By :creator';
+ var viewtext = (typeof config.viewtext !== 'undefined') ? config.viewtext : 'View item';
+ var showImage = (typeof config.showImage !== 'undefined') ? config.showImage : null;
+
+ if (typeof showImage === 'boolean') {
+ showImage = (showImage) ? 1 : 0;
+ }
+
+ var styleBorder = null;
+ var styleShadow = 1;
+
+ if (typeof config.style !== 'undefined') {
+ styleBorder = (typeof config.style.border !== 'undefined') ? config.style.border : null;
+ styleShadow = (typeof config.style.shadow !== 'undefined') ? config.style.shadow : 1;
+ }
+
+ if (typeof styleShadow === 'boolean') {
+ styleShadow = (styleShadow) ? 1 : 0;
+ }
+
+ this.elem = document.createElement('steam-workshop');
+ this.elem.setAttribute('itemid', itemid);
+ this.elem.setAttribute('views', views);
+ this.elem.setAttribute('subscriptions', subscriptions);
+ this.elem.setAttribute('favorites', favorites);
+ this.elem.setAttribute('author', author);
+ this.elem.setAttribute('viewtext', viewtext);
+ this.elem.setAttribute('show-image', showImage);
+ this.elem.setAttribute('style-border', styleBorder);
+ this.elem.setAttribute('style-shadow', styleShadow);
+
+ let sel = document.querySelector(selector);
+ if (sel) {
+ sel.appendChild(this.elem);
+ }
+ }
+
+ updateWidget()
+ {
+ this.elem.updateWidget();
+ }
+
+ changeLang(views, subscriptions, favorites, author, viewtext)
+ {
+ this.elem.changeLang(views, subscriptions, favorites, author, viewtext);
+ }
+
+ setImageVisibility(visibility)
+ {
+ this.elem.setImageVisibility(visibility);
+ }
+
+ remove()
+ {
+ this.elem.remove();
+ }
+ }
+
\ No newline at end of file
diff --git a/app/views/generator.php b/app/views/generator.php
deleted file mode 100644
index 30591ce..0000000
--- a/app/views/generator.php
+++ /dev/null
@@ -1,677 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ env('APP_TITLE') }}
-
-
-
- @if (env('APP_DEBUG'))
-
- @else
-
- @endif
-
-
-
-
-
-
-
-
-
-
-
{{ env('APP_NAME') }} Widget Generator
-
-
-
-
Please select a type of widget you want to create.
-
-
For more information about {{ env('APP_NAME') }} please visit {{ url('/') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/views/index.php b/app/views/index.php
index e30b851..75226e9 100644
--- a/app/views/index.php
+++ b/app/views/index.php
@@ -26,6 +26,7 @@
Steam App Widget
Steam Server Widget
Steam User Widget
+ Steam Workshop Widget
@@ -40,8 +41,8 @@
- STEAM_WIDGETS_MODULE can either be app for the Steam App widget, server for the Steam Server widget or
- user for the Steam User widget.
+ STEAM_WIDGETS_MODULE can either be app for the Steam App widget, server for the Steam Server widget,
+ user for the Steam User widget or workshop for the Steam Workshop widget.
@if (env('APP_SHOWNPMUSAGE', false))
@@ -546,6 +547,143 @@ document.addEventListener('DOMContentLoaded', function() {
Sets the widget image visibility
+
+ remove()
+ Removes the widget from the document
+
+
+
+
+
+
+
+
+
+
Steam Workshop
+
+
+ When referenced the required Steam Workshop module, the minimum code to render a widget is as follows:
+
+
+<steam-workshop itemid="id"></steam-workshop>
+
+
+
+
+ This renders the following widget:
+
+
+
+
+ You can define these options:
+
+
+
+
+
+
+
+
+ Attribute
+ Value
+
+
+
+ itemid
+ Specifies the item ID of the Steam Workshop item
+
+
+
+ views
+ Specifies the text of the views stats label
+
+
+
+ subscriptions
+ Specifies the text of the subscriptions stats label
+
+
+
+ favorites
+ Specifies the text of the favorites stats label
+
+
+
+ author
+ Specifies the author text. Use :creator to insert the creators Steam persona name
+
+
+
+ viewtext
+ Specifies the text of the button which can be used to go to the Workshop item page
+
+
+
+ show-image / showImage
+ Specifies if the workshop item preview image shall be displayed. Defaults to true/1
+
+
+
+ style-border / style.border
+ Specify border rounding: Either none, small or max
+
+
+
+ style-shadow / style.shadow
+ You can specify false to prevent displaying box shadow or true to enable (default)
+
+
+
+
+
+
+ You can also dynamically create Steam Workshop widgets via JavaScript:
+
+
+
+<div id="workshop-widget"></div>
+
+<script>
+document.addEventListener('DOMContentLoaded', function() {
+ let widget = new SteamWorkshop('#workshop-widget', {
+ itemid: 'id',
+ //You can specify the same attributes as shown in the table above
+ });
+});
+</script>
+
+
+
+
+
+ The following methods are available for a Steam Workshop element / object:
+
+
+
+
+
+
+
+
+ Method
+ Description
+
+
+
+ updateWidget()
+ Updates the widget data and displays them
+
+
+
+ changeLang(views, subscriptions, favorites, author, viewtext)
+ Changes the language of the widget using the given information
+
+
+
+ setImageVisibility(visibility)
+ Sets the widget image visibility
+
+
remove()
Removes the widget from the document
diff --git a/app/views/layout.php b/app/views/layout.php
index a0645d5..d2eaac8 100644
--- a/app/views/layout.php
+++ b/app/views/layout.php
@@ -22,6 +22,7 @@
+
diff --git a/app/views/navbar.php b/app/views/navbar.php
index 9ef273a..ea95625 100644
--- a/app/views/navbar.php
+++ b/app/views/navbar.php
@@ -28,6 +28,10 @@
Steam User
+
+
+ Steam Workshop
+
diff --git a/build_ver.bat b/build_ver.bat
index 5b35bfa..ccc00ac 100644
--- a/build_ver.bat
+++ b/build_ver.bat
@@ -16,6 +16,9 @@ del "%~dp0public\css\steamwidgets\%ver%\steam_server.css"
del "%~dp0public\js\steamwidgets\%ver%\steam_user.js"
del "%~dp0public\css\steamwidgets\%ver%\steam_user.css"
+del "%~dp0public\js\steamwidgets\%ver%\steam_workshop.js"
+del "%~dp0public\css\steamwidgets\%ver%\steam_workshop.css"
+
xcopy "%~dp0app\resources\js\steam_app.dev.js" "%~dp0public\js\steamwidgets\%ver%\" /Y
xcopy "%~dp0app\resources\css\steam_app.dev.css" "%~dp0public\css\steamwidgets\%ver%\" /Y
@@ -25,6 +28,9 @@ xcopy "%~dp0app\resources\css\steam_server.dev.css" "%~dp0public\css\steamwidget
xcopy "%~dp0app\resources\js\steam_user.dev.js" "%~dp0public\js\steamwidgets\%ver%\" /Y
xcopy "%~dp0app\resources\css\steam_user.dev.css" "%~dp0public\css\steamwidgets\%ver%\" /Y
+xcopy "%~dp0app\resources\js\steam_workshop.dev.js" "%~dp0public\js\steamwidgets\%ver%\" /Y
+xcopy "%~dp0app\resources\css\steam_workshop.dev.css" "%~dp0public\css\steamwidgets\%ver%\" /Y
+
ren "%~dp0public\js\steamwidgets\%ver%\steam_app.dev.js" "steam_app.js"
ren "%~dp0public\css\steamwidgets\%ver%\steam_app.dev.css" "steam_app.css"
@@ -34,6 +40,9 @@ ren "%~dp0public\css\steamwidgets\%ver%\steam_server.dev.css" "steam_server.css"
ren "%~dp0public\js\steamwidgets\%ver%\steam_user.dev.js" "steam_user.js"
ren "%~dp0public\css\steamwidgets\%ver%\steam_user.dev.css" "steam_user.css"
+ren "%~dp0public\js\steamwidgets\%ver%\steam_workshop.dev.js" "steam_workshop.js"
+ren "%~dp0public\css\steamwidgets\%ver%\steam_workshop.dev.css" "steam_workshop.css"
+
echo "Job done"
pause
\ No newline at end of file
diff --git a/public/css/steamwidgets/v1/steam_workshop.css b/public/css/steamwidgets/v1/steam_workshop.css
new file mode 100644
index 0000000..d61bc30
--- /dev/null
+++ b/public/css/steamwidgets/v1/steam_workshop.css
@@ -0,0 +1,133 @@
+.steam-workshop {
+ position: relative;
+ min-width: 360px;
+ max-width: 555px;
+ height: 205px;
+ background-color: rgb(22, 32, 45);
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+ border-radius: 25px;
+ margin-top: 20px;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+.steam-workshop-preview {
+ position: relative;
+ display: inline-block;
+ min-width: 205px;
+ height: 205px;
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ border-top-left-radius: 25px;
+ border-bottom-left-radius: 25px;
+}
+
+.steam-workshop-info {
+ position: relative;
+ display: inline-block;
+ width: 55%;
+ margin-left: 20px;
+ top: -20px;
+}
+
+.steam-workshop-info-title {
+ margin-bottom: 10px;
+ color: rgb(220, 220, 220);
+ font-size: 1.1em;
+ font-family: Verdana, Arial, sans-serif;
+}
+
+.steam-workshop-info-description {
+ margin-bottom: 10px;
+ color: rgb(150, 150, 150);
+ font-size: 0.8em;
+ font-family: Verdana, Arial, sans-serif;
+}
+
+.steam-workshop-info-stats {
+ margin-bottom: 12px;
+}
+
+.steam-workshop-info-stats-item {
+}
+
+.steam-workshop-info-stats-item-count {
+ display: inline-block;
+ min-width: 50px;
+ color: rgb(59, 135, 185);
+}
+
+.steam-workshop-info-stats-item-label {
+ display: inline-block;
+ text-transform: uppercase;
+ color: rgb(100, 100, 100);
+}
+
+.steam-workshop-info-footer {
+}
+
+.steam-workshop-info-footer-author {
+ display: inline-block;
+ width: 69%;
+}
+
+.steam-workshop-info-footer-author a {
+ color: rgb(50, 115, 220);
+}
+
+.steam-workshop-info-footer-author a:hover {
+ color: rgb(50, 115, 220);
+ text-decoration: underline;
+}
+
+.steam-workshop-info-footer-action {
+ display: inline-block;
+}
+
+.steam-workshop-info-footer-action a {
+ color: #D2E885;
+ background: linear-gradient(to bottom, #a4d007 5%, #536904 95%);
+ border-radius: 5px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 10px;
+ padding-right: 10px;
+ text-decoration: none;
+ font-size: 0.9em;
+ font-family: 'Motiva Sans', sans-serif;
+}
+
+.steam-workshop-info-footer-action a:hover {
+ color: rgb(250, 250, 250);
+}
+
+@media screen and (max-width: 465px) {
+ .steam-workshop {
+ min-width: unset;
+ width: 350px;
+ min-height: 205px;
+ height: unset;
+ }
+
+ .steam-workshop-preview {
+ min-width: unset;
+ width: 350px;
+ height: 350px;
+ border-top-right-radius: 25px;
+ border-bottom-left-radius: unset;
+ }
+
+ .steam-workshop-info {
+ width: 100%;
+ height: 195px;
+ top: unset;
+ }
+
+ .steam-workshop-info-title {
+ margin-top: 5px;
+ }
+
+ .steam-workshop-info-footer-author {
+ width: 64%;
+ }
+}
\ No newline at end of file
diff --git a/public/js/steamwidgets/v1/steam_workshop.js b/public/js/steamwidgets/v1/steam_workshop.js
new file mode 100644
index 0000000..4e671eb
--- /dev/null
+++ b/public/js/steamwidgets/v1/steam_workshop.js
@@ -0,0 +1,285 @@
+/**
+ * SteamWidgets - Steam Widgets for your website
+ *
+ * Module: Steam Workshop Widget
+ *
+ * Visit: https://github.com/danielbrendel
+ */
+
+ const STEAMWIDGETS_WORKSHOP_ENDPOINT = 'http://localhost:8000';
+ const STEAMWIDGETS_WORKSHOP_VERSION = 'v1';
+
+ /**
+ * Class SteamWorkshopElem
+ *
+ * Handle custom HTML element to render Steam workshop widgets
+ */
+ class SteamWorkshopElem extends HTMLElement
+ {
+ DESCRIPTION_MAX_LEN = 40;
+
+ storedData = {};
+ oldHeader = '';
+
+ connectedCallback()
+ {
+ var itemid = (typeof this.attributes.itemid !== 'undefined') ? this.attributes.itemid.value : null;
+ var views = (typeof this.attributes.views !== 'undefined') ? this.attributes.views.value : 'Views';
+ var subscriptions = (typeof this.attributes.subscriptions !== 'undefined') ? this.attributes.subscriptions.value : 'Subscriptions';
+ var favorites = (typeof this.attributes.favorites !== 'undefined') ? this.attributes.favorites.value : 'Favorites';
+ var author = (typeof this.attributes.author !== 'undefined') ? this.attributes.author.value : 'By :creator';
+ var viewtext = (typeof this.attributes.viewtext !== 'undefined') ? this.attributes.viewtext.value : 'View item';
+ var showImage = (typeof this.attributes['show-image'] !== 'undefined') ? parseInt(this.attributes['show-image'].value) : 1;
+ var styleBorder = (typeof this.attributes['style-border'] !== 'undefined') ? this.attributes['style-border'].value : null;
+ var styleShadow = (typeof this.attributes['style-shadow'] !== 'undefined') ? parseInt(this.attributes['style-shadow'].value) : 1;
+
+ if (itemid !== null) {
+ this.storedData = {
+ itemid: itemid,
+ views: views,
+ subscriptions: subscriptions,
+ favorites: favorites,
+ author: author,
+ viewtext: viewtext,
+ showImage: showImage,
+ styleBorder: styleBorder,
+ styleShadow: styleShadow
+ };
+
+ this.setupWidget(
+ itemid,
+ views,
+ subscriptions,
+ favorites,
+ author,
+ viewtext,
+ showImage,
+ styleBorder,
+ styleShadow
+ );
+ }
+ }
+
+ setupWidget(itemid, views, subscriptions, favorites, author, viewtext, showImage, styleBorder, styleShadow)
+ {
+ var req = new XMLHttpRequest();
+ var self = this;
+
+ req.onreadystatechange = function() {
+ if (req.readyState == XMLHttpRequest.DONE) {
+ let json = JSON.parse(req.responseText);
+
+ if (!document.getElementById('steamwidgets-workshop-styles')) {
+ let link = document.createElement('link');
+ link.id = 'steamwidgets-workshop-styles';
+ link.rel = 'stylesheet';
+ link.type = 'text/css';
+ link.href = STEAMWIDGETS_WORKSHOP_ENDPOINT + '/api/resource/query?type=css&module=workshop&version=' + STEAMWIDGETS_WORKSHOP_VERSION;
+ document.getElementsByTagName('head')[0].appendChild(link);
+ }
+
+ let description = json.data.description;
+ if (description.length >= self.DESCRIPTION_MAX_LEN) {
+ description = description.substr(0, self.DESCRIPTION_MAX_LEN - 3) + '...';
+ }
+
+ author = author.replace(':creator', json.data.creator_data.personaname);
+
+ let html = `
+
+
+
+
+
` + json.data.title + `
+
+
` + description + `
+
+
+
+
` + self.readableCount(json.data.views) + `
+
` + views + `
+
+
+
+
` + self.readableCount(json.data.subscriptions) + `
+
`+ subscriptions + `
+
+
+
+
` + self.readableCount(json.data.favorited) + `
+
`+ favorites + `
+
+
+
+
+
+
+ `;
+
+ self.innerHTML = html;
+ }
+ };
+ req.open('GET', STEAMWIDGETS_WORKSHOP_ENDPOINT + '/api/query/workshop?itemid=' + itemid, true);
+ req.send();
+ }
+
+ updateWidget()
+ {
+ this.setupWidget(
+ this.storedData.itemid,
+ this.storedData.views,
+ this.storedData.subscriptions,
+ this.storedData.favorites,
+ this.storedData.author,
+ this.storedData.viewtext,
+ this.storedData.showImage,
+ this.storedData.styleBorder,
+ this.storedData.styleShadow
+ );
+ }
+
+ changeLang(views, subscriptions, favorites, author, viewtext)
+ {
+ this.storedData.views = views;
+ this.storedData.subscriptions = subscriptions;
+ this.storedData.favorites = favorites;
+ this.storedData.author = author;
+ this.storedData.viewtext = viewtext;
+
+ this.setupWidget(
+ this.storedData.itemid,
+ this.storedData.views,
+ this.storedData.subscriptions,
+ this.storedData.favorites,
+ this.storedData.author,
+ this.storedData.viewtext,
+ this.storedData.showImage,
+ this.storedData.styleBorder,
+ this.storedData.styleShadow
+ );
+ }
+
+ setImageVisibility(visibility)
+ {
+ this.storedData.showImage = visibility;
+
+ this.setupWidget(
+ this.storedData.itemid,
+ this.storedData.views,
+ this.storedData.subscriptions,
+ this.storedData.favorites,
+ this.storedData.author,
+ this.storedData.viewtext,
+ this.storedData.showImage,
+ this.storedData.styleBorder,
+ this.storedData.styleShadow
+ );
+ }
+
+ readableCount(count)
+ {
+ const COUNT_MILLION = 1000000;
+ const COUNT_HUNDREDTHOUSAND = 100000;
+ const COUNT_TENTHOUSAND = 10000;
+ const COUNT_THOUSAND = 1000;
+
+ if (count >= COUNT_MILLION) {
+ return (Math.round(count / COUNT_MILLION, 1)).toString() + 'M';
+ } else if ((count < COUNT_MILLION) && (count >= COUNT_HUNDREDTHOUSAND)) {
+ return (Math.round(count / COUNT_THOUSAND, 1)).toString() + 'K';
+ } else if ((count < COUNT_HUNDREDTHOUSAND) && (count >= COUNT_TENTHOUSAND)) {
+ return (Math.round(count / COUNT_THOUSAND, 1)).toString() + 'K';
+ } else if ((count < COUNT_TENTHOUSAND) && (count >= COUNT_THOUSAND)) {
+ return (Math.round(count / COUNT_THOUSAND, 1)).toString() + 'K';
+ } else {
+ return count.toString();
+ }
+ }
+ }
+
+ window.customElements.define('steam-workshop', SteamWorkshopElem);
+
+ /**
+ * Class SteamWorkshop
+ *
+ * Dynamically create a Steam workshop widgets via JavaScript
+ */
+ class SteamWorkshop
+ {
+ elem = null;
+ selident = null;
+ cfg = {};
+
+ constructor(selector, config = {})
+ {
+ this.selident = selector;
+ this.cfg = config;
+
+ var itemid = (typeof config.itemid !== 'undefined') ? config.itemid : null;
+ var views = (typeof config.views !== 'undefined') ? config.views : 'Views';
+ var subscriptions = (typeof config.subscriptions !== 'undefined') ? config.subscriptions : 'Subscriptions';
+ var favorites = (typeof config.favorites !== 'undefined') ? config.favorites : 'Favorites';
+ var author = (typeof config.author !== 'undefined') ? config.author : 'By :creator';
+ var viewtext = (typeof config.viewtext !== 'undefined') ? config.viewtext : 'View item';
+ var showImage = (typeof config.showImage !== 'undefined') ? config.showImage : null;
+
+ if (typeof showImage === 'boolean') {
+ showImage = (showImage) ? 1 : 0;
+ }
+
+ var styleBorder = null;
+ var styleShadow = 1;
+
+ if (typeof config.style !== 'undefined') {
+ styleBorder = (typeof config.style.border !== 'undefined') ? config.style.border : null;
+ styleShadow = (typeof config.style.shadow !== 'undefined') ? config.style.shadow : 1;
+ }
+
+ if (typeof styleShadow === 'boolean') {
+ styleShadow = (styleShadow) ? 1 : 0;
+ }
+
+ this.elem = document.createElement('steam-workshop');
+ this.elem.setAttribute('itemid', itemid);
+ this.elem.setAttribute('views', views);
+ this.elem.setAttribute('subscriptions', subscriptions);
+ this.elem.setAttribute('favorites', favorites);
+ this.elem.setAttribute('author', author);
+ this.elem.setAttribute('viewtext', viewtext);
+ this.elem.setAttribute('show-image', showImage);
+ this.elem.setAttribute('style-border', styleBorder);
+ this.elem.setAttribute('style-shadow', styleShadow);
+
+ let sel = document.querySelector(selector);
+ if (sel) {
+ sel.appendChild(this.elem);
+ }
+ }
+
+ updateWidget()
+ {
+ this.elem.updateWidget();
+ }
+
+ changeLang(views, subscriptions, favorites, author, viewtext)
+ {
+ this.elem.changeLang(views, subscriptions, favorites, author, viewtext);
+ }
+
+ setImageVisibility(visibility)
+ {
+ this.elem.setImageVisibility(visibility);
+ }
+
+ remove()
+ {
+ this.elem.remove();
+ }
+ }
+
\ No newline at end of file