diff --git a/app/assets/javascripts/admin/components/admin-report-table.js.es6 b/app/assets/javascripts/admin/components/admin-report-table.js.es6 index dc007a79cc4..bf1ea4efaeb 100644 --- a/app/assets/javascripts/admin/components/admin-report-table.js.es6 +++ b/app/assets/javascripts/admin/components/admin-report-table.js.es6 @@ -1,5 +1,4 @@ import computed from "ember-addons/ember-computed-decorators"; -import { registerTooltip, unregisterTooltip } from "discourse/lib/tooltip"; const PAGES_LIMIT = 8; @@ -11,19 +10,6 @@ export default Ember.Component.extend({ perPage: Ember.computed.alias("options.perPage"), page: 0, - didRender() { - this._super(...arguments); - - unregisterTooltip($(".text[data-tooltip]")); - registerTooltip($(".text[data-tooltip]")); - }, - - willDestroyElement() { - this._super(...arguments); - - unregisterTooltip($(".text[data-tooltip]")); - }, - @computed("model.computedLabels.length") twoColumns(labelsLength) { return labelsLength === 2; @@ -52,7 +38,12 @@ export default Ember.Component.extend({ @computed("totalsForSampleRow", "model.computedLabels") totalsForSample(row, labels) { - return labels.map(label => label.compute(row)); + return labels.map(label => { + const computedLabel = label.compute(row); + computedLabel.type = label.type; + computedLabel.property = label.mainProperty; + return computedLabel; + }); }, @computed("model.data", "model.computedLabels") @@ -119,7 +110,7 @@ export default Ember.Component.extend({ return { page: v + 1, index: v, - class: v === page ? "current" : null + class: v === page ? "is-current" : null }; }); diff --git a/app/assets/javascripts/admin/components/admin-report.js.es6 b/app/assets/javascripts/admin/components/admin-report.js.es6 index fa57c3d8213..c126d90ee60 100644 --- a/app/assets/javascripts/admin/components/admin-report.js.es6 +++ b/app/assets/javascripts/admin/components/admin-report.js.es6 @@ -4,7 +4,10 @@ import { outputExportResult } from "discourse/lib/export-result"; import { ajax } from "discourse/lib/ajax"; import { SCHEMA_VERSION, default as Report } from "admin/models/report"; import computed from "ember-addons/ember-computed-decorators"; -import { registerTooltip, unregisterTooltip } from "discourse/lib/tooltip"; +import { + registerHoverTooltip, + unregisterHoverTooltip +} from "discourse/lib/tooltip"; const TABLE_OPTIONS = { perPage: 8, @@ -35,12 +38,7 @@ function collapseWeekly(data, average) { } export default Ember.Component.extend({ - classNameBindings: [ - "isEnabled", - "isLoading", - "dasherizedDataSourceName", - "currentMode" - ], + classNameBindings: ["isEnabled", "isLoading", "dasherizedDataSourceName"], classNames: ["admin-report"], isEnabled: true, disabledLabel: "admin.dashboard.disabled", @@ -69,6 +67,7 @@ export default Ember.Component.extend({ "showDatesOptions", "showGroupOptions" ), + shouldDisplayTrend: Ember.computed.and("showTrend", "model.prev_period"), init() { this._super(...arguments); @@ -80,6 +79,7 @@ export default Ember.Component.extend({ this._super(...arguments); const state = this.get("filters") || {}; + this.setProperties({ category: Category.findById(state.categoryId), groupId: state.groupId, @@ -101,14 +101,13 @@ export default Ember.Component.extend({ didRender() { this._super(...arguments); - unregisterTooltip($(".info[data-tooltip]")); - registerTooltip($(".info[data-tooltip]")); + registerHoverTooltip($(".info[data-tooltip]")); }, willDestroyElement() { this._super(...arguments); - unregisterTooltip($(".info[data-tooltip]")); + unregisterHoverTooltip($(".info[data-tooltip]")); }, showError: Ember.computed.or("showTimeoutError", "showExceptionError"), @@ -140,8 +139,8 @@ export default Ember.Component.extend({ const modes = forcedModes ? forcedModes.split(",") : reportModes; return Ember.makeArray(modes).map(mode => { - const base = `mode-button ${mode}`; - const cssClass = currentMode === mode ? `${base} current` : base; + const base = `mode-btn ${mode}`; + const cssClass = currentMode === mode ? `${base} is-current` : base; return { mode, @@ -157,7 +156,7 @@ export default Ember.Component.extend({ { name: I18n.t("admin.dashboard.reports.groups"), value: "all" } ]; return arr.concat( - this.site.groups.map(i => { + (this.site.groups || []).map(i => { return { name: i["name"], value: i["id"] }; }) ); @@ -171,15 +170,25 @@ export default Ember.Component.extend({ @computed("startDate") normalizedStartDate(startDate) { return startDate && typeof startDate.isValid === "function" - ? startDate.format("YYYYMMDD") - : startDate; + ? moment + .utc(startDate.toISOString()) + .locale("en") + .format("YYYYMMDD") + : moment(startDate) + .locale("en") + .format("YYYYMMDD"); }, @computed("endDate") normalizedEndDate(endDate) { return endDate && typeof endDate.isValid === "function" - ? endDate.format("YYYYMMDD") - : endDate; + ? moment + .utc(endDate.toISOString()) + .locale("en") + .format("YYYYMMDD") + : moment(endDate) + .locale("en") + .format("YYYYMMDD"); }, @computed( @@ -317,16 +326,15 @@ export default Ember.Component.extend({ let payload = { data: { cache: true, facets } }; if (this.get("startDate")) { - payload.data.start_date = moment( - this.get("startDate"), - "YYYY-MM-DD" - ).format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ"); + payload.data.start_date = moment + .utc(this.get("startDate"), "YYYY-MM-DD") + .toISOString(); } if (this.get("endDate")) { - payload.data.end_date = moment(this.get("endDate"), "YYYY-MM-DD").format( - "YYYY-MM-DD[T]HH:mm:ss.SSSZZ" - ); + payload.data.end_date = moment + .utc(this.get("endDate"), "YYYY-MM-DD") + .toISOString(); } if (this.get("groupId") && this.get("groupId") !== "all") { diff --git a/app/assets/javascripts/admin/models/report.js.es6 b/app/assets/javascripts/admin/models/report.js.es6 index fc4fb8e86af..24b2b1ab3e5 100644 --- a/app/assets/javascripts/admin/models/report.js.es6 +++ b/app/assets/javascripts/admin/models/report.js.es6 @@ -285,7 +285,7 @@ const Report = Discourse.Model.extend({ value, type, property: mainProperty, - formatedValue: value ? escapeExpression(value) : "-" + formatedValue: value ? escapeExpression(value) : "—" }; } }; @@ -318,7 +318,7 @@ const Report = Discourse.Model.extend({ return { value: username, - formatedValue: username ? formatedValue(username) : "-" + formatedValue: username ? formatedValue(username) : "—" }; }, @@ -333,7 +333,7 @@ const Report = Discourse.Model.extend({ return { value: topicTitle, - formatedValue: topicTitle ? formatedValue() : "-" + formatedValue: topicTitle ? formatedValue() : "—" }; }, @@ -360,7 +360,7 @@ const Report = Discourse.Model.extend({ _percentLabel(value) { return { value, - formatedValue: value ? `${value}%` : "-" + formatedValue: value ? `${value}%` : "—" }; }, @@ -373,14 +373,14 @@ const Report = Discourse.Model.extend({ return { value, - formatedValue: value ? formatedValue() : "-" + formatedValue: value ? formatedValue() : "—" }; }, _dateLabel(value, date) { return { value, - formatedValue: value ? date.format("LL") : "-" + formatedValue: value ? date.format("LL") : "—" }; }, @@ -389,7 +389,7 @@ const Report = Discourse.Model.extend({ return { value, - formatedValue: value ? escaped : "-" + formatedValue: value ? escaped : "—" }; }, @@ -404,7 +404,7 @@ const Report = Discourse.Model.extend({ return { value, - formatedValue: value ? formatedValue(value, row[properties[1]]) : "-" + formatedValue: value ? formatedValue(value, row[properties[1]]) : "—" }; }, diff --git a/app/assets/javascripts/admin/routes/admin-reports-show.js.es6 b/app/assets/javascripts/admin/routes/admin-reports-show.js.es6 index fbcd9106439..55503091e13 100644 --- a/app/assets/javascripts/admin/routes/admin-reports-show.js.es6 +++ b/app/assets/javascripts/admin/routes/admin-reports-show.js.es6 @@ -5,14 +5,23 @@ export default Discourse.Route.extend({ if (!controller.get("start_date")) { controller.set( "start_date", - moment() - .subtract("30", "day") + moment + .utc() + .subtract(1, "day") + .subtract(1, "month") + .startOf("day") .format("YYYY-MM-DD") ); } if (!controller.get("end_date")) { - controller.set("end_date", moment().format("YYYY-MM-DD")); + controller.set( + "end_date", + moment() + .utc() + .endOf("day") + .format("YYYY-MM-DD") + ); } } }); diff --git a/app/assets/javascripts/admin/templates/components/admin-report-table-header.hbs b/app/assets/javascripts/admin/templates/components/admin-report-table-header.hbs index 4e8f2736c7a..15f85276f5c 100644 --- a/app/assets/javascripts/admin/templates/components/admin-report-table-header.hbs +++ b/app/assets/javascripts/admin/templates/components/admin-report-table-header.hbs @@ -1,5 +1,5 @@ {{#if showSortingUI}} - {{d-button action=sortByLabel icon=sortIcon class="sort-button"}} + {{d-button action=sortByLabel icon=sortIcon class="sort-btn"}} {{/if}} -{{label.title}} +{{label.title}} diff --git a/app/assets/javascripts/admin/templates/components/admin-report-table.hbs b/app/assets/javascripts/admin/templates/components/admin-report-table.hbs index 1eb6923b511..2e6c528accb 100644 --- a/app/assets/javascripts/admin/templates/components/admin-report-table.hbs +++ b/app/assets/javascripts/admin/templates/components/admin-report-table.hbs @@ -1,4 +1,4 @@ - +
{{#if model.computedLabels}} @@ -30,7 +30,7 @@ {{#each totalsForSample as |total|}} - {{/each}} @@ -44,8 +44,8 @@ - - + + {{/if}} diff --git a/app/assets/javascripts/admin/templates/components/admin-report.hbs b/app/assets/javascripts/admin/templates/components/admin-report.hbs index 6e2548a9f6d..37335e56368 100644 --- a/app/assets/javascripts/admin/templates/components/admin-report.hbs +++ b/app/assets/javascripts/admin/templates/components/admin-report.hbs @@ -1,50 +1,99 @@ {{#if isEnabled}} - {{#conditional-loading-section isLoading=isLoading}} - {{#if showHeader}} -
- {{#if showTitle}} -
-

- {{#if showAllReportsLink}} - {{#link-to "adminReports" class="all-report-link"}} - {{i18n "admin.dashboard.all_reports"}} - {{/link-to}} - | - {{/if}} +{{#conditional-loading-section isLoading=isLoading}} + {{#if showHeader}} +
+ {{#if showTitle}} +

+
  • + + {{model.title}} + {{#if model.description}} {{d-icon "question-circle"}} {{/if}} -
  • - {{/if}} + + + {{/if}} - {{#if showTrend}} - {{#if model.prev_period}} -
    - - {{#if model.average}} - {{number model.currentAverage}}{{#if model.percent}}%{{/if}} - {{else}} - {{number model.currentTotal noTitle="true"}}{{#if model.percent}}%{{/if}} - {{/if}} - + {{#if shouldDisplayTrend}} +
    + + {{#if model.average}} + {{number model.currentAverage}}{{#if model.percent}}%{{/if}} + {{else}} + {{number model.currentTotal noTitle="true"}}{{#if model.percent}}%{{/if}} + {{/if}} + - {{#if model.trendIcon}} - {{d-icon model.trendIcon class="trend-icon"}} + {{#if model.trendIcon}} + {{d-icon model.trendIcon class="icon"}} + {{/if}} +
    + {{/if}} +
    + {{/if}} + +
    +
    + {{#unless showError}} + {{#if hasData}} + {{#if currentMode}} + {{component modeComponent model=model options=options}} + + {{#if model.relatedReport}} + {{admin-report showFilteringUI=false dataSourceName=model.relatedReport.type}} + {{/if}} + {{/if}} + {{else}} +
    + {{d-icon "pie-chart"}} + {{#if model.reportUrl}} + + + {{#if model.title}} + {{model.title}} — + {{/if}} + {{i18n "admin.dashboard.reports.no_data"}} + + + {{else}} + {{i18n "admin.dashboard.reports.no_data"}} {{/if}}
    {{/if}} + {{else}} + {{#if showTimeoutError}} +
    + {{d-icon "exclamation-triangle"}} + {{i18n "admin.dashboard.timeout_error"}} +
    {{/if}} + {{#if showExceptionError}} +
    + {{d-icon "exclamation-triangle"}} + {{i18n "admin.dashboard.exception_error"}} +
    + {{/if}} + {{/unless}} +
    + + {{#if showFilteringUI}} +
    {{#if showModes}} -
      +
        {{#each displayedModes as |displayedMode|}}
      • {{d-button @@ -56,118 +105,84 @@ {{/each}}
      {{/if}} + + {{#if showDatesOptions}} +
      + + {{i18n 'admin.dashboard.reports.start_date'}} + + +
      + {{date-picker-past + value=startDate + defaultDate=startDate}} +
      +
      + +
      + + {{i18n 'admin.dashboard.reports.end_date'}} + + +
      + {{date-picker-past + value=endDate + defaultDate=endDate}} +
      +
      + {{/if}} + + {{#if showCategoryOptions}} +
      +
      + {{search-advanced-category-chooser + filterable=true + value=category + castInteger=true}} +
      +
      + {{/if}} + + {{#if showGroupOptions}} +
      +
      + {{combo-box + castInteger=true + filterable=true + valueAttribute="value" + content=groupOptions + value=groupId}} +
      +
      + {{/if}} + + {{#if showExport}} +
      +
      + {{d-button + class="export-csv-btn" + action="exportCsv" + label="admin.export_csv.button_text" + icon="download"}} +
      +
      + {{/if}} + + {{#if showRefresh}} +
      +
      + {{d-button + class="refresh-report-btn btn-primary" + action="refreshReport" + label="admin.dashboard.reports.refresh_report" + icon="refresh"}} +
      +
      + {{/if}}
    {{/if}} - -
    - {{#unless showError}} - {{#if hasData}} - {{#if currentMode}} - {{component modeComponent model=model options=options}} - {{/if}} - {{else}} -
    - {{d-icon "pie-chart"}} - {{i18n "admin.dashboard.reports.no_data"}} -
    - {{/if}} - {{else}} - {{#if showTimeoutError}} -
    - {{i18n "admin.dashboard.timeout_error"}} -
    - {{/if}} - - {{#if showExceptionError}} -
    - {{i18n "admin.dashboard.exception_error"}} -
    - {{/if}} - {{/unless}} - - {{#if showFilteringUI}} -
    - {{#if showDatesOptions}} -
    - - {{i18n 'admin.dashboard.reports.start_date'}} - - -
    - {{date-picker-past - value=startDate - defaultDate=startDate}} -
    -
    - -
    - - {{i18n 'admin.dashboard.reports.end_date'}} - - -
    - {{date-picker-past - value=endDate - defaultDate=endDate}} -
    -
    - {{/if}} - - {{#if showCategoryOptions}} -
    -
    - {{search-advanced-category-chooser - filterable=true - value=category - castInteger=true}} -
    -
    - {{/if}} - - {{#if showGroupOptions}} -
    -
    - {{combo-box - castInteger=true - filterable=true - valueAttribute="value" - content=groupOptions - value=groupId}} -
    -
    - {{/if}} - - {{#if showExport}} -
    -
    - {{d-button - class="export-csv-btn" - action="exportCsv" - label="admin.export_csv.button_text" - icon="download"}} -
    -
    - {{/if}} - - {{#if showRefresh}} -
    -
    - {{d-button - class="refresh-report-btn btn-primary" - action="refreshReport" - label="admin.dashboard.reports.refresh_report" - icon="refresh"}} -
    -
    - {{/if}} -
    - {{/if}} -
    - - {{#if model.relatedReport}} - {{admin-report dataSourceName=model.relatedReport.type}} - {{/if}} - {{/conditional-loading-section}} +
    +{{/conditional-loading-section}} {{else}}
    {{{i18n disabledLabel}}} diff --git a/app/assets/javascripts/admin/templates/dashboard_next_general.hbs b/app/assets/javascripts/admin/templates/dashboard_next_general.hbs index 21bde7bd178..593914f44dc 100644 --- a/app/assets/javascripts/admin/templates/dashboard_next_general.hbs +++ b/app/assets/javascripts/admin/templates/dashboard_next_general.hbs @@ -57,23 +57,23 @@
    -
    -
    -

    - {{#link-to "adminReports" class="report-link"}} +
    +

    -
    + +
    -
    +
    -
    -
    {{i18n 'admin.dashboard.reports.today'}}
    -
    {{i18n 'admin.dashboard.reports.yesterday'}}
    -
    {{i18n 'admin.dashboard.reports.last_7_days'}}
    -
    {{i18n 'admin.dashboard.reports.last_30_days'}}
    +
    +
    {{i18n 'admin.dashboard.reports.today'}}
    +
    {{i18n 'admin.dashboard.reports.yesterday'}}
    +
    {{i18n 'admin.dashboard.reports.last_7_days'}}
    +
    {{i18n 'admin.dashboard.reports.last_30_days'}}
    {{#each activityMetrics as |metric|}} @@ -84,10 +84,11 @@ {{/each}}
    + + {{#link-to "adminReports"}} + {{i18n "admin.dashboard.all_reports"}} + {{/link-to}}
    - {{#link-to "adminReports"}} - {{i18n "admin.dashboard.all_reports"}} - {{/link-to}}
    {{#conditional-loading-section isLoading=isLoading}} diff --git a/app/assets/javascripts/discourse/lib/tooltip.js.es6 b/app/assets/javascripts/discourse/lib/tooltip.js.es6 index 1beabf6f86b..6028a87d3a1 100644 --- a/app/assets/javascripts/discourse/lib/tooltip.js.es6 +++ b/app/assets/javascripts/discourse/lib/tooltip.js.es6 @@ -1,8 +1,9 @@ import { escapeExpression } from "discourse/lib/utilities"; +const fadeSpeed = 300; +const tooltipID = "#discourse-tooltip"; + export function showTooltip() { - const fadeSpeed = 300; - const tooltipID = "#discourse-tooltip"; const $this = $(this); const $parent = $this.offsetParent(); const content = escapeExpression($this.attr("data-tooltip")); @@ -16,9 +17,7 @@ export function showTooltip() { pos.top -= delta.top; pos.left -= delta.left; - $(tooltipID) - .fadeOut(fadeSpeed) - .remove(); + hideTooltip(tooltipID); $(this).after(`
    @@ -67,9 +66,24 @@ export function showTooltip() { return false; } +export function hideTooltip() { + $(tooltipID) + .fadeOut(fadeSpeed) + .remove(); +} + export function registerTooltip(jqueryContext) { if (jqueryContext.length) { - jqueryContext.on("click", showTooltip); + jqueryContext.off("click").on("click", showTooltip); + } +} + +export function registerHoverTooltip(jqueryContext) { + if (jqueryContext.length) { + jqueryContext + .off("mouseenter mouseleave click") + .on("mouseenter click", showTooltip) + .on("mouseleave", hideTooltip); } } @@ -78,3 +92,9 @@ export function unregisterTooltip(jqueryContext) { jqueryContext.off("click"); } } + +export function unregisterHoverTooltip(jqueryContext) { + if (jqueryContext.length) { + jqueryContext.off("mouseenter mouseleave click"); + } +} diff --git a/app/assets/stylesheets/common/admin/admin_report.scss b/app/assets/stylesheets/common/admin/admin_report.scss index e458826aeb2..de14fe43881 100644 --- a/app/assets/stylesheets/common/admin/admin_report.scss +++ b/app/assets/stylesheets/common/admin/admin_report.scss @@ -1,70 +1,36 @@ .admin-report { - .report-error, - .no-data { - width: 100%; - width: 100%; - align-self: flex-start; - text-align: center; - padding: 3em; - margin-bottom: 1.5em; - box-sizing: border-box; - } - - + .table { - margin-top: 1.5em; - } - - .report-error { - color: $danger; - border: 1px solid $danger; - } - - .no-data { - background: $secondary; - border: 1px solid $primary-low; - color: $primary-low-mid; - - .d-icon-pie-chart { - color: currentColor; - margin-bottom: 0.25em; - font-size: $font-up-5; - display: block; + .conditional-loading-section { + &.is-loading { + margin: 0; } } - .conditional-loading-section { - flex: 1; - margin: 0; + .header { + display: flex; + align-items: center; + border-bottom: 1px solid $primary-low; + margin-bottom: 0.5em; + padding-bottom: 0.5em; } - .report-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 0.5em; - margin-bottom: 0.5em; + .header .breadcrumb { + margin: 0; + list-style: none; - .report-title { - align-items: center; - display: flex; - justify-content: space-between; + .item { + display: inline; + font-size: $font-up-1; + } - .title { - margin: 0; - padding: 0; - border: 0; - font-size: $font-up-1; - .separator { - font-weight: normal; - } + .all-reports .report-url { + font-weight: 700; + } - .report-link { - color: $primary; - } + .report { + font-weight: 700; - .separator + .report-link { - font-weight: normal; - } + .report-url { + color: $primary; } .info { @@ -77,167 +43,134 @@ } } } + } - .trend { - align-items: center; - - &.trending-down, - &.high-trending-down { - color: $danger; - } - - &.trending-up, - &.high-trending-up { - color: $success; - } - - &.no-change { - color: $primary-medium; - } - - .trend-value { - font-size: $font-up-1; - } - - .trend-icon { - font-size: $font-up-1; - font-weight: 700; - } + .header .trend { + margin-left: auto; + &.trending-down, + &.high-trending-down { + color: $danger; } - .mode-switch { + &.trending-up, + &.high-trending-up { + color: $success; + } + + &.no-change { + color: $primary-medium; + } + + .value { + font-size: $font-up-1; + } + + .icon { + font-size: $font-up-1; + font-weight: 700; + } + } + + .body { + display: flex; + } + + .main { + flex: 1; + } + + .main .report-alert { + margin: 0; + text-align: center; + padding: 3em; + border: 1px solid transparent; + + a { + color: $primary-medium; + } + + .d-icon { + color: currentColor; + margin-bottom: 0.25em; + font-size: $font-up-5; + display: block; + } + + &.no-data { + background: $secondary; + border-color: $primary-low; + color: $primary-low-mid; + } + + &.timeout, + &.exception { + border-color: $danger-low; + color: $danger; + } + } + + .filters { + display: flex; + margin-left: 1em; + flex-direction: column; + width: 220px; + + .modes { + margin: 0 0 1em 0; + padding: 0; list-style: none; - display: flex; - margin: 0; .mode { - display: inline; + display: inline-flex; + flex: 1; - .mode-button.current { + .mode-btn.is-current { color: $tertiary; } } } - } - .report-body { - display: flex; - justify-content: space-between; + .control { + margin-bottom: 1em; + } - .admin-report-table, - .admin-report-chart { + .control .label { + font-weight: 700; width: 100%; } - .report-filters { - margin-left: 1em; - min-width: 250px; - display: flex; - flex-direction: column; + .control .input, + .control .select-kit { + width: 100%; - .filtering-control { - display: flex; - flex-direction: column; - margin-bottom: 1em; - } - .filtering-label { - } - .filtering-input { + .export-csv-btn { width: 100%; + } - .date-picker-wrapper, - .combo-box, - .export-csv-btn, - .refresh-report-btn { + .refresh-report-btn { + width: 100%; + } + + .date-picker-wrapper { + width: 100%; + .date-picker { + box-sizing: border-box; width: 100%; - } - - .date-picker-wrapper { - .date-picker { - width: 100%; - box-sizing: border-box; - margin: 0; - } + margin: 0; } } } - - .report-filters:only-child { - margin-left: auto; - } } } -.admin-report.activity-metrics { - table { - table-layout: auto; - } -} - -.admin-report.users-by-type { - margin-top: 1.5em; -} - -.admin-report.users-by-type, -.admin-report.users-by-trust-level { - margin-bottom: 1.5em; - flex: 1; - .report-header { - border-bottom: 1px solid $primary-medium; - padding-bottom: 0.25em; - border-bottom: 1px solid #e9e9e9; - } -} - -.admin-report.moderators-activity { - tbody tr td.username, - thead tr th.username { - text-align: left; - } -} - -.admin-report.trending-search { - tbody tr td.term, - thead tr th.term { - text-align: left; - } -} - -.admin-report.top-traffic-sources { - tbody tr td.domain, - thead tr th.domain { - text-align: left; - } -} - -.admin-report.post-edits { - .report-table { - table-layout: auto; - - tbody tr td, - thead tr th { - text-align: left; - } - - thead tr th.edit_reason, - tbody tr td.edit_reason { - width: 100%; - } - } -} - -.admin-report.flags-status { - .admin-report-table { - table-layout: auto; - - tbody tr td, - thead tr th { - text-align: left; - } - - tbody tr td.response_time, - thead tr th.response_time { - text-align: center; - } +.rtl .admin-report { + .filters { + margin-left: 0; + margin-right: 1em; + } + + .trend { + margin-left: unset; + margin-right: auto; } } diff --git a/app/assets/stylesheets/common/admin/admin_report_counters.scss b/app/assets/stylesheets/common/admin/admin_report_counters.scss index ac7c8610b96..74f2f64be21 100644 --- a/app/assets/stylesheets/common/admin/admin_report_counters.scss +++ b/app/assets/stylesheets/common/admin/admin_report_counters.scss @@ -1,67 +1,21 @@ -.admin-report-counters-list { - display: flex; - flex: 1; - flex-direction: column; - border-bottom: 1px solid $primary-low; - - .counters-header { - display: grid; - flex: 1; - grid-template-columns: 33% repeat(auto-fit, minmax(20px, 1fr)); - border: 1px solid $primary-low; - border-bottom: 0; - padding: 0.25em; - font-weight: 700; - text-align: right; - } - - .conditional-loading-section.is-loading { - padding: 0.5em; - margin: 0; - flex-direction: row; - justify-content: flex-start; - - .title { - font-weight: normal; - font-size: $font-down-1; - } - - .spinner { - margin: 0 0 0 0.5em; - height: 5px; - width: 5px; - } - } -} - -.admin-report.counters { +.admin-report { .admin-report-counters { display: grid; flex: 1; grid-template-columns: 33% repeat(auto-fit, minmax(20px, 1fr)); grid-template-rows: repeat(auto-fit, minmax(32px, 1fr)); - border: 1px solid $primary-low; align-items: center; - border-bottom: 0; .cell { padding: 0.25em; text-align: right; white-space: nowrap; - padding: 8px 21px 8px 8px; // accounting for negative right caret margin - &:nth-of-type(2) { - padding: 8px 12px 8px; - } - i { - margin-right: -12px; // align on caret - @media screen and (max-width: 650px) { - margin-right: -9px; - } - } &.title { text-align: left; - padding: 8px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; .d-icon { color: $primary-low-mid; @@ -75,13 +29,8 @@ } @media screen and (max-width: 400px) { - &.title { - padding: 8px 0 8px 4px; - font-size: $font-down-1; - - .d-icon { - display: none; - } + &.title .d-icon { + display: none; } } @@ -99,27 +48,18 @@ } } } +} - .no-data { - margin: 0; - padding: 8px; - display: flex; - flex-direction: row; - align-items: center; - font-size: $font-0; - border-bottom: 0; - color: $primary-medium; - .d-icon { - font-size: $font-up-1; - margin: 0 0.25em 0 0; - color: $primary-low-mid; +.rtl .counters-list .counters-header .counters-cell { + text-align: left; +} + +.rtl .counters-list { + .cell { + text-align: left; + + &.title { + text-align: right; } } - - .alert-error { - text-align: left; - padding: 0.5em; - margin: 0; - border: 0; - } } diff --git a/app/assets/stylesheets/common/admin/admin_report_table.scss b/app/assets/stylesheets/common/admin/admin_report_table.scss index 733ab5620fb..7fc1661fb20 100644 --- a/app/assets/stylesheets/common/admin/admin_report_table.scss +++ b/app/assets/stylesheets/common/admin/admin_report_table.scss @@ -1,9 +1,74 @@ .admin-report-table { - @media screen and (max-width: 650px) { - table { - tbody tr td { - font-size: $font-down-1; + &.two-columns { + .table .admin-report-table-cell:first-child, + .table .admin-report-table-header:first-child { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + text-align: left; + width: 80%; + } + + .table .admin-report-table-cell:last-child, + .table .admin-report-table-header:last-child { + display: inline-block; + width: 80%; + text-align: right; + } + } + + .table { + margin: 0; + border: 1px solid $primary-low; + table-layout: fixed; + + tbody { + border-top: 0; + } + } + + .table .admin-report-table-header { + .sort-btn { + outline: none; + background: none; + padding: 3px 8px; + overflow: hidden; + text-overflow: ellipsis; + } + + &.is-current-sort { + .d-icon { + color: $tertiary; } + + .sort-btn:hover { + color: $primary-medium; + background: $primary-low; + } + } + + &:not(.is-current-sort) .sort-btn { + background: none; + + &:hover { + color: $primary-medium; + background: $primary-low; + } + } + } + + .admin-report-table-cell { + &.user .username { + margin-left: 0.25em; + } + } + + .total-row { + background: $primary-very-low; + + td { + font-weight: 700; + text-align: left; } } @@ -15,98 +80,114 @@ button { margin-left: 0.5em; - &.current { + &.is-current { color: $tertiary; } } } +} - &.two-columns { - .report-table tbody tr td:first-child, - .report-table thead tr th:first-child { - text-align: left; +.admin-report.top-referred-topics { + .admin-report-table-header.topic_title { + width: 80%; + } +} + +.admin-report.trending-search { + .admin-report-table-header.ctr, + .admin-report-table-header.unique_searches, + .admin-report-table-cell.ctr, + .admin-report-table-cell.unique_searches { + text-align: center; + width: 20%; + } + + .admin-report-table-cell.term { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } +} + +.admin-report.moderators-activity { + .admin-report-table-header.seconds, + .admin-report-table-header.number, + .admin-report-table-cell.seconds, + .admin-report-table-cell.number { + text-align: center; + } + + .admin-report-table-header.user { + width: 20%; + } +} + +.admin-report.post-edits { + .admin-report-table-header.user { + width: 20%; + } + + .admin-report-table-cell.post, + .admin-report-table-cell.edit_reason { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } +} + +.admin-report.flags-status { + .admin-report-table-header.response_time, + .admin-report-table-cell.response_time { + text-align: center; + } +} + +.rtl { + .admin-report-table { + &.two-columns { + .table .admin-report-table-cell:first-child, + .table .admin-report-table-header:first-child { + text-align: right; + } + + .table .admin-report-table-cell:last-child, + .table .admin-report-table-header:last-child { + text-align: left; + } } - .report-table { - table-layout: auto; + .total-row { + td { + text-align: right; + } } } - .report-table { - table-layout: fixed; - border: 1px solid $primary-low; - margin-top: 0; - - tbody { - border: none; - - .total-row { - td { - font-weight: 700; - text-align: left; - } - } - - tr { - td { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - text-align: center; - padding: 8px; - - &.user { - text-align: left; - - .username { - margin-left: 3px; - } - } - } - } + .admin-report-table-cell { + &.user .username { + margin-left: 0; + margin-right: 0.25em; } + } - thead { - border: 1px solid $primary-low; + .admin-report.trending-search { + .admin-report-table-header.term, + .admin-report-table-cell.term { + text-align: right; + } + } - .admin-report-table-header { - .sort-button { - outline: none; - background: none; - padding: 3px 7px; - overflow: hidden; - text-overflow: ellipsis; - } + .pagination { + button { + margin-left: 0; + margin-right: 0.5em; + } + } - &.is-current-sort { - .d-icon { - color: $tertiary; - } - - .sort-button:hover { - color: $primary-medium; - background: $primary-low; - } - } - - &:not(.is-current-sort) .sort-button { - background: none; - - &:hover { - color: $primary-medium; - background: $primary-low; - } - } - } - - tr { - th { - text-align: center; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - } + .admin-report.moderators-activity { + .admin-report-table-header.user, + .admin-report-table-cell.user { + text-align: right; } } } diff --git a/app/assets/stylesheets/common/admin/dashboard_next.scss b/app/assets/stylesheets/common/admin/dashboard_next.scss index d51686212d6..42d6bcd1443 100644 --- a/app/assets/stylesheets/common/admin/dashboard_next.scss +++ b/app/assets/stylesheets/common/admin/dashboard_next.scss @@ -62,11 +62,11 @@ max-width: 100%; &:last-child { - margin-left: 1em; + margin-left: 0.5em; } &:first-child { - margin-right: 1em; + margin-right: 0.5em; } @include breakpoint(medium) { @@ -119,22 +119,25 @@ } } - .charts { - display: flex; - justify-content: space-between; - flex-wrap: wrap; + .admin-report .header { + border: 0; + padding: 0; + margin-bottom: 1em; + } - .chart { - max-width: calc(100% * 1 / 3.2); - width: 100%; - flex-grow: 1; - flex-basis: 100%; - display: flex; + .charts { + display: grid; + grid-template-columns: repeat(12, 1fr); + grid-column-gap: 1em; + grid-row-gap: 1em; + + .admin-report { + grid-column: span 4; } @include breakpoint(medium) { - .chart { - max-width: 100%; + .admin-report { + grid-column: span 12; } } @@ -209,6 +212,10 @@ } } + .top-referred-topics { + margin-bottom: 1.5em; + } + .top-referred-topics, .trending-search { th:first-of-type { @@ -216,12 +223,6 @@ } } - .top-referred-topics { - .dashboard-table table { - table-layout: auto; - } - } - .section { .period-chooser .period-chooser-header { .selected-name, @@ -248,27 +249,82 @@ } } -.admin-report-table { - &.is-disabled { - background: $primary-low; - padding: 1em; +.counters-list { + display: flex; + flex: 1; + flex-direction: column; + + .counters-header { + display: grid; + flex: 1; + grid-template-columns: 33% repeat(auto-fit, minmax(20px, 1fr)); + border: 1px solid $primary-low; + border-bottom: 0; + font-weight: 700; + text-align: right; + align-items: center; + padding: 0.65em 0.25em; } - @media screen and (max-width: 650px) { - table { - tbody tr td { - font-size: $font-down-1; - } + .admin-report .main { + border: 1px solid $primary-low; + + &:hover { + background-color: $primary-very-low; } } - &.is-loading { - height: 150px; + .admin-report:not(:last-child) { + .main { + border-bottom: 0; + } + + .conditional-loading-section.is-loading { + border-bottom: 0; + } + } + + .admin-report .conditional-loading-section.is-loading { + display: flex; + flex-direction: row; + padding: 0.5em 0.25em; + align-items: flex-start; + justify-content: flex-start; + border: 1px solid $primary-low; + + .title { + font-size: $font-0; + } + + .spinner { + margin: 0; + width: 8px; + height: 8px; + margin-left: 0.5em; + } + } + + .admin-report .main .report-alert { + display: flex; + flex-direction: row; + padding: 0.5em 0.25em; + align-items: center; + border: 0; + + &:hover { + background-color: $primary-very-low; + } + + .d-icon { + font-size: $font-up-1; + margin: 0 0.25em 0 0; + color: $primary-low-mid; + } } } .activity-metrics { - margin-bottom: 0.25em; + margin-bottom: 1.5em; } .user-metrics { @@ -368,21 +424,32 @@ } } -.community-health.section { - margin-bottom: 1em; +.users-by-trust-level, +.users-by-type { + margin-bottom: 1.5em; } -.dashboard-next.moderation { +.community-health.section { + margin-bottom: 1.5em; +} + +.dashboard-next-moderation { .admin-dashboard-moderation-top { display: grid; grid-template-columns: repeat(12, 1fr); grid-column-gap: 1em; + grid-row-gap: 1em; + } + + .section-body { + margin-bottom: 1em; } .main-section { display: grid; grid-template-columns: repeat(12, 1fr); grid-column-gap: 1em; + grid-row-gap: 1em; > * { grid-column: span 12; @@ -392,6 +459,7 @@ display: grid; grid-template-columns: repeat(12, 1fr); grid-column-gap: 1em; + grid-row-gap: 1em; } } diff --git a/app/assets/stylesheets/mobile.scss b/app/assets/stylesheets/mobile.scss index e7330a79f6b..d8c5f7ffc55 100644 --- a/app/assets/stylesheets/mobile.scss +++ b/app/assets/stylesheets/mobile.scss @@ -22,9 +22,11 @@ @import "mobile/ring"; @import "mobile/group"; @import "mobile/groups"; +@import "mobile/dashboard_next"; @import "mobile/admin_reports"; @import "mobile/admin_report"; @import "mobile/admin_report_table"; +@import "mobile/admin_report_counters"; // Import all component-specific files @import "mobile/components/*"; diff --git a/app/assets/stylesheets/mobile/admin_report.scss b/app/assets/stylesheets/mobile/admin_report.scss index 2af96e2b4fc..4b9c8a467f8 100644 --- a/app/assets/stylesheets/mobile/admin_report.scss +++ b/app/assets/stylesheets/mobile/admin_report.scss @@ -9,27 +9,9 @@ } } -.admin-report.top-referred-topics { - .admin-report-table { - .report-table { - table-layout: fixed; - - thead tr th.topic_title, - tbody tr td.topic_title { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - width: 80%; - } - } - } -} - .admin-report.trending-search { .admin-report-table { .report-table { - table-layout: fixed; - thead tr th.term, tbody tr td.term { width: 50%; diff --git a/app/assets/stylesheets/mobile/admin_report_counters.scss b/app/assets/stylesheets/mobile/admin_report_counters.scss new file mode 100644 index 00000000000..ec10485f99b --- /dev/null +++ b/app/assets/stylesheets/mobile/admin_report_counters.scss @@ -0,0 +1,5 @@ +.counters-list { + .counters-header .counters-cell { + font-weight: normal; + } +} diff --git a/app/assets/stylesheets/mobile/admin_report_table.scss b/app/assets/stylesheets/mobile/admin_report_table.scss index a0779794950..73497ff27df 100644 --- a/app/assets/stylesheets/mobile/admin_report_table.scss +++ b/app/assets/stylesheets/mobile/admin_report_table.scss @@ -1,14 +1,28 @@ .admin-report-table { - .report-table { - table-layout: fixed; + .table { + font-size: $font-down-1; + } - thead tr th { - font-weight: normal; - font-size: $font-down-2; - white-space: unset; - .sort-button { - display: none; - } + .table .admin-report-table-header { + font-weight: 500; + border-right: 1px solid $primary-low; + padding: auto; + + .title { + writing-mode: vertical-rl; + text-orientation: mixed; + text-align: right; + transform: rotate(180deg); + } + + .sort-btn { + display: none; + } + } + + .table tbody tr td { + &.user .username { + display: none; } } } diff --git a/app/assets/stylesheets/mobile/admin_reports.scss b/app/assets/stylesheets/mobile/admin_reports.scss index 210d4e33fdb..0179cd4161c 100644 --- a/app/assets/stylesheets/mobile/admin_reports.scss +++ b/app/assets/stylesheets/mobile/admin_reports.scss @@ -1,24 +1,24 @@ .admin-reports { .admin-report { - .report-body { + .body { flex-direction: column; - .report-filters { + .filters { order: 0; margin: 0; + width: 100%; } - .alert { + .main { + order: 2; + } + + .report-alert { margin: 0; order: 1; flex: 1; padding: 1em; } - - .admin-report-table, - .admin-report-chart { - order: 2; - } } } } diff --git a/app/assets/stylesheets/mobile/dashboard_next.scss b/app/assets/stylesheets/mobile/dashboard_next.scss new file mode 100644 index 00000000000..38fd6240796 --- /dev/null +++ b/app/assets/stylesheets/mobile/dashboard_next.scss @@ -0,0 +1,5 @@ +.dashboard-next { + .activity-metrics .counters-list { + font-size: $font-down-1; + } +} diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index 945283cab9a..ae90288ec1f 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -23,8 +23,8 @@ class Admin::ReportsController < Admin::AdminController raise Discourse::NotFound unless report_type =~ /^[a-z0-9\_]+$/ - start_date = (params[:start_date].present? ? params[:start_date].to_date : 30.days.ago).beginning_of_day - end_date = (params[:end_date].present? ? params[:end_date].to_date : start_date + 30.days).end_of_day + start_date = (params[:start_date].present? ? Time.parse(params[:start_date]).to_date : 1.days.ago).beginning_of_day + end_date = (params[:end_date].present? ? Time.parse(params[:end_date]).to_date : start_date + 30.days).end_of_day if params.has_key?(:category_id) && params[:category_id].to_i > 0 category_id = params[:category_id].to_i diff --git a/app/models/report.rb b/app/models/report.rb index a732480f519..8e5e797d240 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -18,8 +18,8 @@ class Report def initialize(type) @type = type - @start_date ||= Report.default_days.days.ago.beginning_of_day - @end_date ||= Time.now.end_of_day + @start_date ||= Report.default_days.days.ago.utc.beginning_of_day + @end_date ||= Time.now.utc.end_of_day @prev_end_date = @start_date @average = false @percent = false diff --git a/test/javascripts/components/admin-report-test.js.es6 b/test/javascripts/components/admin-report-test.js.es6 index 59e94c564a5..d7a94d1068a 100644 --- a/test/javascripts/components/admin-report-test.js.es6 +++ b/test/javascripts/components/admin-report-test.js.es6 @@ -10,12 +10,10 @@ componentTest("default", { async test(assert) { assert.ok(exists(".admin-report.signups")); - assert.ok( - exists(".admin-report.table.signups", "it defaults to table mode") - ); + assert.ok(exists(".admin-report.signups", "it defaults to table mode")); assert.equal( - find(".report-header .title") + find(".header .item.report") .text() .trim(), "Signups", @@ -23,13 +21,13 @@ componentTest("default", { ); assert.equal( - find(".report-header .info").attr("data-tooltip"), + find(".header .info").attr("data-tooltip"), "New account registrations for this period", "it has a description" ); assert.equal( - find(".report-body .report-table thead tr th:first-child") + find(".admin-report-table thead tr th:first-child .title") .text() .trim(), "Day", @@ -37,7 +35,7 @@ componentTest("default", { ); assert.equal( - find(".report-body .report-table thead tr th:nth-child(2)") + find(".admin-report-table thead tr th:nth-child(2) .title") .text() .trim(), "Count", @@ -45,7 +43,7 @@ componentTest("default", { ); assert.equal( - find(".report-body .report-table tbody tr:nth-child(1) td:nth-child(1)") + find(".admin-report-table tbody tr:nth-child(1) td:nth-child(1)") .text() .trim(), "June 16, 2018", @@ -53,7 +51,7 @@ componentTest("default", { ); assert.equal( - find(".report-body .report-table tbody tr:nth-child(1) td:nth-child(2)") + find(".admin-report-table tbody tr:nth-child(1) td:nth-child(2)") .text() .trim(), "12", @@ -62,9 +60,10 @@ componentTest("default", { assert.ok(exists(".total-row"), "it has totals"); - await click(".admin-report-table-header.y .sort-button"); + await click(".admin-report-table-header.y .sort-btn"); + assert.equal( - find(".report-body .report-table tbody tr:nth-child(1) td:nth-child(2)") + find(".admin-report-table tbody tr:nth-child(1) td:nth-child(2)") .text() .trim(), "7", @@ -98,13 +97,13 @@ componentTest("options", { }); componentTest("switch modes", { - template: "{{admin-report dataSourceName='signups'}}", + template: "{{admin-report dataSourceName='signups' showFilteringUI=true}}", async test(assert) { - await click(".mode-button.chart"); + await click(".mode-btn.chart"); - assert.notOk(exists(".admin-report.table.signups"), "it removes the table"); - assert.ok(exists(".admin-report.chart.signups"), "it shows the chart"); + assert.notOk(exists(".admin-report-table"), "it removes the table"); + assert.ok(exists(".admin-report-chart"), "it shows the chart"); } });
    + {{total.formatedValue}}
    -{{number model.total}}{{number model.total}}