From 7fa7abdb1df8c650e538d33d425ac60757174bdb Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 20 Jun 2016 22:43:28 -0700 Subject: [PATCH] add operating hours to domain-server settings/UI --- .../resources/describe-settings.json | 54 +++++++++++++++++- .../resources/web/settings/js/settings.js | 14 ++++- domain-server/src/DomainMetadata.cpp | 56 ++++++++++++++----- domain-server/src/DomainMetadata.h | 8 ++- .../src/DomainServerSettingsManager.cpp | 27 ++++++++- 5 files changed, 139 insertions(+), 20 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 3633685365..59fa9c4f3d 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 1.4, + "version": 1.5, "settings": [ { "name": "metaverse", @@ -143,9 +143,57 @@ ] }, { - "name": "utc_offset", + "label": "Operating Hours", + "help": "\"Open\" domains can be searched using their operating hours. Hours are entered in the local timezone, selected below.", + + "name": "weekday_hours", + "caption": "Weekday Hours (Monday-Friday)", + "type": "table", + "can_add_new_rows": false, + "columns": [ + { + "name": "open", + "label": "Opening Time", + "type": "time", + "default": "00:00", + "editable": true + }, + { + "name": "close", + "label": "Closing Time", + "type": "time", + "default": "23:59", + "editable": true + } + ] + }, + { + "name": "weekend_hours", + "label": "Weekend Hours (Saturday/Sunday)", + "type": "table", + "can_add_new_rows": false, + "columns": [ + { + "name": "open", + "label": "Opening Time", + "type": "time", + "default": "00:00", + "editable": true + }, + { + "name": "close", + "label": "Closing Time", + "type": "time", + "default": "23:59", + "editable": true + } + ] + }, + { "label": "Time Zone", - "help": "This server's time zone, used for searching open servers", + "name": "utc_offset", + "caption": "Time Zone", + "help": "This server's time zone. Used to define your server's operating hours.", "type": "select", "options": [ { diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index aecc48b31f..709e0e05ce 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -987,7 +987,7 @@ function makeTable(setting, keypath, setting_value, isLocked) { html += "" + rowIndexOrName + "" } - var isNonDeletableRow = false; + var isNonDeletableRow = !setting.can_add_new_rows; _.each(setting.columns, function(col) { @@ -1007,6 +1007,10 @@ function makeTable(setting, keypath, setting_value, isLocked) { html += "" + ""; + } else if (isArray && col.type === "time" && col.editable) { + html += "" + + ""; } else { // Use a hidden input so that the values are posted. html += "" @@ -1196,15 +1200,21 @@ function addTableRow(add_glyphicon) { // Hide inputs var input = $(element).find("input") var isCheckbox = false; + var isTime = false; if (input.hasClass("table-checkbox")) { input = $(input).parent(); isCheckbox = true; + } else if (input.hasClass("table-time")) { + input = $(input).parent(); + isTime = true; } var val = input.val(); if (isCheckbox) { - val = $(input).find("input").is(':checked'); // don't hide the checkbox + val = $(input).find("input").is(':checked'); + } else if (isTime) { + // don't hide the time } else { input.attr("type", "hidden") } diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index bdf24c000a..c1656af5b7 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -31,30 +31,32 @@ const QString DomainMetadata::Users::HOSTNAMES = "user_hostnames"; const QString DomainMetadata::DESCRIPTORS = "descriptors"; const QString DomainMetadata::Descriptors::DESCRIPTION = "description"; const QString DomainMetadata::Descriptors::CAPACITY = "capacity"; // parsed from security -const QString DomainMetadata::Descriptors::HOURS = "hours"; const QString DomainMetadata::Descriptors::RESTRICTION = "restriction"; // parsed from ACL const QString DomainMetadata::Descriptors::MATURITY = "maturity"; const QString DomainMetadata::Descriptors::HOSTS = "hosts"; const QString DomainMetadata::Descriptors::TAGS = "tags"; +const QString DomainMetadata::Descriptors::HOURS = "hours"; +const QString DomainMetadata::Descriptors::Hours::WEEKDAY = "weekday"; +const QString DomainMetadata::Descriptors::Hours::WEEKEND = "weekend"; +const QString DomainMetadata::Descriptors::Hours::UTC_OFFSET = "utc_offset"; // descriptors metadata will appear as (JSON): // { "description": String, // capped description // "capacity": Number, -// "hours": { -// "utc_offset": Number, -// "weekday": [ Number, Number ], -// "weekend": [ Number, Number ] -// } // "restriction": String, // enum of either open, hifi, or acl // "maturity": String, // enum corresponding to ESRB ratings // "hosts": [ String ], // capped list of usernames // "tags": [ String ], // capped list of tags +// "hours": { +// "utc_offset": Number, +// "weekday": [ { "open": Time, "close": Time } ], +// "weekend": [ { "open": Time, "close": Time } ], +// } // } // metadata will appear as (JSON): // { users: , descriptors: } // // it is meant to be sent to and consumed by an external API -// NOTE: metadata may not appear as documented, as parts are generated by describe-settings.js DomainMetadata::DomainMetadata(QObject* domainServer) : QObject(domainServer) { _metadata[USERS] = {}; @@ -86,20 +88,42 @@ QJsonObject DomainMetadata::get(const QString& group) { } void DomainMetadata::descriptorsChanged() { - const QString CAPACITY = "security.maximum_user_capacity"; + // get descriptors auto settings = static_cast(parent())->_settingsManager.getSettingsMap(); + auto descriptors = settings[DESCRIPTORS].toMap(); + + // parse capacity + const QString CAPACITY = "security.maximum_user_capacity"; const QVariant* capacityVariant = valueForKeyPath(settings, CAPACITY); unsigned int capacity = capacityVariant ? capacityVariant->toUInt() : 0; - - auto descriptors = settings[DESCRIPTORS].toMap(); descriptors[Descriptors::CAPACITY] = capacity; + + // parse operating hours + const QString WEEKDAY_HOURS = "weekday_hours"; + const QString WEEKEND_HOURS = "weekday_hours"; + const QString UTC_OFFSET = "utc_offset"; + auto weekdayHours = descriptors[WEEKDAY_HOURS]; + auto weekendHours = descriptors[WEEKEND_HOURS]; + auto utcOffset = descriptors[UTC_OFFSET]; + descriptors.remove(WEEKDAY_HOURS); + descriptors.remove(WEEKEND_HOURS); + descriptors.remove(UTC_OFFSET); + QVariantMap hours { + { Descriptors::Hours::UTC_OFFSET, utcOffset }, + { Descriptors::Hours::WEEKDAY, weekdayHours }, + { Descriptors::Hours::WEEKEND, weekendHours } + }; + descriptors[Descriptors::HOURS] = hours; + + // update metadata _metadata[DESCRIPTORS] = descriptors; // update overwritten fields + // this further overwrites metadata, so it must be done after commiting descriptors securityChanged(false); #if DEV_BUILD || PR_BUILD - qDebug() << "Domain metadata descriptors set:" << _metadata[DESCRIPTORS]; + qDebug() << "Domain metadata descriptors set:" << QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap()); #endif sendDescriptors(); @@ -189,7 +213,7 @@ void DomainMetadata::maybeUpdateUsers() { ++_tic; #if DEV_BUILD || PR_BUILD - qDebug() << "Domain metadata users updated:" << users; + qDebug() << "Domain metadata users set:" << QJsonObject::fromVariantMap(_metadata[USERS].toMap()); #endif } @@ -198,10 +222,16 @@ void DomainMetadata::sendDescriptors() { const QUuid& domainID = DependencyManager::get()->getSessionUUID(); if (!domainID.isNull()) { static const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; - DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), + QString path { DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)) }; + DependencyManager::get()->sendRequest(path, AccountManagerAuth::Required, QNetworkAccessManager::PutOperation, JSONCallbackParameters(), domainUpdateJSON.toUtf8()); + +#if DEV_BUILD || PR_BUILD + qDebug() << "Domain metadata sent to" << path; + qDebug() << "Domain metadata update:" << domainUpdateJSON; +#endif } } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index 0bfd6c611b..6573a9076c 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -35,11 +35,17 @@ public: public: static const QString DESCRIPTION; static const QString CAPACITY; - static const QString HOURS; static const QString RESTRICTION; static const QString MATURITY; static const QString HOSTS; static const QString TAGS; + static const QString HOURS; + class Hours { + public: + static const QString WEEKDAY; + static const QString WEEKEND; + static const QString UTC_OFFSET; + }; }; DomainMetadata(QObject* domainServer); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index b03d2c07ae..f5ff479cd3 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include #include #include @@ -69,7 +71,7 @@ DomainServerSettingsManager::DomainServerSettingsManager() : } static const QString MISSING_SETTINGS_DESC_MSG = - QString("Did not find settings decription in JSON at %1 - Unable to continue. domain-server will quit.\n%2 at %3") + QString("Did not find settings description in JSON at %1 - Unable to continue. domain-server will quit.\n%2 at %3") .arg(SETTINGS_DESCRIPTION_RELATIVE_PATH).arg(parseError.errorString()).arg(parseError.offset); static const int MISSING_SETTINGS_DESC_ERROR_CODE = 6; @@ -258,6 +260,29 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList _standardAgentPermissions.clear(); _agentPermissions.clear(); } + + if (oldVersion < 1.5) { + // This was prior to operating hours, so add default hours + static const QString WEEKDAY_HOURS{ "descriptors.weekday_hours" }; + static const QString WEEKEND_HOURS{ "descriptors.weekend_hours" }; + static const QString UTC_OFFSET{ "descriptors.utc_offset" }; + + QVariant* weekdayHours = valueForKeyPath(_configMap.getUserConfig(), WEEKDAY_HOURS, true); + QVariant* weekendHours = valueForKeyPath(_configMap.getUserConfig(), WEEKEND_HOURS, true); + QVariant* utcOffset = valueForKeyPath(_configMap.getUserConfig(), UTC_OFFSET, true); + + + QVariantList allHours { QVariantMap{ { "open", QVariant("00:00") }, { "close", QVariant("23:59") } } }; + *weekdayHours = allHours; + *weekendHours = allHours; + *utcOffset = QVariant(QTimeZone::systemTimeZone().offsetFromUtc(QDateTime::currentDateTime()) / (float)3600); + + // write the new settings to file + persistToFile(); + + // reload the master and user config so the merged config is correct + _configMap.loadMasterAndUserConfig(_argumentList); + } } unpackPermissions();