diff --git a/.github/workflows/frontend.yaml b/.github/workflows/frontend.yaml index b58a560ec..11e5d720b 100644 --- a/.github/workflows/frontend.yaml +++ b/.github/workflows/frontend.yaml @@ -28,7 +28,7 @@ jobs: strategy: matrix: - target: [js, hbs] + target: [js, hbs, css] steps: - uses: actions/checkout@v4 diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 000000000..72f4d1971 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + "prettier-plugin-tailwindcss" + ] +} \ No newline at end of file diff --git a/frontend/.stylelintrc.js b/frontend/.stylelintrc.js index 4889135cd..6c1f7cadb 100644 --- a/frontend/.stylelintrc.js +++ b/frontend/.stylelintrc.js @@ -2,9 +2,23 @@ module.exports = { plugins: ["stylelint-prettier"], - extends: ["stylelint-prettier/recommended", "stylelint-config-standard-scss"], + extends: ["stylelint-prettier/recommended", "stylelint-config-standard"], rules: { - "scss/at-extend-no-missing-placeholder": null, - "selector-class-pattern": null, + "custom-property-empty-line-before": null, // we use empty lines to group/order properties + "at-rule-empty-line-before": ["never", { ignoreAtRules: ["import"] }], // we use empty lines to group/order imports (su) + "selector-class-pattern": null, // we can ignore this because most css is styling 3rd party components where we don't control the class names + "import-notation": null, // doesn't really work with postcss-import + "at-rule-no-unknown": [ + true, + { + ignoreAtRules: ["apply"], // ignore tailwind decorators + }, + ], + "function-no-unknown": [ + true, + { + ignoreFunctions: ["theme"], // ignore tailwind functions + }, + ], }, }; diff --git a/frontend/.template-lintrc-ci.js b/frontend/.template-lintrc-ci.js deleted file mode 100644 index 6326407a0..000000000 --- a/frontend/.template-lintrc-ci.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; - -module.exports = { - extends: "recommended", - rules: { - // following rules are for temporary use only, delete when ember 4.0 ready - "no-action": "warn", - "no-curly-component-invocation": "warn", - "no-duplicate-id": "warn", - "no-link-to-positional-params": "warn", - "no-link-to-tagname": "warn", - "no-invalid-interactive": "warn", - "no-implicit-this": "warn", - "no-passed-in-event-handlers": "warn", - "no-positional-data-test-selectors": "warn", - "no-unknown-arguments-for-builtin-components": "warn", - "no-with": "warn", - "no-yield-only": "warn", - "require-input-label": "warn", - "require-has-block-helper": "warn", - "require-presentational-children": "warn", - }, -}; diff --git a/frontend/.template-lintrc.js b/frontend/.template-lintrc.js index d1311e116..4386ab2c8 100644 --- a/frontend/.template-lintrc.js +++ b/frontend/.template-lintrc.js @@ -1,5 +1,6 @@ "use strict"; module.exports = { - extends: "recommended", + plugins: ["ember-template-lint-plugin-prettier"], + extends: ["recommended", "ember-template-lint-plugin-prettier:recommended"], }; diff --git a/frontend/app/abilities/report.js b/frontend/app/abilities/report.js index f6cf1cc20..2aeb2b396 100644 --- a/frontend/app/abilities/report.js +++ b/frontend/app/abilities/report.js @@ -22,7 +22,7 @@ export default class ReportAbility extends Ability { (this.model?.taskAssignees ?? []) .concat( this.model?.projectAssignees ?? [], - this.model?.customerAssignees ?? [] + this.model?.customerAssignees ?? [], ) .filter((a) => a?.user) .map((a) => a.user.get("id")) diff --git a/frontend/app/analysis/edit/controller.js b/frontend/app/analysis/edit/controller.js index 641ec99de..231e6ab6b 100644 --- a/frontend/app/analysis/edit/controller.js +++ b/frontend/app/analysis/edit/controller.js @@ -103,7 +103,7 @@ export default class AnalysisEditController extends Controller { })}`, { method: "GET", - } + }, ); yield this.store.pushPayload("report-intersection", res); @@ -252,9 +252,9 @@ export default class AnalysisEditController extends Controller { underscoreQueryParams( serializeQueryParams( filterQueryParams(params, "editable"), - queryParamsState(this) - ) - ) + queryParamsState(this), + ), + ), ); } } diff --git a/frontend/app/analysis/edit/template.hbs b/frontend/app/analysis/edit/template.hbs index 630dd91df..c85a7f859 100644 --- a/frontend/app/analysis/edit/template.hbs +++ b/frontend/app/analysis/edit/template.hbs @@ -1,41 +1,55 @@ -
+
-
+
{{#if this.intersection.isRunning}} -
+ -
+ {{else}} -

- {{#if (eq this.intersection.lastSuccessful.value.meta.count 1)}} - Edit report - {{else}} - Bulk edit - {{this.intersection.lastSuccessful.value.meta.count}} - reports - {{/if}} -

-
-
- {{#let this.intersection.lastSuccessful.value.model as |model|}} - - + + +

+ {{#if + (eq this.intersection.lastSuccessful.value.meta.count 1) }} - as |t| - > - + Edit report + {{else}} + Bulk edit + {{this.intersection.lastSuccessful.value.meta.count}} + reports + {{/if}} +

+
+ + + +
- + - {{#if model.task.project.customerVisible}} - - {{/if}} - - - Not billable - {{#if (eq model.notBillable null)}} - - {{/if}} - {{#if (not-eq f.model.notBillable model.notBillable)}} - - {{/if}} - - +
+ + + Not billable + {{#if (eq model.notBillable null)}} + + {{/if}} + {{#if (not-eq f.model.notBillable model.notBillable)}} + + {{/if}} + + - - - Needs Review - {{#if (eq model.review null)}} - - {{/if}} - {{#if (not-eq f.model.review model.review)}} - - {{/if}} - - + + + Needs Review + {{#if (eq model.review null)}} + + {{/if}} + {{#if (not-eq f.model.review model.review)}} + + {{/if}} + + - - - Reject report - {{#if (eq model.rejected null)}} - - {{/if}} - {{#if (not-eq f.model.rejected model.rejected)}} - - {{/if}} - - + + + Reject report + {{#if (eq model.rejected null)}} + + {{/if}} + {{#if (not-eq f.model.rejected model.rejected)}} + + {{/if}} + + - - - Billed - {{#if (eq model.billed null)}} - - {{/if}} - {{#if (not-eq f.model.billed model.billed)}} - - {{/if}} - - + + + Billed + {{#if (eq model.billed null)}} + + {{/if}} + {{#if (not-eq f.model.billed model.billed)}} + + {{/if}} + + - - - Verified - {{#if (eq model.verified null)}} - - {{/if}} - {{#if (not-eq f.model.verified model.verified)}} - - {{/if}} - - + + + Verified + {{#if (eq model.verified null)}} + + {{/if}} + {{#if (not-eq f.model.verified model.verified)}} + + {{/if}} + + +
-
+ + +
-
- - - {{/let}} -
-
+ + + + + + {{/let}} {{/if}}
- + \ No newline at end of file diff --git a/frontend/app/analysis/index/controller.js b/frontend/app/analysis/index/controller.js index 91b58b9f7..bd6cdbd86 100644 --- a/frontend/app/analysis/index/controller.js +++ b/frontend/app/analysis/index/controller.js @@ -199,7 +199,7 @@ export default class AnalysisController extends QPController { data = enqueueTask(async () => { const params = underscoreQueryParams( - serializeQueryParams(this.allQueryParams, queryParamsState(this)) + serializeQueryParams(this.allQueryParams, queryParamsState(this)), ); if (this._canLoadMore) { @@ -219,24 +219,24 @@ export default class AnalysisController extends QPController { "taskAssignees", assignees.taskAssignees.filter( (taskAssignee) => - report.get("task.id") === taskAssignee.get("task.id") - ) + report.get("task.id") === taskAssignee.get("task.id"), + ), ); report.set( "projectAssignees", assignees.projectAssignees.filter( (projectAssignee) => report.get("task.project.id") === - projectAssignee.get("project.id") - ) + projectAssignee.get("project.id"), + ), ); report.set( "customerAssignees", assignees.customerAssignees.filter( (customerAssignee) => report.get("task.project.customer.id") === - customerAssignee.get("customer.id") - ) + customerAssignee.get("customer.id"), + ), ); return report; }); @@ -315,10 +315,10 @@ export default class AnalysisController extends QPController { ...params, ...serializeQueryParams( this.allQueryParams, - queryParamsState(this) + queryParamsState(this), ), - }) - ) + }), + ), ); const res = yield fetch(`${url}?${queryString}`, { @@ -345,7 +345,7 @@ export default class AnalysisController extends QPController { } catch (e) { /* istanbul ignore next */ this.notify.error( - "Error while downloading, try again or try reducing results" + "Error while downloading, try again or try reducing results", ); } } diff --git a/frontend/app/analysis/index/template.hbs b/frontend/app/analysis/index/template.hbs index f35ba5d1a..621c60401 100644 --- a/frontend/app/analysis/index/template.hbs +++ b/frontend/app/analysis/index/template.hbs @@ -1,248 +1,221 @@ -{{#if (or (media "isMo") (media "isXs") (media "isSm"))}} +{{#if (not (media "isMd"))}} {{else}} -

Analysis

+

Analysis

{{#unless this.prefetchData.isRunning}} - - + - - Customer - - - - - - Project - - - - - - Task - - - - - - Comment - + + + + + + + + + + {{#let (unique-id) as |id|}} - + {{/let}} - - - User - - - - - - - - Reviewer - - - - - - + + + + + + + + + + + - - Billing type - - - - Cost center - - + + - - From - - - - To - - + + - - Review - - - - Billability - - - - Verified - - - - Billed - - - - Editable - - - - Rejected - - + + + + + + - - + + {{/unless}} {{#if this.appliedFilters.length}} {{#if (and (not this._dataCache.length) this.data.isRunning)}} -
+ -
+ {{else}} {{#if this.data.lastSuccessful.value.length}} {{#let this.data.lastSuccessful.value as |reports|}} -
+
{{#if this.selectedReportIds.length}}
- + {{! template-lint-disable table-groups }} +
- - - - - - - - - - - - - + + + + + + + + + + + + - - + + Verified by - - - - - - -
RejectedReviewNot billableBilled
+ Rejected + Review + Not billable + Billed + + + - +
- - - - - - - - - - - - - + + + + + + + + + + + + {{#each reports as |report|}} {{! template-lint-disable}} - - - - - - - - - - - - - - + /> + {{/each}} {{#if this._canLoadMore}} {{/if}} -
{{report.user.username}}{{moment-format report.date "DD.MM.YYYY"}}{{format-duration report.duration false}}{{report.task.project.customer.name}}{{report.task.project.name}}{{report.task.name}}{{report.user.username}} + {{moment-format + report.date + "DD.MM.YYYY" + }} + {{format-duration + report.duration + false + }} + {{report.task.project.customer.name}} + {{report.task.project.name}} + {{report.task.name}} + {{report.comment}}{{if + >{{report.comment}} + {{if report.verifiedBy report.verifiedBy.username - }} + + + +
+
- +
- - - + + + + + + + + + + + + - - - - {{#unless this.data.isRunning}} - - - {{/unless}} - - -
Total:{{format-duration - this.totalTime - false - }}Displaying - {{reports.length}} - of - {{this.totalItems}} - reports
-
+ + + Total: + + {{format-duration + this.totalTime + false + }} + Displaying + {{reports.length}} + of + {{this.totalItems}} + reports + + + + + +
{{#each this.exportLinks as |link|}} -{{/each}} +
+ {{#each this.choices as |choice index|}} + + {{/each}} +
\ No newline at end of file diff --git a/frontend/app/components/date-navigation/template.hbs b/frontend/app/components/date-navigation/template.hbs index c85d36688..8adb3d491 100644 --- a/frontend/app/components/date-navigation/template.hbs +++ b/frontend/app/components/date-navigation/template.hbs @@ -1,13 +1,11 @@ -
-
- -
-
+
+
+
- -
+ +
\ No newline at end of file diff --git a/frontend/app/components/sy-datepicker-btn/template.hbs b/frontend/app/components/datepicker-button.hbs similarity index 67% rename from frontend/app/components/sy-datepicker-btn/template.hbs rename to frontend/app/components/datepicker-button.hbs index f22d6c031..3a4bb1911 100644 --- a/frontend/app/components/sy-datepicker-btn/template.hbs +++ b/frontend/app/components/datepicker-button.hbs @@ -1,16 +1,16 @@ - - - + - + \ No newline at end of file diff --git a/frontend/app/components/sy-datepicker-btn/component.js b/frontend/app/components/datepicker-button.js similarity index 58% rename from frontend/app/components/sy-datepicker-btn/component.js rename to frontend/app/components/datepicker-button.js index 8f68aff75..39c44e574 100644 --- a/frontend/app/components/sy-datepicker-btn/component.js +++ b/frontend/app/components/datepicker-button.js @@ -5,17 +5,17 @@ */ import { action } from "@ember/object"; -import SyDatepickerComponent from "timed/components/sy-datepicker/component"; +import Datepicker from "timed/components/datepicker"; import { localCopy } from "tracked-toolbox"; /** - * The sy datepicker btn component + * The datepicker buttn component * - * @class SyDatepickerBtnComponent - * @extends SyDatepickerComponent + * @class DatepickerButton + * @extends Datepicker * @public */ -export default class SyDatepickerBtnComponent extends SyDatepickerComponent { +export default class DatepickerButtonComponent extends Datepicker { @localCopy("args.current") center; @action diff --git a/frontend/app/components/sy-datepicker/template.hbs b/frontend/app/components/datepicker.hbs similarity index 53% rename from frontend/app/components/sy-datepicker/template.hbs rename to frontend/app/components/datepicker.hbs index 8511ab238..5df4582f0 100644 --- a/frontend/app/components/sy-datepicker/template.hbs +++ b/frontend/app/components/datepicker.hbs @@ -1,45 +1,43 @@ - - + {{#if @value}} × + {{on "click" (prevent-default (stop-propagation (fn this.clear dd)))}} + >× {{/if}} - + - - + - + + +{{yield (hash id=this.uniqueId)}} \ No newline at end of file diff --git a/frontend/app/components/sy-datepicker/component.js b/frontend/app/components/datepicker.js similarity index 92% rename from frontend/app/components/sy-datepicker/component.js rename to frontend/app/components/datepicker.js index ab5d0fa32..94e7046cf 100644 --- a/frontend/app/components/sy-datepicker/component.js +++ b/frontend/app/components/datepicker.js @@ -12,7 +12,7 @@ const PARSE_FORMAT = "D.M.YYYY"; const parse = (value) => (value ? moment(value, PARSE_FORMAT) : null); -export default class SyDatepicker extends Component { +export default class Datepicker extends Component { placeholder = DISPLAY_FORMAT; @tracked center; @@ -20,7 +20,7 @@ export default class SyDatepicker extends Component { constructor(...args) { super(...args); - this.uniqueId = guidFor(this); + this.uniqueId = this.args.id ?? guidFor(this); this.center = this.args.value ?? moment(); } @@ -40,7 +40,7 @@ export default class SyDatepicker extends Component { @action handleBlur(dd, e) { const container = document.getElementById( - `ember-basic-dropdown-content-${dd.uniqueId}` + `ember-basic-dropdown-content-${dd.uniqueId}`, ); if (!container || !container.contains(e.relatedTarget)) { diff --git a/frontend/app/components/sy-durationpicker-day/template.hbs b/frontend/app/components/durationpicker-day.hbs similarity index 89% rename from frontend/app/components/sy-durationpicker-day/template.hbs rename to frontend/app/components/durationpicker-day.hbs index df54bb4ef..bb030f6b1 100644 --- a/frontend/app/components/sy-durationpicker-day/template.hbs +++ b/frontend/app/components/durationpicker-day.hbs @@ -3,7 +3,7 @@ aria-label="day picker" name="duration-day" type="text" - class="duration-day form-control" + class="duration-day form-control rounded" disabled={{@disabled}} pattern={{this.pattern}} value={{this.displayValue}} @@ -14,4 +14,4 @@ {{on "change" this.change}} {{on "keyup" this.handleKeyPress}} {{on "focusout" (optional @onFocusOut)}} -/> +/> \ No newline at end of file diff --git a/frontend/app/components/sy-durationpicker-day/component.js b/frontend/app/components/durationpicker-day.js similarity index 75% rename from frontend/app/components/sy-durationpicker-day/component.js rename to frontend/app/components/durationpicker-day.js index 8cbc914d8..4ea565c9a 100644 --- a/frontend/app/components/sy-durationpicker-day/component.js +++ b/frontend/app/components/durationpicker-day.js @@ -1,9 +1,9 @@ import { action } from "@ember/object"; import moment from "moment"; -import SyDurationpickerComponent from "timed/components/sy-durationpicker/component"; +import DurationpickerComponent from "timed/components/durationpicker"; import parseDayTime from "timed/utils/parse-daytime"; -export default class SyDurationpickerDayComponent extends SyDurationpickerComponent { +export default class DurationpickerDayComponent extends DurationpickerComponent { maxlength = 5; max = moment.duration({ h: 24, m: 0 }); diff --git a/frontend/app/components/sy-durationpicker/template.hbs b/frontend/app/components/durationpicker.hbs similarity index 94% rename from frontend/app/components/sy-durationpicker/template.hbs rename to frontend/app/components/durationpicker.hbs index 9ab9c1a79..dfaf1a53b 100644 --- a/frontend/app/components/sy-durationpicker/template.hbs +++ b/frontend/app/components/durationpicker.hbs @@ -11,6 +11,7 @@ aria-label="duration picker" name="duration" type="text" + class="rounded" id={{this.elementId}} title={{@title}} disabled={{@disabled}} @@ -30,7 +31,7 @@ aria-label="duration picker" name="duration" type="text" - class="form-control" + class="form-control rounded" id={{this.elementId}} disabled={{@disabled}} pattern={{this.pattern}} @@ -43,4 +44,4 @@ {{on "keyup" this.handleKeyPress}} {{on "focusout" (optional @onFocusOut)}} /> -{{/if}} +{{/if}} \ No newline at end of file diff --git a/frontend/app/components/sy-durationpicker/component.js b/frontend/app/components/durationpicker.js similarity index 89% rename from frontend/app/components/sy-durationpicker/component.js rename to frontend/app/components/durationpicker.js index 494c86928..6d8ec848f 100644 --- a/frontend/app/components/sy-durationpicker/component.js +++ b/frontend/app/components/durationpicker.js @@ -1,13 +1,8 @@ -/** - * @module timed - * @submodule timed-components - * @public - */ import { action } from "@ember/object"; import { guidFor } from "@ember/object/internals"; import { tracked } from "@glimmer/tracking"; import moment from "moment"; -import SyTimepickerComponent from "timed/components/sy-timepicker/component"; +import TimepickerComponent from "timed/components/timepicker"; import formatDuration from "timed/utils/format-duration"; import { localCopy } from "tracked-toolbox"; @@ -17,11 +12,11 @@ const { abs } = Math; /** * Duration selector component * - * @class SyDurationpickerComponent + * @class DurationpickerComponent * @extends Ember.Component * @public */ -export default class SyDurationpicker extends SyTimepickerComponent { +export default class Durationpicker extends TimepickerComponent { maxlength = null; /** @@ -29,7 +24,7 @@ export default class SyDurationpicker extends SyTimepickerComponent { * * 60 needs to be divisible by this * - * @property {Number} precision + * @property {number} precision * @public */ precision = 15; @@ -54,7 +49,7 @@ export default class SyDurationpicker extends SyTimepickerComponent { /** * The regex for the input * - * @property {String} pattern + * @property {string} pattern * @public */ get pattern() { diff --git a/frontend/app/components/empty.hbs b/frontend/app/components/empty.hbs new file mode 100644 index 000000000..7ba3ac1bc --- /dev/null +++ b/frontend/app/components/empty.hbs @@ -0,0 +1,6 @@ +
+ {{yield}} +
\ No newline at end of file diff --git a/frontend/app/components/filter-sidebar/filter/template.hbs b/frontend/app/components/filter-sidebar/filter/template.hbs index 3dcc524ff..ce8b873bb 100644 --- a/frontend/app/components/filter-sidebar/filter/template.hbs +++ b/frontend/app/components/filter-sidebar/filter/template.hbs @@ -1,44 +1,48 @@
- {{#if (eq @type "button")}} -
- {{#each @options as |opt|}} - - {{yield}} - {{/each}} -
- {{else if (eq @type "date")}} - - {{else if (eq @type "search")}} - {{#let (unique-id) as |searchId|}} - + {{#let (unique-id) as |id|}} + + {{#if (eq @type "button")}} +
+ {{#each @options as |opt|}} + + {{yield}} + {{/each}} +
+ {{else if (eq @type "date")}} + + {{else if (eq @type "search")}} - {{/let}} - {{else if (eq @type "select")}} - {{#let (unique-id) as |selectId|}} - + {{else if (eq @type "select")}} - {{/let}} - {{else}} - {{yield}} - {{/if}} -
+ {{else}} + {{yield}} + {{/if}} + {{/let}} +
\ No newline at end of file diff --git a/frontend/app/components/filter-sidebar/group/template.hbs b/frontend/app/components/filter-sidebar/group/template.hbs index 8e7fa49d7..3451e86ad 100644 --- a/frontend/app/components/filter-sidebar/group/template.hbs +++ b/frontend/app/components/filter-sidebar/group/template.hbs @@ -1,18 +1,25 @@ -
- +
+ +
+
+ {{yield}}
-
\ No newline at end of file +
+
\ No newline at end of file diff --git a/frontend/app/components/filter-sidebar/label/template.hbs b/frontend/app/components/filter-sidebar/label/template.hbs index 6b67e8407..a0222d4ca 100644 --- a/frontend/app/components/filter-sidebar/label/template.hbs +++ b/frontend/app/components/filter-sidebar/label/template.hbs @@ -1,3 +1,4 @@ +{{! using this is not encouraged as it can make :hover behave weirdly }} \ No newline at end of file diff --git a/frontend/app/components/filter-sidebar/template.hbs b/frontend/app/components/filter-sidebar/template.hbs index 95b41f9a6..6242a3a70 100644 --- a/frontend/app/components/filter-sidebar/template.hbs +++ b/frontend/app/components/filter-sidebar/template.hbs @@ -1,6 +1,17 @@ {{#in-element this.destination}} -
+
\ No newline at end of file diff --git a/frontend/app/components/optimized-power-select/custom-select/task-selection.hbs b/frontend/app/components/optimized-power-select/custom-select/task-selection.hbs index 93476be6a..2ac97e213 100644 --- a/frontend/app/components/optimized-power-select/custom-select/task-selection.hbs +++ b/frontend/app/components/optimized-power-select/custom-select/task-selection.hbs @@ -1 +1 @@ -{{@selected.name}} +{{@selected.name}} \ No newline at end of file diff --git a/frontend/app/components/optimized-power-select/custom-select/user-selection.hbs b/frontend/app/components/optimized-power-select/custom-select/user-selection.hbs index 4179cb6fd..360ba4395 100644 --- a/frontend/app/components/optimized-power-select/custom-select/user-selection.hbs +++ b/frontend/app/components/optimized-power-select/custom-select/user-selection.hbs @@ -1 +1 @@ -{{@selected.longName}} +{{@selected.longName}} \ No newline at end of file diff --git a/frontend/app/components/optimized-power-select/options/component.js b/frontend/app/components/optimized-power-select/options/component.js index bb96fed34..b42f3a65f 100644 --- a/frontend/app/components/optimized-power-select/options/component.js +++ b/frontend/app/components/optimized-power-select/options/component.js @@ -25,7 +25,7 @@ export default class OptimizedPowerSelectOptionsComponent extends Component { "actions", this.args.select.actions, "scrollTo", - this.args.select.highlighted + this.args.select.highlighted, ); } diff --git a/frontend/app/components/optimized-power-select/options/template.hbs b/frontend/app/components/optimized-power-select/options/template.hbs index 6b6bce351..a8f51a60d 100644 --- a/frontend/app/components/optimized-power-select/options/template.hbs +++ b/frontend/app/components/optimized-power-select/options/template.hbs @@ -4,7 +4,7 @@ {{on "touchmove" this.onEvent}} {{on "touchstart" this.onEvent}} {{on "touchend" this.onEvent}} - {{!-- template-lint-disable no-invalid-interactive --}} + {{! template-lint-disable no-invalid-interactive }} {{on "mouseup" this.onEvent}} {{on "mouseover" this.onEvent}} ...attributes @@ -46,4 +46,4 @@ {{/if}} - + \ No newline at end of file diff --git a/frontend/app/components/optimized-power-select/template.hbs b/frontend/app/components/optimized-power-select/template.hbs index 7761038a0..c917203bf 100644 --- a/frontend/app/components/optimized-power-select/template.hbs +++ b/frontend/app/components/optimized-power-select/template.hbs @@ -1,4 +1,6 @@ + @dropdownClass={{@dropdownClass}} +/> \ No newline at end of file diff --git a/frontend/app/components/optimized-power-select/trigger/template.hbs b/frontend/app/components/optimized-power-select/trigger/template.hbs index 30b2e7b86..f68e9bb93 100644 --- a/frontend/app/components/optimized-power-select/trigger/template.hbs +++ b/frontend/app/components/optimized-power-select/trigger/template.hbs @@ -1,36 +1,34 @@ -
- {{#if @select.selected}} - {{#if @selectedItemComponent}} - {{component - @selectedItemComponent - option=(readonly @select.selected) - select=(readonly @select) - }} - {{else}} - - {{#if @extra.selectedTemplate}} - {{component - (ensure-safe-component @extra.selectedTemplate) - selected=@select.selected - }} - {{else}} - {{yield @select.selected @select}} - {{/if}} - - {{/if}} - {{#if (and @allowClear (not @select.disabled))}} - × - {{/if}} - {{else}} +{{#if @select.selected}} + {{#if @selectedItemComponent}} {{component - (ensure-safe-component @placeholderComponent) - placeholder=@placeholder + @selectedItemComponent + option=(readonly @select.selected) + select=(readonly @select) }} + {{else}} + + {{#if @extra.selectedTemplate}} + {{component + (ensure-safe-component @extra.selectedTemplate) + selected=@select.selected + }} + {{else}} + {{yield @select.selected @select}} + {{/if}} + + {{/if}} + {{#if (and @allowClear (not @select.disabled))}} + × {{/if}} - -
+{{else}} + {{component + (ensure-safe-component @placeholderComponent) + placeholder=@placeholder + }} +{{/if}} + \ No newline at end of file diff --git a/frontend/app/components/page-permission/template.hbs b/frontend/app/components/page-permission/template.hbs index 32934a60f..632472ec0 100644 --- a/frontend/app/components/page-permission/template.hbs +++ b/frontend/app/components/page-permission/template.hbs @@ -1,5 +1,5 @@ {{#if (cannot "access page")}} -
+

Access forbidden

You do not have the permission to access this page

diff --git a/frontend/app/components/progress-tooltip/component.js b/frontend/app/components/progress-tooltip/component.js index 2aec8f177..69aa0772e 100644 --- a/frontend/app/components/progress-tooltip/component.js +++ b/frontend/app/components/progress-tooltip/component.js @@ -82,37 +82,41 @@ export default class ProgressTooltipComponent extends Component { : 0; } + get badgeClass() { + return "text-foreground-primary rounded-xl py-1 px-1.5 font-mono text-xs rounded-xl m-0.5 inline-block min-w-2.5 text-center whitespace-nowrap"; + } + // The color of the badge and progress bar for billable time spent get colorBillable() { if (this.progressBillable > 1) { - return "danger"; + return "bg-danger"; } else if (this.progressBillable >= 0.9) { - return "warning"; + return "bg-warning"; } - return "success"; + return "bg-success"; } // The color of the badge and progress bar for total time spent get colorTotal() { if (this.progressTotal > 1) { - return "danger"; + return "bg-danger"; } else if (this.progressTotal >= 0.9) { - return "warning"; + return "bg-warning"; } - return "success"; + return "bg-success"; } // The color of the badge and progress bar for remaining effort get colorRemainingEffort() { if (this.progressRemainingEffort > 1) { - return "danger"; + return "bg-danger"; } else if (this.progressRemainingEffort >= 0.9) { - return "warning"; + return "bg-warning"; } - return "success"; + return "bg-success"; } get tooltipVisible() { diff --git a/frontend/app/components/progress-tooltip/template.hbs b/frontend/app/components/progress-tooltip/template.hbs index ab48d7da3..21deb69a7 100644 --- a/frontend/app/components/progress-tooltip/template.hbs +++ b/frontend/app/components/progress-tooltip/template.hbs @@ -1,24 +1,23 @@ {{#if this.tooltipVisible}} -
+
Spent (Total): {{humanize-duration this.spent}}
{{#if this.progressTotal}} - + {{#if (gt this.progressTotal 1)}} - {{/if}} - {{round (mult 100 this.progressTotal)}}% + {{/if}}{{round (mult 100 this.progressTotal)}}% {{/if}}
@@ -27,7 +26,7 @@ {{humanize-duration this.billable}}
{{#if this.progressBillable}} - + {{#if (gt this.progressBillable 1)}} - Budget: + Budget: {{if this.estimated (humanize-duration this.estimated) "None"}} {{#if this.remainingEffort}} @@ -48,7 +47,9 @@ }}
{{#if this.progressRemainingEffort}} - + {{#if (gt this.progressRemainingEffort 1)}} -{{/if}} +{{/if}} \ No newline at end of file diff --git a/frontend/app/components/record-button/template.hbs b/frontend/app/components/record-button/template.hbs index 2b729ad0c..0f07701d7 100644 --- a/frontend/app/components/record-button/template.hbs +++ b/frontend/app/components/record-button/template.hbs @@ -1,27 +1,25 @@ -
{{#if this.active}} - +
{{else}} - + {{/if}} -
+ \ No newline at end of file diff --git a/frontend/app/components/report-review-warning/component.js b/frontend/app/components/report-review-warning/component.js index ebc731e1a..7848af380 100644 --- a/frontend/app/components/report-review-warning/component.js +++ b/frontend/app/components/report-review-warning/component.js @@ -7,4 +7,10 @@ export default class ReportReviewWarning extends Component { @service unverifiedReports; @service rejectedReports; + + get class() { + return `text-primary hover:text-foreground-primary hover:bg-primary-light p-2 gap-1 grid-cols-[auto,minmax(0,1fr)] grid items-center h-full ${ + this.args.class ?? "" + }`; + } } diff --git a/frontend/app/components/report-review-warning/template.hbs b/frontend/app/components/report-review-warning/template.hbs index deb5b2ba1..f70cd53bf 100644 --- a/frontend/app/components/report-review-warning/template.hbs +++ b/frontend/app/components/report-review-warning/template.hbs @@ -1,56 +1,60 @@ -
- {{#if this.unverifiedReports.hasReports}} - - {{/if}} - {{#if this.rejectedReports.hasReports}} - - {{/if}} -
+{{#if this.unverifiedReports.hasReports}} + + + + {{this.unverifiedReports.amountReports}} + + +{{/if}} +{{#if this.rejectedReports.hasReports}} + + + + {{this.rejectedReports.amountReports}} + + +{{/if}} \ No newline at end of file diff --git a/frontend/app/components/report-row/component.js b/frontend/app/components/report-row/component.js index afc75e117..cc9815e06 100644 --- a/frontend/app/components/report-row/component.js +++ b/frontend/app/components/report-row/component.js @@ -17,7 +17,7 @@ export default class ReportRowComponent extends Component { return this.editable ? "" : `This entry was already verified by ${this.args.report.get( - "verifiedBy.fullName" + "verifiedBy.fullName", )} and therefore not editable anymore`; } diff --git a/frontend/app/components/report-row/template.hbs b/frontend/app/components/report-row/template.hbs index 9f7e84aa3..f1c4a8e9d 100644 --- a/frontend/app/components/report-row/template.hbs +++ b/frontend/app/components/report-row/template.hbs @@ -1,42 +1,54 @@ {{#let (changeset @report this.ReportValidations) as |cs|}} -
+ -
{{t.customer}}
-
{{t.project}}
-
{{t.task}}
+ + + + +
-
+
- {{#if cs.task.project.customerVisible}} - - {{/if}}
-
{{#if cs.task.project.remainingEffortTracking}} - - - - - - + /> {{/if}}
-
- + - - + - +
-
+
{{#if this.editable}} - + disabled={{or + this.save.isRunning + (or (not cs.isValid) (not (or cs.isDirty cs.isNew))) + }} + > {{/if}}
- -{{/let}} + +{{/let}} \ No newline at end of file diff --git a/frontend/app/components/scroll-container.hbs b/frontend/app/components/scroll-container.hbs index 411d09169..bdfca6b0b 100644 --- a/frontend/app/components/scroll-container.hbs +++ b/frontend/app/components/scroll-container.hbs @@ -1,6 +1,6 @@
{{yield}}
+>{{yield}}
\ No newline at end of file diff --git a/frontend/app/components/sort-header/template.hbs b/frontend/app/components/sort-header/template.hbs index 9f2f0e110..e001c88af 100644 --- a/frontend/app/components/sort-header/template.hbs +++ b/frontend/app/components/sort-header/template.hbs @@ -1,9 +1,14 @@ {{! template-lint-disable}} - + {{yield}} {{#if this.active}} {{else}} {{/if}} - + \ No newline at end of file diff --git a/frontend/app/components/statistic-list/bar/component.js b/frontend/app/components/statistic-list/bar/component.js index b58940e67..501ba9445 100644 --- a/frontend/app/components/statistic-list/bar/component.js +++ b/frontend/app/components/statistic-list/bar/component.js @@ -15,11 +15,11 @@ export default class StatisticListBar extends Component { get spentEffortsBarColor() { if (this.didFinishEffortsInBudget) { - return "strong-success"; + return "before:bg-success"; } if (this.didFinishEffortsOverBudget) { - return "strong-danger"; + return "before:bg-danger"; } - return ""; + return "before:bg-primary"; } } diff --git a/frontend/app/components/statistic-list/bar/template.hbs b/frontend/app/components/statistic-list/bar/template.hbs index c9d48c40b..cf06cbc4d 100644 --- a/frontend/app/components/statistic-list/bar/template.hbs +++ b/frontend/app/components/statistic-list/bar/template.hbs @@ -1,23 +1,26 @@ -
- +
{{#if (and @remaining (lte @remaining 1))}}
{{/if}} {{#if @goal}}
{{/if}} -
+
\ No newline at end of file diff --git a/frontend/app/components/statistic-list/column/template.hbs b/frontend/app/components/statistic-list/column/template.hbs index 7140b9642..39b0a5e92 100644 --- a/frontend/app/components/statistic-list/column/template.hbs +++ b/frontend/app/components/statistic-list/column/template.hbs @@ -1,4 +1,4 @@ - + {{#if (eq @layout "DURATION")}} {{humanize-duration @value false}} {{else if (eq @layout "MONTH")}} @@ -6,4 +6,4 @@ {{else}} {{@value}} {{/if}} - + \ No newline at end of file diff --git a/frontend/app/components/statistic-list/component.js b/frontend/app/components/statistic-list/component.js index 042672ab2..a0bdf425c 100644 --- a/frontend/app/components/statistic-list/component.js +++ b/frontend/app/components/statistic-list/component.js @@ -76,16 +76,16 @@ export default class StatisticList extends Component { } const maxEstimated = moment.duration( - Math.max(0, ...this.value.map((v) => v.estimatedTime).filter(Boolean)) + Math.max(0, ...this.value.map((v) => v.estimatedTime).filter(Boolean)), ); const maxDurationWithRemainingEffort = moment.duration( Math.max( ...this.value.map((task) => moment .duration(task.duration) - .add(moment.duration(task.mostRecentRemainingEffort)) - ) - ) + .add(moment.duration(task.mostRecentRemainingEffort)), + ), + ), ); return Math.max(maxEstimated, maxDurationWithRemainingEffort); } diff --git a/frontend/app/components/statistic-list/template.hbs b/frontend/app/components/statistic-list/template.hbs index e877b66e5..7d48a5082 100644 --- a/frontend/app/components/statistic-list/template.hbs +++ b/frontend/app/components/statistic-list/template.hbs @@ -1,10 +1,10 @@
{{#if @data.isRunning}} -
+ -
+ {{else if @data.last.isError}} -
+

Oops... Something went wrong

@@ -14,27 +14,23 @@ Please try refreshing the page.

-
+ {{else if @missingParams}} -
-
- -

Missing filter parameters

-

{{this.missingParamsMessage}}

-
-
+ + +

Missing filter parameters

+

{{this.missingParamsMessage}}

+
{{else if (not @data.last.value)}} -
-
- -

No statistics to display

-

Maybe try loosening your filters

-
-
+ + +

No statistics to display

+

Maybe try loosening your filters

+
{{else}} - - - +
+ + {{#each this.columns as |column|}} {{#if column.ordering}} {{else}} - + {{column.title}} {{/if}} {{/each}} - - - + + + - + {{#each this.columns as |column|}} {{/each}} - - + + - - + + {{#each this.columns as |column index|}} - + {{/each}} - - - -
{{column.title}}
+ {{#let (or row.totalRemainingEffort row.mostRecentRemainingEffort) as |remainingEffort| @@ -84,13 +85,13 @@ /> {{/let}} {{/let}} -
+ {{#if (not index)}} Total: @@ -101,11 +102,11 @@ }} {{/if}} -
+ + + + {{/if}} -
+
\ No newline at end of file diff --git a/frontend/app/components/sy-calendar/template.hbs b/frontend/app/components/sy-calendar/template.hbs deleted file mode 100644 index 3494ec2f3..000000000 --- a/frontend/app/components/sy-calendar/template.hbs +++ /dev/null @@ -1,45 +0,0 @@ - - - - {{#let (moment-format calendar.center "MMMM") as |currentMonth|}} - {{currentMonth}} - - {{/let}} - - - {{#let (moment-format calendar.center "YYYY") as |currentYear|}} - {{currentYear}} - - {{/let}} - - - - diff --git a/frontend/app/components/sy-checkmark/template.hbs b/frontend/app/components/sy-checkmark/template.hbs deleted file mode 100644 index d3bb5aded..000000000 --- a/frontend/app/components/sy-checkmark/template.hbs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/app/components/sy-modal-target/template.hbs b/frontend/app/components/sy-modal-target/template.hbs deleted file mode 100644 index 5843e1ddc..000000000 --- a/frontend/app/components/sy-modal-target/template.hbs +++ /dev/null @@ -1 +0,0 @@ -
diff --git a/frontend/app/components/sy-modal/body/template.hbs b/frontend/app/components/sy-modal/body/template.hbs deleted file mode 100644 index 1ca19b419..000000000 --- a/frontend/app/components/sy-modal/body/template.hbs +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/frontend/app/components/sy-modal/component.js b/frontend/app/components/sy-modal/component.js deleted file mode 100644 index 80919a286..000000000 --- a/frontend/app/components/sy-modal/component.js +++ /dev/null @@ -1,7 +0,0 @@ -import Component from "@glimmer/component"; - -export default class SyModal extends Component { - get syModals() { - return document.getElementById("sy-modals"); - } -} diff --git a/frontend/app/components/sy-modal/footer/template.hbs b/frontend/app/components/sy-modal/footer/template.hbs deleted file mode 100644 index 9c9c24ff4..000000000 --- a/frontend/app/components/sy-modal/footer/template.hbs +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/frontend/app/components/sy-modal/overlay/template.hbs b/frontend/app/components/sy-modal/overlay/template.hbs deleted file mode 100644 index bdb98a621..000000000 --- a/frontend/app/components/sy-modal/overlay/template.hbs +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/frontend/app/components/sy-modal/template.hbs b/frontend/app/components/sy-modal/template.hbs deleted file mode 100644 index 8fb598fb8..000000000 --- a/frontend/app/components/sy-modal/template.hbs +++ /dev/null @@ -1,16 +0,0 @@ -{{#if @visible}} - {{#in-element this.syModals insertBefore=null}} - - - - {{/in-element}} -{{/if}} diff --git a/frontend/app/components/sy-topnav/template.hbs b/frontend/app/components/sy-topnav/template.hbs deleted file mode 100644 index 848ce2bc3..000000000 --- a/frontend/app/components/sy-topnav/template.hbs +++ /dev/null @@ -1,75 +0,0 @@ - diff --git a/frontend/app/components/table.hbs b/frontend/app/components/table.hbs new file mode 100644 index 000000000..5dc02e662 --- /dev/null +++ b/frontend/app/components/table.hbs @@ -0,0 +1,3 @@ + + {{yield}} +
\ No newline at end of file diff --git a/frontend/app/components/table/td.hbs b/frontend/app/components/table/td.hbs new file mode 100644 index 000000000..923245154 --- /dev/null +++ b/frontend/app/components/table/td.hbs @@ -0,0 +1 @@ +{{yield}} \ No newline at end of file diff --git a/frontend/app/components/table/tfoot.hbs b/frontend/app/components/table/tfoot.hbs new file mode 100644 index 000000000..6274e7dc8 --- /dev/null +++ b/frontend/app/components/table/tfoot.hbs @@ -0,0 +1,3 @@ + + {{yield}} + \ No newline at end of file diff --git a/frontend/app/components/table/th.hbs b/frontend/app/components/table/th.hbs new file mode 100644 index 000000000..c6aad301c --- /dev/null +++ b/frontend/app/components/table/th.hbs @@ -0,0 +1,6 @@ + + {{yield}} + \ No newline at end of file diff --git a/frontend/app/components/table/thead.hbs b/frontend/app/components/table/thead.hbs new file mode 100644 index 000000000..80f25eea6 --- /dev/null +++ b/frontend/app/components/table/thead.hbs @@ -0,0 +1,3 @@ + + {{yield}} + \ No newline at end of file diff --git a/frontend/app/components/table/tr.hbs b/frontend/app/components/table/tr.hbs new file mode 100644 index 000000000..adcba879d --- /dev/null +++ b/frontend/app/components/table/tr.hbs @@ -0,0 +1,6 @@ +{{yield}} \ No newline at end of file diff --git a/frontend/app/components/task-selection/component.js b/frontend/app/components/task-selection/component.js index a213d5197..3de13ccee 100644 --- a/frontend/app/components/task-selection/component.js +++ b/frontend/app/components/task-selection/component.js @@ -63,7 +63,7 @@ export default class TaskSelectionComponent extends Component { // we track "_activity" here since we can not track the public getters directly this.tracking.addObserver( "_activity", - this.handleTrackingActiveActivityChanged.perform + this.handleTrackingActiveActivityChanged.perform, ); } } @@ -72,7 +72,7 @@ export default class TaskSelectionComponent extends Component { if (this.args.liveTracking) { this.tracking.removeObserver( "_activity", - this.handleTrackingActiveActivityChanged.perform + this.handleTrackingActiveActivityChanged.perform, ); } super.willDestroy(...args); @@ -256,7 +256,7 @@ export default class TaskSelectionComponent extends Component { _customersAndRecentTasks = trackedTask( this, this.customersAndRecentTasksTask, - () => [this.history, this.tracking.recentTasks, this.archived] + () => [this.history, this.tracking.recentTasks, this.archived], ); get customersAndRecentTasks() { diff --git a/frontend/app/components/task-selection/template.hbs b/frontend/app/components/task-selection/template.hbs index caffd4651..f6fbe3f51 100644 --- a/frontend/app/components/task-selection/template.hbs +++ b/frontend/app/components/task-selection/template.hbs @@ -9,7 +9,7 @@ searchField="longName" allowClear=true tagName="div" - class="customer-select" + class="customer-select rounded" onChange=this.onCustomerChange extra=(hash selectedTemplate=this.selectedTemplate @@ -25,7 +25,7 @@ searchField="name" allowClear=true tagName="div" - class="project-select" + class="project-select rounded" onChange=this.onProjectChange extra=(hash selectedTemplate=this.selectedTemplate @@ -41,7 +41,7 @@ searchField="name" allowClear=true tagName="div" - class="task-select" + class="task-select rounded" onChange=this.onTaskChange extra=(hash selectedTemplate=this.selectedTemplate @@ -51,4 +51,4 @@ clear=this.clear reset=this.reset ) -}} +}} \ No newline at end of file diff --git a/frontend/app/components/timed-clock/template.hbs b/frontend/app/components/timed-clock/template.hbs index f7afa675b..953db1f13 100644 --- a/frontend/app/components/timed-clock/template.hbs +++ b/frontend/app/components/timed-clock/template.hbs @@ -1,11 +1,18 @@ - + - + \ No newline at end of file diff --git a/frontend/app/components/sy-timepicker/template.hbs b/frontend/app/components/timepicker.hbs similarity index 90% rename from frontend/app/components/sy-timepicker/template.hbs rename to frontend/app/components/timepicker.hbs index 2fb9ec0d3..cf0070d59 100644 --- a/frontend/app/components/sy-timepicker/template.hbs +++ b/frontend/app/components/timepicker.hbs @@ -1,7 +1,7 @@ +/> \ No newline at end of file diff --git a/frontend/app/components/sy-timepicker/component.js b/frontend/app/components/timepicker.js similarity index 92% rename from frontend/app/components/sy-timepicker/component.js rename to frontend/app/components/timepicker.js index b1b9d20a8..408ed8988 100644 --- a/frontend/app/components/sy-timepicker/component.js +++ b/frontend/app/components/timepicker.js @@ -1,8 +1,3 @@ -/** - * @module timed - * @submodule timed-components - * @public - */ import { action } from "@ember/object"; import Component from "@glimmer/component"; import moment from "moment"; @@ -10,11 +5,11 @@ import moment from "moment"; /** * Timepicker component * - * @class SyTimepickerComponent + * @class TimepickerComponent * @extends Ember.Component * @public */ -export default class SyTimepickerComponent extends Component { +export default class TimepickerComponent extends Component { optionalUnwrap(date) { if (this.isProxiedDate(date)) { return date.unwrap(); @@ -62,7 +57,7 @@ export default class SyTimepickerComponent extends Component { /** * The input placeholder * - * @property {String} placeholder + * @property {string} placeholder * @public */ get placeholder() { @@ -72,7 +67,7 @@ export default class SyTimepickerComponent extends Component { /** * The maximal length of the value * - * @property {Number} maxlength + * @property {number} maxlength * @public */ get maxlength() { @@ -84,7 +79,7 @@ export default class SyTimepickerComponent extends Component { * * 60 needs to be divisible by this * - * @property {Number} precision + * @property {number} precision * @public */ get precision() { @@ -94,7 +89,7 @@ export default class SyTimepickerComponent extends Component { /** * The regex for the input * - * @property {String} pattern + * @property {string} pattern * @public */ get pattern() { @@ -111,7 +106,7 @@ export default class SyTimepickerComponent extends Component { * * This is the value in the input field. * - * @property {String} displayValue + * @property {string} displayValue * @public */ get displayValue() { @@ -221,7 +216,7 @@ export default class SyTimepickerComponent extends Component { * Add hours to the current value * * @method _addHours - * @param {moment} value The amount of hours to add + * @param {import('moment').Moment} value The amount of hours to add * @private */ _addHours(value) { @@ -236,7 +231,7 @@ export default class SyTimepickerComponent extends Component { * Ensure that the new value is valid and trigger a change * * @method change - * @param {moment} value The new value + * @param {import('moment').Moment} value The new value * @private */ _change(value) { diff --git a/frontend/app/components/sy-toggle/template.hbs b/frontend/app/components/toggle.hbs similarity index 67% rename from frontend/app/components/sy-toggle/template.hbs rename to frontend/app/components/toggle.hbs index 6d6a2acaa..07870fe98 100644 --- a/frontend/app/components/sy-toggle/template.hbs +++ b/frontend/app/components/toggle.hbs @@ -1,6 +1,8 @@
{{/if}} -
+
\ No newline at end of file diff --git a/frontend/app/components/sy-toggle/component.js b/frontend/app/components/toggle.js similarity index 54% rename from frontend/app/components/sy-toggle/component.js rename to frontend/app/components/toggle.js index 7f8bb499c..e67e8e103 100644 --- a/frontend/app/components/sy-toggle/component.js +++ b/frontend/app/components/toggle.js @@ -1,14 +1,7 @@ -import { assert } from "@ember/debug"; import { action } from "@ember/object"; import Component from "@glimmer/component"; -export default class SyToggle extends Component { - constructor(...args) { - super(...args); - - assert("You must pass a onToggle callback.", this.args.onToggle); - } - +export default class Toggle extends Component { @action handleKeyUp(event) { // only trigger on "Space" key diff --git a/frontend/app/components/topnav.hbs b/frontend/app/components/topnav.hbs new file mode 100644 index 000000000..65ebfc816 --- /dev/null +++ b/frontend/app/components/topnav.hbs @@ -0,0 +1,114 @@ +
+ +
\ No newline at end of file diff --git a/frontend/app/components/sy-topnav/component.js b/frontend/app/components/topnav.js similarity index 70% rename from frontend/app/components/sy-topnav/component.js rename to frontend/app/components/topnav.js index 1e0f9c4ff..c170eaf54 100644 --- a/frontend/app/components/sy-topnav/component.js +++ b/frontend/app/components/topnav.js @@ -2,7 +2,7 @@ import { service } from "@ember/service"; import Component from "@glimmer/component"; import { tracked } from "@glimmer/tracking"; -export default class SyTopnav extends Component { +export default class Topnav extends Component { @service currentUser; @service media; @@ -10,6 +10,6 @@ export default class SyTopnav extends Component { @tracked expand = false; get navMobile() { - return this.media.isMo || this.media.isXs; + return !this.media.isSm; } } diff --git a/frontend/app/components/topnav/link-to.hbs b/frontend/app/components/topnav/link-to.hbs new file mode 100644 index 000000000..abfe26ceb --- /dev/null +++ b/frontend/app/components/topnav/link-to.hbs @@ -0,0 +1,31 @@ +{{#if @route}} + {{#if @model}} + + {{yield}} + + {{else}} + + {{yield}} + + {{/if}} +{{else}} + {{yield}} +{{/if}} \ No newline at end of file diff --git a/frontend/app/components/topnav/link-to.js b/frontend/app/components/topnav/link-to.js new file mode 100644 index 000000000..80a9a9528 --- /dev/null +++ b/frontend/app/components/topnav/link-to.js @@ -0,0 +1,11 @@ +import Component from "@glimmer/component"; + +export default class TopnavLinkToComponent extends Component { + get class() { + return "gap-1 grid grid-cols-[auto,minmax(0,1fr)] h-full hover:[&:not(.active)]:bg-primary-light hover:text-foreground-primary items-center lg:gap-2 md:place-items-center md:self-center [&:not(.active,:hover)]:text-tertiary py-2 px-2.5 transition-[font-size] w-full"; + } + + get activeClass() { + return "active text-foreground-primary visited:text-foreground-primary bg-primary-dark hover:bg-primary"; + } +} diff --git a/frontend/app/components/topnav/list-item.hbs b/frontend/app/components/topnav/list-item.hbs new file mode 100644 index 000000000..22dde95f0 --- /dev/null +++ b/frontend/app/components/topnav/list-item.hbs @@ -0,0 +1 @@ +
  • {{yield}}
  • \ No newline at end of file diff --git a/frontend/app/components/topnav/list.hbs b/frontend/app/components/topnav/list.hbs new file mode 100644 index 000000000..fc8d8a367 --- /dev/null +++ b/frontend/app/components/topnav/list.hbs @@ -0,0 +1,3 @@ +
      + {{yield}} +
    \ No newline at end of file diff --git a/frontend/app/components/tracking-bar/template.hbs b/frontend/app/components/tracking-bar/template.hbs index b0a3d3f74..bcdf5db80 100644 --- a/frontend/app/components/tracking-bar/template.hbs +++ b/frontend/app/components/tracking-bar/template.hbs @@ -1,4 +1,4 @@ -
    +
    -
    -
    + +
    -
    +
    -
    +
    -
    +
    - {{#if this.tracking.activity.task.project.customerVisible}} - - {{/if}}
    -
    +
    -
    +
    \ No newline at end of file diff --git a/frontend/app/components/user-selection/template.hbs b/frontend/app/components/user-selection/template.hbs index 7f9e2e319..a4eb0e7a7 100644 --- a/frontend/app/components/user-selection/template.hbs +++ b/frontend/app/components/user-selection/template.hbs @@ -8,7 +8,7 @@ placeholder="Select user..." searchField="longName" tagName="div" - class="user-select" + class="user-select rounded" allowClear=true onChange=@onChange extra=(hash @@ -18,4 +18,4 @@ ) ) ) -}} +}} \ No newline at end of file diff --git a/frontend/app/components/void.hbs b/frontend/app/components/void.hbs new file mode 100644 index 000000000..2ba609ef7 --- /dev/null +++ b/frontend/app/components/void.hbs @@ -0,0 +1 @@ +{{! used as @labelComponent in ValidatedForm otherwise there'd be s even with an empty label}} \ No newline at end of file diff --git a/frontend/app/components/weekly-overview-benchmark/template.hbs b/frontend/app/components/weekly-overview-benchmark/template.hbs index ff8c2026e..66045c500 100644 --- a/frontend/app/components/weekly-overview-benchmark/template.hbs +++ b/frontend/app/components/weekly-overview-benchmark/template.hbs @@ -1,6 +1,14 @@ -
    +
    {{#if @showLabel}} - {{@hours}}h + {{@hours}}h {{/if}} -
    +
    \ No newline at end of file diff --git a/frontend/app/components/weekly-overview-day/component.js b/frontend/app/components/weekly-overview-day/component.js index f0b0bcc99..1443de452 100644 --- a/frontend/app/components/weekly-overview-day/component.js +++ b/frontend/app/components/weekly-overview-day/component.js @@ -24,7 +24,7 @@ export default class WeeklyOverviewDay extends Component { get style() { const height = Math.min( (this.args.worktime.asHours() / this.max) * 100, - 100 + 100, ); return { height: `${height}%` }; } diff --git a/frontend/app/components/weekly-overview-day/template.hbs b/frontend/app/components/weekly-overview-day/template.hbs index 9eac3279a..28ae0fe35 100644 --- a/frontend/app/components/weekly-overview-day/template.hbs +++ b/frontend/app/components/weekly-overview-day/template.hbs @@ -1,18 +1,32 @@ -
    +
    +
    -
    -
    - {{moment-format @day 'DD'}} - {{moment-format @day 'dd'}} + {{moment-format @day "DD"}} + {{moment-format @day "dd"}}
    -
    + \ No newline at end of file diff --git a/frontend/app/components/weekly-overview/template.hbs b/frontend/app/components/weekly-overview/template.hbs index f0977b55d..726d68c76 100644 --- a/frontend/app/components/weekly-overview/template.hbs +++ b/frontend/app/components/weekly-overview/template.hbs @@ -1,17 +1,25 @@ -
    -
    - - - - - - - - - - - - +
    +
    + + + + + + + + + + + + {{yield}}
    -
    +
    \ No newline at end of file diff --git a/frontend/app/components/welcome-modal/template.hbs b/frontend/app/components/welcome-modal/template.hbs index f469dff8f..b096145e4 100644 --- a/frontend/app/components/welcome-modal/template.hbs +++ b/frontend/app/components/welcome-modal/template.hbs @@ -1,38 +1,41 @@ - + +

    Welcome to Timed!

    -
    -

    Welcome to Timed!

    - -

    Would you like to take a tour?

    +
    + + +

    Would you like to take a tour?

    - + - +
    + - + +
    - + \ No newline at end of file diff --git a/frontend/app/components/worktime-balance-chart/component.js b/frontend/app/components/worktime-balance-chart/component.js index 5c61b941b..cc84327ad 100644 --- a/frontend/app/components/worktime-balance-chart/component.js +++ b/frontend/app/components/worktime-balance-chart/component.js @@ -2,7 +2,12 @@ import Component from "@glimmer/component"; import moment from "moment"; import humanizeDuration from "timed/utils/humanize-duration"; -const FONT_FAMILY = "Source Sans Pro"; +// TODO: take this from tailwind.config.js +const FONT_SANS = ['"Source Sans 3"', "sans-serif"]; +const FONT_MONO = ['"Source Code Pro"', "monospace"]; + +const cssvar = (name) => + getComputedStyle(document.documentElement).getPropertyValue(name); export default class WorktimeBalanceChart extends Component { type = "line"; @@ -17,7 +22,7 @@ export default class WorktimeBalanceChart extends Component { datasets: [ { data: this.args.worktimeBalances.map(({ balance }) => - Number.parseFloat(balance.asHours().toFixed(2)) + Number.parseFloat(balance.asHours().toFixed(2)), ), }, ], @@ -26,20 +31,24 @@ export default class WorktimeBalanceChart extends Component { get options() { return { - lineTension: 0, + tension: 0, + // lineTension: 0, legend: { display: false }, layout: { padding: 10 }, elements: { line: { - borderColor: "rgb(91, 142, 219)", + tension: 0, + borderColor: cssvar("--primary"), backgroundColor: "transparent", borderWidth: 2, }, point: { - borderColor: "rgb(91, 142, 219)", - backgroundColor: "rgb(255, 255, 255)", - hoverBackgroundColor: "rgb(0,0,0)", + borderColor: cssvar("--tertiary"), + backgroundColor: `rgb(${cssvar("--background")})`, + hoverBackgroundColor: cssvar("--background-muted"), + hoverBorderColor: cssvar("--primary"), borderWidth: 2, + hoverBorderWidth: 2, radius: 3.5, hoverRadius: 3.5, hitRadius: 10, @@ -52,8 +61,9 @@ export default class WorktimeBalanceChart extends Component { callback(value) { return [value.format("DD"), value.format("dd").toUpperCase()]; }, - fontFamily: FONT_FAMILY, - fontColor: "rgb(180, 180, 180)", + fontFamily: FONT_MONO, + fontColor: `rgb(${cssvar("--foreground-muted")})`, + fontSize: 18, }, gridLines: { drawBorder: false, @@ -67,6 +77,8 @@ export default class WorktimeBalanceChart extends Component { display: false, }, gridLines: { + zeroLineColor: `rgb(${cssvar("--foreground-muted")})`, + color: `rgb(${cssvar("--foreground-muted")})`, drawBorder: false, drawTicks: false, borderDash: [5, 5], @@ -75,12 +87,15 @@ export default class WorktimeBalanceChart extends Component { ], }, tooltips: { + backgroundColor: cssvar("--background-muted"), + titleFontColor: cssvar("--foreground"), + bodyFontColor: cssvar("--foreground"), displayColors: false, - cornerRadius: 4, - bodyFontFamily: FONT_FAMILY, - bodyFontSize: 12, - titleFontFamily: FONT_FAMILY, - titleFontSize: 14, + cornerRadius: 2, + bodyFontFamily: FONT_SANS, + bodyFontSize: 16, + titleFontFamily: FONT_SANS, + titleFontSize: 18, titleFontStyle: "normal", titleMarginBottom: 10, xPadding: 10, diff --git a/frontend/app/components/worktime-balance-chart/template.hbs b/frontend/app/components/worktime-balance-chart/template.hbs index 965e139e3..6aa411cb2 100644 --- a/frontend/app/components/worktime-balance-chart/template.hbs +++ b/frontend/app/components/worktime-balance-chart/template.hbs @@ -1 +1 @@ - + \ No newline at end of file diff --git a/frontend/app/controllers/qpcontroller.js b/frontend/app/controllers/qpcontroller.js index d9d3ea99e..eb25522a0 100644 --- a/frontend/app/controllers/qpcontroller.js +++ b/frontend/app/controllers/qpcontroller.js @@ -32,7 +32,7 @@ export default class ControllersQPControllerController extends Controller { value: this[key], enumerable: true, }), - {} + {}, ); } } diff --git a/frontend/app/helpers/balance-highlight-class.js b/frontend/app/helpers/balance-highlight-class.js index c3ac54446..bd4d744a4 100644 --- a/frontend/app/helpers/balance-highlight-class.js +++ b/frontend/app/helpers/balance-highlight-class.js @@ -21,9 +21,9 @@ export function balanceHighlightClass([balance]) { const minutes = moment.isDuration(balance) ? balance.asMinutes() : 0; if (minutes > 0) { - return "color-success"; + return "text-success"; } else if (minutes < 0) { - return "color-danger"; + return "text-danger"; } return ""; diff --git a/frontend/app/index.html b/frontend/app/index.html index 9d5e0817e..cc6e7a676 100644 --- a/frontend/app/index.html +++ b/frontend/app/index.html @@ -1,22 +1,25 @@ - + Timed - - - + + + {{content-for "head"}} + + + {{content-for "head-footer"}} - + {{content-for "body"}} diff --git a/frontend/app/index/activities/controller.js b/frontend/app/index/activities/controller.js index 2d00ff6f7..30d7234c2 100644 --- a/frontend/app/index/activities/controller.js +++ b/frontend/app/index/activities/controller.js @@ -176,7 +176,7 @@ export default class ActivitiesIndexController extends Controller { (a) => a.get("task.id") && !(a.get("active") && !a.get("from").isSame(moment(), "day")) && - !a.get("transferred") + !a.get("transferred"), ) .reduce(async (reducer, activity) => { if (activity.get("active")) { diff --git a/frontend/app/index/activities/edit/route.js b/frontend/app/index/activities/edit/route.js index be01451f4..f2bbcd13e 100644 --- a/frontend/app/index/activities/edit/route.js +++ b/frontend/app/index/activities/edit/route.js @@ -52,7 +52,7 @@ export default class IndexActivityEditController extends Route { const changeset = new Changeset( model, lookupValidator(ActivityValidator), - ActivityValidator + ActivityValidator, ); changeset.validate(); diff --git a/frontend/app/index/activities/edit/template.hbs b/frontend/app/index/activities/edit/template.hbs index 971b2be85..cf89ed2a2 100644 --- a/frontend/app/index/activities/edit/template.hbs +++ b/frontend/app/index/activities/edit/template.hbs @@ -1,14 +1,12 @@
    -
    - -
    + +
    {{t.customer}}
    {{t.project}}
    - {{!-- template-lint-disable no-at-ember-render-modifiers --}} + {{! template-lint-disable no-at-ember-render-modifiers }}
    {{t.task}}
    -
    - - -
    -
    + + + Cancel +
    + + +
    +
    + + \ No newline at end of file diff --git a/frontend/app/index/activities/template.hbs b/frontend/app/index/activities/template.hbs index 068cbe8f7..7a1ae4e81 100644 --- a/frontend/app/index/activities/template.hbs +++ b/frontend/app/index/activities/template.hbs @@ -1,169 +1,195 @@ -
    - -
    +Generate timesheet -
    -
    {{outlet}}
    +
    +
    {{outlet}}
    -
    +
    {{#if this.activities}} - +
    {{#each this.sortedActivities as |activity|}} - {{!template-lint-disable no-invalid-interactive}} - - - - - - - - + + + {{/let}} {{/each}} -
    - {{moment-format activity.from "HH:mm"}} - - - {{#unless activity.active}} - {{moment-format activity.to "HH:mm"}} - {{/unless}} - - {{#if activity.task}} -
    - {{activity.task.project.customer.name}} - > - {{activity.task.project.name}} - > - {{activity.task.name}} + + {{moment-format activity.from "HH:mm"}} + - + {{#unless activity.active}} + {{moment-format activity.to "HH:mm"}} + {{/unless}} + + + {{#if activity.task}} +
    + {{activity.task.project.customer.name}} + > + {{activity.task.project.name}} + > + {{activity.task.name}} +
    + {{else}} + Unknown task + {{/if}} +
    + +
    {{activity.comment}}
    + {{#if activity.task.project.customerVisible}} + + {{/if}} +
    + +
    + Needs review
    +
    + Not billable
    +
    + + {{#if activity.active}} + + {{else}} + {{format-duration activity.duration}} + {{/if}} + + +
    + {{#if activity.active}} + + {{else}} + + {{/if}}
    - {{else}} - Unknown task - {{/if}} -
    -
    {{activity.comment}}
    - {{#if activity.task.project.customerVisible}} - - {{/if}} -
    -
    - Needs review
    -
    - Not billable
    -
    - {{#if activity.active}} - - {{else}} - {{format-duration activity.duration}} - {{/if}} - - {{#if activity.active}} - - {{else}} - - {{/if}} -
    + {{else}}
    No activities yet
    {{/if}}
    - + - Activities overlap +

    Activities overlap

    Overlapping activities will not be taken into account for the timesheet. - + + >Cancel + >That's fine -
    + - + - Activities contain unknown tasks +

    Activities contain unknown tasks

    Unknown tasks will not be taken into account for the timesheet. - + + >Cancel + >That's fine -
    + \ No newline at end of file diff --git a/frontend/app/index/attendances/template.hbs b/frontend/app/index/attendances/template.hbs index 352b5607b..e64ec6cd3 100644 --- a/frontend/app/index/attendances/template.hbs +++ b/frontend/app/index/attendances/template.hbs @@ -1,71 +1,66 @@ -
    - -
    -
    +Add attendance + + +
    {{#if this.attendances}} - {{#if (or (media "isXl") (media "isLg") (media "isMd"))}} +
    {{#each this.attendances as |attendance|}} {{/each}} - {{else}} - - - {{#each this.attendances as |attendance|}} - {{#let (changeset attendance this.AttendanceValidator) as |model|}} - - - - - - {{/let}} - {{/each}} - -
    - - - - - - -
    - {{/if}} +
    + +
    + {{#each this.attendances as |attendance|}} + {{#let (changeset attendance this.AttendanceValidator) as |model|}} +
    + + +
    + + +
    +
    + {{/let}} + {{/each}} +
    {{else}}
    No attendances yet
    {{/if}} -
    -
    -
    -
    +
    \ No newline at end of file diff --git a/frontend/app/index/controller.js b/frontend/app/index/controller.js index 76d766aaf..6543ed295 100644 --- a/frontend/app/index/controller.js +++ b/frontend/app/index/controller.js @@ -23,6 +23,8 @@ import { cached } from "tracked-toolbox"; export default class IndexController extends Controller { queryParams = ["day"]; + negate = (n) => n * -1; + @tracked showAddModal = false; @tracked showEditModal = false; @tracked day = moment().format("YYYY-MM-DD"); @@ -33,10 +35,11 @@ export default class IndexController extends Controller { /* istanbul ignore next */ @trackedWrapper disabledDates = []; - @service store; + @service currentUser; + @service media; @service notify; + @service store; @service tracking; - @service currentUser; AbsenceValidations = AbsenceValidations; MultipleAbsenceValidations = MultipleAbsenceValidations; @@ -253,7 +256,7 @@ export default class IndexController extends Controller { return [...reportDurations, ...absenceDurations].reduce( (val, dur) => val.add(dur), - moment.duration() + moment.duration(), ); } @@ -318,6 +321,22 @@ export default class IndexController extends Controller { return get(this, "currentUser.user.activeEmployment.location.workdays"); } + get weeklyOverviewSliceValue() { + if (this.media.isLg) { + return 5; + } + + if (this.media.isMd) { + return 10; + } + + if (this.media.isSm) { + return 15; + } + + return 21; + } + /** * The task to compute the data for the weekly overview * @@ -329,14 +348,14 @@ export default class IndexController extends Controller { (report) => report.get("user.id") === this.currentUser.user.get("id") && !report.get("isDeleted") && - !report.get("isNew") + !report.get("isNew"), ); const allAbsences = this.allAbsences.filter( (absence) => absence.get("user.id") === this.currentUser.user.get("id") && !absence.get("isDeleted") && - !absence.get("isNew") + !absence.get("isNew"), ); const allHolidays = this.store.peekAll("public-holiday"); @@ -360,11 +379,11 @@ export default class IndexController extends Controller { return obj; }, - {} + {}, ); - return Array.from({ length: 31 }, (value, index) => - moment(this.date).add(index - 20, "days") + return Array.from({ length: 56 }, (value, index) => + moment(this.date).add(index - 28, "days"), ).map((d) => { const { reports = [], @@ -461,7 +480,7 @@ export default class IndexController extends Controller { */ get disabledDatesForEdit() { return this.disabledDates.filter( - (date) => !date.isSame(this.absence.date, "day") + (date) => !date.isSame(this.absence.date, "day"), ); } diff --git a/frontend/app/index/reports/controller.js b/frontend/app/index/reports/controller.js index 0476663c2..741a871ca 100644 --- a/frontend/app/index/reports/controller.js +++ b/frontend/app/index/reports/controller.js @@ -166,7 +166,7 @@ export default class IndexReportController extends Controller { if (reports.length < this.reports.length - 1) { /* istanbul ignore next */ this.notify.warning( - "Reports that got verified already can not get transferred." + "Reports that got verified already can not get transferred.", ); } @@ -174,7 +174,7 @@ export default class IndexReportController extends Controller { reports.map(async (report) => { report.set("date", date); return await report.save(); - }) + }), ); this.showReschedule = false; this.router.transitionTo({ diff --git a/frontend/app/index/reports/route.js b/frontend/app/index/reports/route.js index 3b7578fee..fa01614ea 100644 --- a/frontend/app/index/reports/route.js +++ b/frontend/app/index/reports/route.js @@ -51,7 +51,7 @@ export default class IndexReportsRoute extends Route { controller.notBillable = null; this.notify.success( - "Temporary report was created. Please amend it and save it or delete it." + "Temporary report was created. Please amend it and save it or delete it.", ); } catch { /* istanbul ignore next */ diff --git a/frontend/app/index/reports/template.hbs b/frontend/app/index/reports/template.hbs index 21609c35b..c88e0069b 100644 --- a/frontend/app/index/reports/template.hbs +++ b/frontend/app/index/reports/template.hbs @@ -1,39 +1,36 @@ -
    - -
    +Reschedule + -
    -
    - {{#each this.reports as |report|}} - - {{/each}} -
    +
    + {{#each this.reports as |report|}} + + {{/each}}
    - - Reschedule timesheet +

    Reschedule timesheet

    - + + -
    + \ No newline at end of file diff --git a/frontend/app/index/route.js b/frontend/app/index/route.js index 037c690c2..dff621228 100644 --- a/frontend/app/index/route.js +++ b/frontend/app/index/route.js @@ -69,8 +69,8 @@ export default class IndexRoute extends Route { const userId = this.currentUser.user.id; const day = model.format(DATE_FORMAT); - const from = moment(model).subtract(20, "days").format(DATE_FORMAT); - const to = moment(model).add(10, "days").format(DATE_FORMAT); + const from = moment(model).subtract(28, "days").format(DATE_FORMAT); + const to = moment(model).add(28, "days").format(DATE_FORMAT); const location = this.store .peekRecord("user", userId) .get("activeEmployment.location.id"); diff --git a/frontend/app/index/template.hbs b/frontend/app/index/template.hbs index faec1f4ec..91d55d7da 100644 --- a/frontend/app/index/template.hbs +++ b/frontend/app/index/template.hbs @@ -1,123 +1,127 @@ -
    -
    -
    -

    {{moment-format @model "dddd, DD.MM.YYYY"}}

    -
    -
    - -
    -
    - - {{#each this.weeklyOverviewData.value as |d|}} - - {{/each}} - -
    - +{{outlet}} {{#if this.absence}} {{#let (changeset this.absence this.AbsenceValidations) as |cs|}} - - Edit absence +

    Edit absence

    - + -
    +
    {{#each this.absenceTypes as |at|}} {{/each}} @@ -148,7 +154,7 @@ - +
    - + {{/let}} {{/if}} {{#let (changeset this.newAbsence this.MultipleAbsenceValidations) as |cs|}} - -
    - - - New absence - - - -
    - {{#each this.absenceTypes as |at|}} - - {{/each}} -
    -
    - - -
    - - + {{#let + (queue (toggle "showAddModal" this) (fn this.rollback cs)) + as |onClose| + }} + +
    + + +

    New absence

    +
    + + +
    + {{#each this.absenceTypes as |at|}} + + {{/each}}
    - -
    - -
    - - - -
    -
    - -{{/let}} + + + + +
    + + +
    +
    +
    + + + + + + + +
    + + {{/let}} +{{/let}} \ No newline at end of file diff --git a/frontend/app/login/template.hbs b/frontend/app/login/template.hbs index 5ff79e339..663ab9888 100644 --- a/frontend/app/login/template.hbs +++ b/frontend/app/login/template.hbs @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/frontend/app/models/activity.js b/frontend/app/models/activity.js index e92782c43..fc5a1c5cc 100644 --- a/frontend/app/models/activity.js +++ b/frontend/app/models/activity.js @@ -104,7 +104,7 @@ export default class Activity extends Model { review: this.review, notBillable: this.notBillable, fromTime: moment({ h: 0, m: 0, s: 0 }), - }) + }), ); } @@ -121,18 +121,18 @@ export default class Activity extends Model { m: 59, s: 59, }), - moment() - ) + moment(), + ), ); await activity.save(); - }) + }), ); if (moment().diff(this.date, "days") > 1) { this.notify.info( "The activity overlapped multiple days, which is not possible. The activity was stopped at midnight of the day it was started.", - { closeAfter: 5000 } + { closeAfter: 5000 }, ); } } diff --git a/frontend/app/no-access/template.hbs b/frontend/app/no-access/template.hbs index 763f2c563..1b3ad50fd 100644 --- a/frontend/app/no-access/template.hbs +++ b/frontend/app/no-access/template.hbs @@ -1,6 +1,4 @@ -
    -
    - -

    You do not have permission to access Timed.

    -
    -
    + + +

    You do not have permission to access Timed.

    +
    \ No newline at end of file diff --git a/frontend/app/notfound/template.hbs b/frontend/app/notfound/template.hbs index e6d675729..0a51fbf9e 100644 --- a/frontend/app/notfound/template.hbs +++ b/frontend/app/notfound/template.hbs @@ -1,4 +1,4 @@

    404

    The site you requested does not exist

    -
    +
    \ No newline at end of file diff --git a/frontend/app/projects/controller.js b/frontend/app/projects/controller.js index 356d86827..cd5c6f70b 100644 --- a/frontend/app/projects/controller.js +++ b/frontend/app/projects/controller.js @@ -37,7 +37,7 @@ export default class ProjectsController extends Controller { get customers() { return uniqBy( this.projects?.map((p) => p?.get("customer")).filter(Boolean) ?? [], - (c) => c.get("id") + (c) => c.get("id"), ).toSorted((c) => c.get("name")); } @@ -68,7 +68,7 @@ export default class ProjectsController extends Controller { *filterProjects() { return yield this.projects.filter( (project) => - project.get("customer.id") === this.selectedCustomer.get("id") + project.get("customer.id") === this.selectedCustomer.get("id"), ); } @@ -150,7 +150,7 @@ export default class ProjectsController extends Controller { ) { changeset.set( "mostRecentRemainingEffort", - changeset.get("estimatedTime") + changeset.get("estimatedTime"), ); } } diff --git a/frontend/app/projects/template.hbs b/frontend/app/projects/template.hbs index 9bff940c2..8b37e460f 100644 --- a/frontend/app/projects/template.hbs +++ b/frontend/app/projects/template.hbs @@ -1,14 +1,15 @@ +

    Projects

    {{#if this.loading}} -
    + -
    + {{else}} -
    +
    -
    {{customer.name}}
    +
    -
    {{project.name}}
    +
    {{#if this.selectedProject}} @@ -44,10 +47,8 @@ this.selectedProject.remainingEffortTracking as |remainingEffortTracking| }} -

    - - {{this.selectedProject.name}} - +

    + {{this.selectedProject.name}}

    - Remaining Effort Tracking + >Remaining Effort Tracking {{#if (and @@ -71,9 +72,9 @@ {{humanize-duration this.selectedProject.totalRemainingEffort}} {{/if}} -
    +
    {{#each f.model.errors as |error|}} -
    +
    {{/each}} @@ -87,11 +88,11 @@
    -
    -

    - +
    +
    +

    Tasks - +

    -

    - + Hide Archived Tasks - - Hide Archived Tasks +
    + + + Name + Reference + Estimated time + {{#if remainingEffortTracking}} + Remaining effort + {{/if}} + Archived + + +
    + + @@ -121,132 +135,134 @@ {{/if}} - - - - - - {{#if remainingEffortTracking}} - - {{/if}} - - - {{#each this.tasks as |task|}} {{#unless (and this.hideArchivedTasks task.archived)}} - - - - - - {{#if remainingEffortTracking}} - - {{/if}} - - + }} + {{if + task.estimatedTime + (humanize-duration task.estimatedTime) + "-" + }} + + {{#if remainingEffortTracking}} + {{if + task.mostRecentRemainingEffort + (humanize-duration task.mostRecentRemainingEffort) + "-" + }} + {{/if}} + + {{/unless}} {{/each}} -
    NameReferenceEstimated timeRemaining effortArchived
    {{task.name}}{{if - task.reference - task.reference - "-" - }}{{if - task.estimatedTime - (humanize-duration task.estimatedTime) - "-" - }}{{if - task.mostRecentRemainingEffort - (humanize-duration task.mostRecentRemainingEffort) + + {{task.name}} + {{if + task.reference + task.reference "-" - }}
    +
    {{#if this.selectedTask}}
    -

    {{if +

    {{if this.selectedTask.isNew "Add task" this.selectedTask.name }}

    -
    -
    - - + + +
    + +
    -
    - -
    - - -
    -
    + - {{#if remainingEffortTracking}} - -
    - - -
    -
    - {{/if}} + - -
    - - -
    -
    -
    -
    -
    + {{#if remainingEffortTracking}} + +
    + + +
    +
    + {{/if}} + + + + + +
    + + +

    Please select a customer and a project

    +
    {{/if}} {{/if}} - + \ No newline at end of file diff --git a/frontend/app/protected/controller.js b/frontend/app/protected/controller.js index 37de2f534..b3d666011 100644 --- a/frontend/app/protected/controller.js +++ b/frontend/app/protected/controller.js @@ -2,7 +2,71 @@ import Controller from "@ember/controller"; import { action } from "@ember/object"; import { service } from "@ember/service"; import { tracked } from "@glimmer/tracking"; +import { keyResponder, onKey } from "ember-keyboard"; +const getHtml = () => document.querySelector("html"); + +const COLOR_SCHEME_KEY = "color-scheme"; +const THEME_KEY = "theme"; + +/** + * Sets dark or light mode + * @param {"light" | "dark"} colorScheme + * @param {ReturnType} html + **/ +const setColorScheme = (colorScheme, html = null) => { + const _html = html ?? getHtml(); + localStorage.setItem(COLOR_SCHEME_KEY, colorScheme); + + if (colorScheme === "light") { + _html.classList.remove("dark"); + return; + } + _html.classList.add("dark"); +}; + +const THEMES = /** @type {const} */ (["old", "regular"]); + +/** + * Sets regular or old color scheme + * @param {typeof THEMES[number]} theme + * @param {ReturnType} html + **/ +const setTheme = (theme, html = null) => { + const _html = html ?? getHtml(); + localStorage.setItem(THEME_KEY, theme); + + if (_html.classList.contains(theme)) { + return; + } + _html.classList.remove(...THEMES.filter((t) => t !== theme)); + _html.classList.add(theme); +}; + +const loadConfiguration = () => { + const colorScheme = + localStorage.getItem(COLOR_SCHEME_KEY) ?? + (window.matchMedia("(prefers-color-scheme:dark)").matches + ? "dark" + : "light"); + const theme = localStorage.getItem(THEME_KEY) ?? THEMES[0]; + const html = getHtml(); + setTheme(theme, html); + setColorScheme(colorScheme, html); +}; + +const toggleColorScheme = () => + setColorScheme( + localStorage.getItem(COLOR_SCHEME_KEY) === "dark" ? "light" : "dark", + ); + +const cycleTheme = () => { + const currentTheme = localStorage.getItem(THEME_KEY); + const newTheme = THEMES[THEMES.indexOf(currentTheme) + 1] ?? THEMES[0]; + setTheme(newTheme); +}; + +@keyResponder export default class ProtectedController extends Controller { @service notify; @service router; @@ -74,4 +138,21 @@ export default class ProtectedController extends Controller { this.tour.prepare(this.currentUser.user); this.tour.startTour(); } + + constructor(...args) { + super(...args); + loadConfiguration(); + } + + @onKey("ctrl+,") + _toggleColorScheme(e) { + e.preventDefault(); + toggleColorScheme(); + } + + @onKey("ctrl+.") + _cycleTheme(e) { + e.preventDefault(); + cycleTheme(); + } } diff --git a/frontend/app/protected/route.js b/frontend/app/protected/route.js index cdf75afb5..0b6b1e244 100644 --- a/frontend/app/protected/route.js +++ b/frontend/app/protected/route.js @@ -38,7 +38,7 @@ export default class ProtectedRoute extends Route { const visible = !this.autostartTour.allDone && !this.currentUser.user.tourDone && - (this.media.isMd || this.media.isLg || this.media.isXl); + this.media.isMd; controller.set("visible", visible); } diff --git a/frontend/app/protected/template.hbs b/frontend/app/protected/template.hbs index 14941d8f0..92b48aeb2 100644 --- a/frontend/app/protected/template.hbs +++ b/frontend/app/protected/template.hbs @@ -1,8 +1,10 @@ -
    +
    {{#if this.loading}}{{/if}} -
    - - +
    + +
    {{outlet}}
    @@ -12,4 +14,4 @@ @onNever={{this.neverTour}} @onLater={{this.laterTour}} @onStart={{this.startTour}} -/> +/> \ No newline at end of file diff --git a/frontend/app/services/current-user.js b/frontend/app/services/current-user.js index d2e6524e2..23d9c4562 100644 --- a/frontend/app/services/current-user.js +++ b/frontend/app/services/current-user.js @@ -17,7 +17,7 @@ export default class CurrentUserService extends Service { })}`, { method: "GET", - } + }, ); await this.store.pushPayload("user", user); diff --git a/frontend/app/services/fetch.js b/frontend/app/services/fetch.js index e950f900f..5dbd6f60b 100644 --- a/frontend/app/services/fetch.js +++ b/frontend/app/services/fetch.js @@ -75,7 +75,7 @@ export default class FetchService extends Service { response, body, error: new Error( - `Fetch request to URL ${response.url} returned ${response.status} ${response.statusText}:\n\n${body}` + `Fetch request to URL ${response.url} returned ${response.status} ${response.statusText}:\n\n${body}`, ), }; } diff --git a/frontend/app/services/metadata-fetcher.js b/frontend/app/services/metadata-fetcher.js index eeb9f7429..76b512647 100644 --- a/frontend/app/services/metadata-fetcher.js +++ b/frontend/app/services/metadata-fetcher.js @@ -77,11 +77,11 @@ export default class MetadataFetcherService extends Service { [key]: value ? transform.deserialize(value) : defaultValue, }; }, - {} + {}, ); const attributesValues = Object.keys( - ATTRIBUTE_MODELS[camelize(type)] + ATTRIBUTE_MODELS[camelize(type)], ).reduce((parsedAttribute, key) => { const { defaultValue, transform } = ATTRIBUTE_MODELS[camelize(type)][key]; const value = attributes[dasherize(key)]; diff --git a/frontend/app/services/rejected-reports.js b/frontend/app/services/rejected-reports.js index 88197b3ae..b5e1db90c 100644 --- a/frontend/app/services/rejected-reports.js +++ b/frontend/app/services/rejected-reports.js @@ -29,7 +29,7 @@ export default class RejectedReportsService extends Service { } else { this.intervalId = setInterval( this.pollReports.bind(this), - INTERVAL_DELAY + INTERVAL_DELAY, ); } } diff --git a/frontend/app/services/tour.js b/frontend/app/services/tour.js index d57f0ac1f..d590c2de8 100644 --- a/frontend/app/services/tour.js +++ b/frontend/app/services/tour.js @@ -100,12 +100,12 @@ export default class TourService extends Tour { text: data.content, buttons: [ { - classes: "shepherd-button-secondary", + classes: "shepherd-button-tertiary-dark btn-default btn", text: "Exit", type: "cancel", }, { - classes: "shepherd-button-primary", + classes: "shepherd-button-primary btn-primary btn", text: "Next", type: "next", }, @@ -121,7 +121,7 @@ export default class TourService extends Tour { return ( !this.model.tourDone && !this.autostartTour.done.includes(this.routeName) && - (this.media.isMd || this.media.isLg || this.media.isXl) + this.media.isMd ); } @@ -157,7 +157,7 @@ export default class TourService extends Tour { } else { try { await this.router.transitionTo( - this.autostartTour.undoneTours.shift() ?? "index" + this.autostartTour.undoneTours.shift() ?? "index", ); } catch { /* eslint:disable:no-empty */ diff --git a/frontend/app/services/tracking.js b/frontend/app/services/tracking.js index 0df09deef..6dea8a1f8 100644 --- a/frontend/app/services/tracking.js +++ b/frontend/app/services/tracking.js @@ -112,7 +112,7 @@ export default class TrackingService extends Service { scheduleOnce( "afterRender", this, - this.scheduleDocumentTitle.bind(this, title) + this.scheduleDocumentTitle.bind(this, title), ); } diff --git a/frontend/app/services/unverified-reports.js b/frontend/app/services/unverified-reports.js index b320b70e8..71fc40a50 100644 --- a/frontend/app/services/unverified-reports.js +++ b/frontend/app/services/unverified-reports.js @@ -40,7 +40,7 @@ export default class UnverifiedReportsService extends Service { if (macroCondition(!isTesting())) { this.intervalId = setInterval( this.pollReports.bind(this), - INTERVAL_DELAY + INTERVAL_DELAY, ); } } diff --git a/frontend/app/statistics/controller.js b/frontend/app/statistics/controller.js index ad0ebd34e..9bad65cdf 100644 --- a/frontend/app/statistics/controller.js +++ b/frontend/app/statistics/controller.js @@ -17,16 +17,21 @@ const TYPES = { project: { include: "customer", requiredParams: ["customer"], + mobile: false, }, task: { include: "project,project.customer", requiredParams: ["customer", "project"], + mobile: false, }, user: { include: "user", requiredParams: [] }, }; export default class StatisticsController extends QPController { types = Object.keys(TYPES); + mobileTypes = Object.entries(TYPES) + .filter(([, v]) => v.mobile !== false) + .map(([k]) => k); queryParams = [ "customer", @@ -122,7 +127,7 @@ export default class StatisticsController extends QPController { get missingParams() { return this.requiredParams.filter( - (param) => !queryParamsState(this)[param].changed + (param) => !queryParamsState(this)[param].changed, ); } @@ -169,7 +174,7 @@ export default class StatisticsController extends QPController { const type = this.type; let params = underscoreQueryParams( - serializeQueryParams(this.allQueryParams, queryParamsState(this)) + serializeQueryParams(this.allQueryParams, queryParamsState(this)), ); params = Object.keys(params).reduce((obj, key) => { diff --git a/frontend/app/statistics/template.hbs b/frontend/app/statistics/template.hbs index 542172665..f16908100 100644 --- a/frontend/app/statistics/template.hbs +++ b/frontend/app/statistics/template.hbs @@ -1,221 +1,211 @@ -{{#if (or (media "isMo") (media "isXs") (media "isSm"))}} - -{{else}} - -

    Statistics

    + +

    Statistics

    - + - - - - Customer - - - - - - Project - - - - - - Task - - - - - - - - User - - - - - - - - Reviewer - - - - - - - - - - Billing type - - - - Cost center - - - - - - From - - - - To - - - - - - - Review - - - - Billability - - - - Verified - - - - Billed - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
    - -
    + + +
    + + -
    - -
    -
    -{{/if}} + + +
    + + +
    +
    \ No newline at end of file diff --git a/frontend/app/styles/activities.scss b/frontend/app/styles/activities.scss deleted file mode 100644 index 45c929145..000000000 --- a/frontend/app/styles/activities.scss +++ /dev/null @@ -1,74 +0,0 @@ -.activities { - display: flex; - flex-direction: row-reverse; -} - -.table--activity-edit > tbody > tr > td { - vertical-align: middle; - text-align: center; - - &:nth-child(1) { - width: 80px; - } - - &:nth-child(2) { - width: 25px; - } - - &:nth-child(3) { - width: 80px; - } -} - -.activities-list { - flex: 1 1 auto; - overflow: hidden; - - tr.selected td { - background-color: #1e87f0; - color: #fff; - } -} - -.activities-edit { - flex: 0 1 100%; - - &:empty { - flex-basis: 0%; - } - - &:not(:empty) + .activities-list { - flex-basis: 0%; - } -} - -.transferred { - cursor: not-allowed; - color: #a29b96; -} - -.checkboxes { - display: flex; - justify-content: space-around; -} - -@media #{$lg-viewport} { - .activities-edit:not(:empty) + .activities-list { - flex-basis: 70%; - } - - .activities-edit { - padding-left: 1rem; - flex: 0 1 45%; - } - - .activities-edit:empty { - padding-left: 0; - } -} - -@media #{$xl-viewport} { - .activities-edit { - flex-basis: 30%; - } -} diff --git a/frontend/app/styles/adcssy.scss b/frontend/app/styles/adcssy.scss deleted file mode 100644 index e60a547ee..000000000 --- a/frontend/app/styles/adcssy.scss +++ /dev/null @@ -1,4148 +0,0 @@ -.color-primary { - color: #5b8edb; -} - -.color-secondary { - color: #a29b96; -} - -.color-tertiary { - color: #867f7c; -} - -.color-success { - color: #5cb85c; -} - -.color-info { - color: #5bc0de; -} - -.color-warning { - color: #f0ad4e; -} - -.color-danger { - color: #d9534f; -} - -.background-color-primary { - background-color: #5b8edb; -} - -.background-color-secondary { - background-color: #a29b96; -} - -.background-color-tertiary { - background-color: #867f7c; -} - -.background-color-success { - background-color: #5cb85c; -} - -.background-color-info { - background-color: #5bc0de; -} - -.background-color-warning { - background-color: #f0ad4e; -} - -.background-color-danger { - background-color: #d9534f; -} - -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} - -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} - -@font-face { - font-family: TheSansLT; - font-weight: 300; - font-style: normal; - src: url("../fonts/TheSans_LT_300_.eot") format("embedded-opentype"), - url("../fonts/TheSans_LT_300_.svg") format("svg"), - url("../fonts/TheSans_LT_300_.woff") format("woff"); -} - -@font-face { - font-family: TheSansLT; - font-weight: 300; - font-style: italic; - src: url("../fonts/TheSans_LT_300i.eot") format("embedded-opentype"), - url("../fonts/TheSans_LT_300i.svg") format("svg"), - url("../fonts/TheSans_LT_300i.woff") format("woff"); -} - -@font-face { - font-family: TheSansLT; - font-weight: 500; - font-style: normal; - src: url("../fonts/TheSans_LT_500_.eot") format("embedded-opentype"), - url("../fonts/TheSans_LT_500_.svg") format("svg"), - url("../fonts/TheSans_LT_500_.woff") format("woff"); -} - -@font-face { - font-family: TheSansLT; - font-weight: 500; - font-style: italic; - src: url("../fonts/TheSans_LT_500i.eot") format("embedded-opentype"), - url("../fonts/TheSans_LT_500i.svg") format("svg"), - url("../fonts/TheSans_LT_500i.woff") format("woff"); -} - -.media-debug::before { - content: "mo"; - text-transform: uppercase; - position: fixed; - display: block; - top: 0; - right: 0; - padding: 5px; - border-left: 1px solid; - border-bottom: 1px solid; - border-color: #e1e1e1; - background-color: rgb(92 184 92 / 70%); - z-index: 99999; -} - -@media only screen and (width >=480px) { - .media-debug::before { - content: "xs"; - background-color: rgb(132 152 88 / 76%); - } -} - -@media only screen and (width >=768px) { - .media-debug::before { - content: "sm"; - background-color: rgb(161 128 85 / 82%); - } -} - -@media only screen and (width >=992px) { - .media-debug::before { - content: "md"; - background-color: rgb(184 110 82 / 88%); - } -} - -@media only screen and (width >=1200px) { - .media-debug::before { - content: "lg"; - background-color: rgb(202 95 81 / 94%); - } -} - -@media only screen and (width >=1440px) { - .media-debug::before { - content: "xl"; - background-color: rgb(217 83 79 / 70%); - } -} - -*, -::after, -::before { - box-sizing: border-box; -} - -body { - margin: 0; -} - -main { - display: block; -} - -ol, -ul { - padding-left: 0; - margin: 0; -} - -ol > li, -ul > li { - margin-left: 0; -} - -button, -input, -optgroup, -select, -textarea { - color: inherit; - font: inherit; - line-height: inherit; - margin: 0; -} - -textarea { - min-height: 4em; -} - -fieldset { - border: 0; - margin: 0; - padding: 0; -} - -button { - overflow: visible; -} - -button, -select { - text-transform: none; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -[hidden] { - display: none !important; -} - -template { - display: none; -} - -progress { - display: inline-block; -} - -code, -kbd, -pre, -samp, -tt { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 1em; -} - -html { - height: 100%; - background: #fff; - color: #3d3d3d; - font-weight: 400; - font-family: "Source Sans Pro", sans-serif; - font-size: calc(11px + 5 * ((100vw - 420px) / 1020)); -} - -@media screen and (width >=1440px) { - html { - font-size: 16px; - } -} - -@media screen and (width <=420px) { - html { - font-size: 11px; - } -} - -a { - color: #5b8edb; - text-decoration: none; -} - -a:hover { - transition: background 0.1s ease 0, color 0.1s ease 0; -} - -a:active, -a:hover { - color: #86ace4; -} - -a:focus { - outline: thin dotted; - outline-offset: -1px; -} - -a:visited { - color: #3272d2; -} - -::selection { - background-color: #c4d7f2; - text-shadow: none; -} - -.hidden, -.sr-only, -.visible-lg, -.visible-md, -.visible-sm, -.visible-xl, -.visible-xs { - display: none !important; -} - -@media only screen and (width >=480px) { - .visible-xs { - display: block !important; - } - - table.visible-xs { - display: table !important; - } - - tr.visible-xs { - display: table-row !important; - } - - td.visible-xs, - th.visible-xs { - display: table-cell !important; - } - - .hidden-xs { - display: none !important; - } -} - -@media only screen and (width >=768px) { - .visible-sm { - display: block !important; - } - - table.visible-sm { - display: table !important; - } - - tr.visible-sm { - display: table-row !important; - } - - td.visible-sm, - th.visible-sm { - display: table-cell !important; - } - - .hidden-sm { - display: none !important; - } -} - -@media only screen and (width >=992px) { - .visible-md { - display: block !important; - } - - table.visible-md { - display: table !important; - } - - tr.visible-md { - display: table-row !important; - } - - td.visible-md, - th.visible-md { - display: table-cell !important; - } - - .hidden-md { - display: none !important; - } -} - -@media only screen and (width >=1200px) { - .visible-lg { - display: block !important; - } - - table.visible-lg { - display: table !important; - } - - tr.visible-lg { - display: table-row !important; - } - - td.visible-lg, - th.visible-lg { - display: table-cell !important; - } - - .hidden-lg { - display: none !important; - } -} - -@media only screen and (width >=1440px) { - .visible-xl { - display: block !important; - } - - table.visible-xl { - display: table !important; - } - - tr.visible-xl { - display: table-row !important; - } - - td.visible-xl, - th.visible-xl { - display: table-cell !important; - } - - .hidden-xl { - display: none !important; - } -} - -.link-prefix::before { - content: ">"; - vertical-align: 6%; - padding: 0 0.2em 0 0; - transition: padding 0.1s; - display: inline-block; - background-color: #fff; -} - -.link-prefix:focus::before, -.link-prefix:hover::before { - padding: 0 0.1em; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} - -.flex-grow { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -button.close { - padding: 0; - cursor: pointer; - background: none; - border: 0; -} - -.close { - float: right; - font-size: 1.5rem; - font-weight: 500; - line-height: 1; - color: #000; - opacity: 0.33; - text-shadow: 0 1px 0 #fff; -} - -.close:focus, -.close:hover { - color: #000; - text-decoration: none; - cursor: pointer; - opacity: 0.75; -} - -@keyframes a { - 0% { - transform: translateX(-100%); - } - - 100% { - transform: none; - } -} - -@keyframes a { - 0% { - transform: translateX(-100%); - } - - 100% { - transform: none; - } -} - -@keyframes b { - 0% { - transform: translateX(100%); - } - - 100% { - transform: none; - } -} - -@keyframes b { - 0% { - transform: translateX(100%); - } - - 100% { - transform: none; - } -} - -.slide-in { - animation: 0.2s ease-out 0s normal forwards 1 running a; -} - -.slide-in--to-left { - animation-name: b; -} - -@keyframes c { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} - -@keyframes c { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} - -.fade-in { - animation: 0.2s ease 0s normal forwards 1 running c; -} - -@keyframes d { - 0% { - opacity: 1; - } - - 50% { - opacity: 0; - } - - 100% { - opacity: 0; - } -} - -@keyframes d { - 0% { - opacity: 1; - } - - 50% { - opacity: 0; - } - - 100% { - opacity: 0; - } -} - -.loading-dots i { - animation: d 1.3s infinite; - font-style: normal; - opacity: 1; -} - -.loading-dots i + i { - animation-delay: 0.1s; - opacity: 0; -} - -.loading-dots i + i + i { - animation-delay: 0.2s; -} - -@keyframes e { - 0% { - background-position: 45px 0; - } - - 100% { - background-position: 0 0; - } -} - -@keyframes e { - 0% { - background-position: 45px 0; - } - - 100% { - background-position: 0 0; - } -} - -.btn.loading, -.loadingbar-stripes, -.nav-side-list .ember-transitioning-in, -.nav-tabs .ember-transitioning-in { - position: relative; - cursor: wait; - z-index: 0; -} - -.btn.loading::after, -.loadingbar-stripes::after, -.nav-side-list .ember-transitioning-in::after, -.nav-tabs .ember-transitioning-in::after { - content: ""; - pointer-events: none; - inset: 0; - position: absolute; - animation: 2s linear 0s normal none infinite running e; - background-image: linear-gradient( - 45deg, - hsl(0deg 0% 100% / 20%) 25%, - transparent 0, - transparent 50%, - hsl(0deg 0% 100% / 20%) 0, - hsl(0deg 0% 100% / 20%) 75%, - transparent 0, - transparent - ); - background-size: 45px 45px; - z-index: -1; -} - -@keyframes f { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(359deg); - } -} - -@keyframes f { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(359deg); - } -} - -.loading-mask { - position: relative; -} - -.loading-mask::before { - content: ""; - position: absolute; - z-index: 1; - inset: 0; - background-color: rgb(0 0 0 / 25%); -} - -.loading-mask::after { - content: ""; - position: absolute; - z-index: 2; - border: 3px solid #fff; - border-top-color: transparent; - border-radius: 50%; - width: 100px; - height: 100px; - top: calc(50% - 50px); - left: calc(50% - 50px); - animation: f 2s infinite linear; - filter: drop-shadow(0 0 2px rgb(0 0 0 / 33%)); -} - -.text-center { - text-align: center; -} - -.text-right { - text-align: right; -} - -.text-left { - text-align: left; -} - -.grid { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; - flex-wrap: wrap; - list-style: none; - margin: 0 -1rem 1rem; - padding: 0; -} - -.grid--nowrap { - flex-wrap: nowrap; -} - -.grid-cell { - -webkit-box-flex: 1; - flex: 1 0 auto; - padding-left: 1rem; - padding-right: 1rem; -} - -.grid--no-gutters { - margin-left: 0; - margin-right: 0; -} - -.grid--no-gutters > .grid-cell { - padding-left: 0; - padding-right: 0; -} - -.grid--row { - -webkit-box-orient: horizontal; - flex-direction: row; -} - -.grid--col, -.grid--row { - -webkit-box-direction: normal; -} - -.grid--col { - -webkit-box-orient: vertical; - flex-direction: column; -} - -.grid--row-reverse { - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - flex-direction: row-reverse; -} - -.grid--col-reverse { - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - flex-direction: column-reverse; -} - -.grid--align-start { - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; -} - -.grid--align-center { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.grid--align-end { - -webkit-box-align: end; - -ms-flex-align: end; - align-items: flex-end; -} - -.grid--justify-center { - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; -} - -.grid-cell--align-start { - -ms-flex-item-align: start; - align-self: flex-start; -} - -.grid-cell--align-center { - -ms-flex-item-align: center; - align-self: center; -} - -.grid-cell--align-end { - -ms-flex-item-align: end; - align-self: flex-end; -} - -.grid--1of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; -} - -.grid--2of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; -} - -.grid--3of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 25%; -} - -.grid--4of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; -} - -.grid--5of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; -} - -.grid--6of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 50%; -} - -.grid--7of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; -} - -.grid--8of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; -} - -.grid--9of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 75%; -} - -.grid--10of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; -} - -.grid--11of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; -} - -.grid--12of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 100%; -} - -@media only screen and (width >=480px) { - .grid-xs--row { - -webkit-box-orient: horizontal; - flex-direction: row; - } - - .grid-xs--col, - .grid-xs--row { - -webkit-box-direction: normal; - } - - .grid-xs--col { - -webkit-box-orient: vertical; - flex-direction: column; - } - - .grid-xs--row-reverse { - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - flex-direction: row-reverse; - } - - .grid-xs--col-reverse { - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - flex-direction: column-reverse; - } - - .grid-xs--1of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid-xs--2of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid-xs--3of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid-xs--4of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid-xs--5of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid-xs--6of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid-xs--7of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid-xs--8of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid-xs--9of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid-xs--10of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid-xs--11of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid-xs--12of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=768px) { - .grid-sm--row { - -webkit-box-orient: horizontal; - flex-direction: row; - } - - .grid-sm--col, - .grid-sm--row { - -webkit-box-direction: normal; - } - - .grid-sm--col { - -webkit-box-orient: vertical; - flex-direction: column; - } - - .grid-sm--row-reverse { - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - flex-direction: row-reverse; - } - - .grid-sm--col-reverse { - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - flex-direction: column-reverse; - } - - .grid-sm--1of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid-sm--2of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid-sm--3of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid-sm--4of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid-sm--5of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid-sm--6of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid-sm--7of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid-sm--8of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid-sm--9of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid-sm--10of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid-sm--11of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid-sm--12of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=992px) { - .grid-md--row { - -webkit-box-orient: horizontal; - flex-direction: row; - } - - .grid-md--col, - .grid-md--row { - -webkit-box-direction: normal; - } - - .grid-md--col { - -webkit-box-orient: vertical; - flex-direction: column; - } - - .grid-md--row-reverse { - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - flex-direction: row-reverse; - } - - .grid-md--col-reverse { - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - flex-direction: column-reverse; - } - - .grid-md--1of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid-md--2of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid-md--3of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid-md--4of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid-md--5of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid-md--6of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid-md--7of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid-md--8of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid-md--9of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid-md--10of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid-md--11of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid-md--12of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=1200px) { - .grid-lg--row { - -webkit-box-orient: horizontal; - flex-direction: row; - } - - .grid-lg--col, - .grid-lg--row { - -webkit-box-direction: normal; - } - - .grid-lg--col { - -webkit-box-orient: vertical; - flex-direction: column; - } - - .grid-lg--row-reverse { - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - flex-direction: row-reverse; - } - - .grid-lg--col-reverse { - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - flex-direction: column-reverse; - } - - .grid-lg--1of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid-lg--2of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid-lg--3of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid-lg--4of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid-lg--5of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid-lg--6of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid-lg--7of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid-lg--8of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid-lg--9of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid-lg--10of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid-lg--11of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid-lg--12of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=1440px) { - .grid-xl--row { - -webkit-box-orient: horizontal; - flex-direction: row; - } - - .grid-xl--col, - .grid-xl--row { - -webkit-box-direction: normal; - } - - .grid-xl--col { - -webkit-box-orient: vertical; - flex-direction: column; - } - - .grid-xl--row-reverse { - -webkit-box-orient: horizontal; - -webkit-box-direction: reverse; - flex-direction: row-reverse; - } - - .grid-xl--col-reverse { - -webkit-box-orient: vertical; - -webkit-box-direction: reverse; - flex-direction: column-reverse; - } - - .grid-xl--1of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid-xl--2of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid-xl--3of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid-xl--4of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid-xl--5of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid-xl--6of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid-xl--7of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid-xl--8of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid-xl--9of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid-xl--10of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid-xl--11of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid-xl--12of12 > .grid-cell { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -.grid > .grid-cell--1of12 { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; -} - -.grid > .grid-cell--2of12 { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; -} - -.grid > .grid-cell--3of12 { - -webkit-box-flex: 0; - flex: 0 0 25%; -} - -.grid > .grid-cell--4of12 { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; -} - -.grid > .grid-cell--5of12 { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; -} - -.grid > .grid-cell--6of12 { - -webkit-box-flex: 0; - flex: 0 0 50%; -} - -.grid > .grid-cell--7of12 { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; -} - -.grid > .grid-cell--8of12 { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; -} - -.grid > .grid-cell--9of12 { - -webkit-box-flex: 0; - flex: 0 0 75%; -} - -.grid > .grid-cell--10of12 { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; -} - -.grid > .grid-cell--11of12 { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; -} - -.grid > .grid-cell--12of12 { - -webkit-box-flex: 0; - flex: 0 0 100%; -} - -@media only screen and (width >=480px) { - .grid > .grid-cell-xs--1of12 { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid > .grid-cell-xs--2of12 { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid > .grid-cell-xs--3of12 { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid > .grid-cell-xs--4of12 { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid > .grid-cell-xs--5of12 { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid > .grid-cell-xs--6of12 { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid > .grid-cell-xs--7of12 { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid > .grid-cell-xs--8of12 { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid > .grid-cell-xs--9of12 { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid > .grid-cell-xs--10of12 { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid > .grid-cell-xs--11of12 { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid > .grid-cell-xs--12of12 { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=768px) { - .grid > .grid-cell-sm--1of12 { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid > .grid-cell-sm--2of12 { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid > .grid-cell-sm--3of12 { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid > .grid-cell-sm--4of12 { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid > .grid-cell-sm--5of12 { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid > .grid-cell-sm--6of12 { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid > .grid-cell-sm--7of12 { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid > .grid-cell-sm--8of12 { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid > .grid-cell-sm--9of12 { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid > .grid-cell-sm--10of12 { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid > .grid-cell-sm--11of12 { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid > .grid-cell-sm--12of12 { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=992px) { - .grid > .grid-cell-md--1of12 { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid > .grid-cell-md--2of12 { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid > .grid-cell-md--3of12 { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid > .grid-cell-md--4of12 { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid > .grid-cell-md--5of12 { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid > .grid-cell-md--6of12 { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid > .grid-cell-md--7of12 { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid > .grid-cell-md--8of12 { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid > .grid-cell-md--9of12 { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid > .grid-cell-md--10of12 { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid > .grid-cell-md--11of12 { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid > .grid-cell-md--12of12 { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=1200px) { - .grid > .grid-cell-lg--1of12 { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid > .grid-cell-lg--2of12 { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid > .grid-cell-lg--3of12 { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid > .grid-cell-lg--4of12 { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid > .grid-cell-lg--5of12 { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid > .grid-cell-lg--6of12 { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid > .grid-cell-lg--7of12 { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid > .grid-cell-lg--8of12 { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid > .grid-cell-lg--9of12 { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid > .grid-cell-lg--10of12 { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid > .grid-cell-lg--11of12 { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid > .grid-cell-lg--12of12 { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -@media only screen and (width >=1440px) { - .grid > .grid-cell-xl--1of12 { - -webkit-box-flex: 0; - flex: 0 0 8.3333%; - } - - .grid > .grid-cell-xl--2of12 { - -webkit-box-flex: 0; - flex: 0 0 16.6667%; - } - - .grid > .grid-cell-xl--3of12 { - -webkit-box-flex: 0; - flex: 0 0 25%; - } - - .grid > .grid-cell-xl--4of12 { - -webkit-box-flex: 0; - flex: 0 0 33.3333%; - } - - .grid > .grid-cell-xl--5of12 { - -webkit-box-flex: 0; - flex: 0 0 41.6667%; - } - - .grid > .grid-cell-xl--6of12 { - -webkit-box-flex: 0; - flex: 0 0 50%; - } - - .grid > .grid-cell-xl--7of12 { - -webkit-box-flex: 0; - flex: 0 0 58.3333%; - } - - .grid > .grid-cell-xl--8of12 { - -webkit-box-flex: 0; - flex: 0 0 66.6667%; - } - - .grid > .grid-cell-xl--9of12 { - -webkit-box-flex: 0; - flex: 0 0 75%; - } - - .grid > .grid-cell-xl--10of12 { - -webkit-box-flex: 0; - flex: 0 0 83.3333%; - } - - .grid > .grid-cell-xl--11of12 { - -webkit-box-flex: 0; - flex: 0 0 91.6667%; - } - - .grid > .grid-cell-xl--12of12 { - -webkit-box-flex: 0; - flex: 0 0 100%; - } -} - -.page { - -webkit-box-orient: vertical; - flex-direction: column; - min-height: 100%; -} - -.page, -.page-viewport, -.page.ember-application > .ember-view:first-of-type { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-direction: normal; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.page-viewport, -.page.ember-application > .ember-view:first-of-type { - -webkit-box-orient: horizontal; - flex-direction: row; - position: relative; - overflow: hidden; - width: 100vw; -} - -.page--column.ember-application > .ember-view:first-of-type, -.page-viewport--column { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; -} - -.page-content-footer, -.page-content-header { - -webkit-box-flex: 0; - flex: 0 0 auto; -} - -.page-content { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - min-height: 100vh; -} - -.page-main { - overflow: hidden; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.page-content, -.page-main { - display: -webkit-box; - display: flexbox; - display: flex; - background: #fff; -} - -.page-content--scroll, -.page-main--scroll { - height: 100vh; - overflow: auto; - scroll-behavior: smooth; - -webkit-overflow-scrolling: touch; -} - -.page-content-main { - -webkit-box-flex: 1; - flex: 1 0 auto; -} - -.page-content { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - padding: 1em 1.5em; -} - -@media only screen and (width >=1200px) { - .page-content { - padding: 1.25em 1.875em; - } -} - -@media only screen and (width >=1440px) { - .page-content { - padding: 1.5em 2.25em; - } -} - -.h1, -.h2, -.h3, -.h4, -.h5, -.h6, -h1, -h2, -h3, -h4, -h5, -h6 { - color: #000; - font-family: "Source Sans Pro", sans-serif; - font-feature-settings: "dlig", "liga", "lnum", "kern"; - font-weight: 500; - letter-spacing: -1; - line-height: 1.25; - margin: 0 0 0.4em; - text-rendering: geometricprecision; -} - -.h1, -h1 { - font-size: 31.5px; - color: #5b8edb; -} - -.h2, -h2 { - font-size: 28px; - color: #5b8edb; -} - -.h3, -h3 { - font-size: 25.2px; - color: #5b8edb; -} - -.h4, -h4 { - font-size: 21px; -} - -.h5, -h5 { - font-size: 17.5px; -} - -.h6, -h6 { - font-size: 15.4px; -} - -.h1 .small, -.h1 small, -.h2 .small, -.h2 small, -.h3 .small, -.h3 small, -.h4 .small, -.h4 small, -.h5 .small, -.h5 small, -.h6 .small, -.h6 small, -h1 .small, -h1 small, -h2 .small, -h2 small, -h3 .small, -h3 small, -h4 .small, -h4 small, -h5 .small, -h5 small, -h6 .small, -h6 small { - font-weight: 400; - line-height: 1; - color: gray; -} - -.typeset { - counter-reset: a; -} - -.typeset .h1-counter { - counter-reset: b; -} - -.typeset .h2-counter { - counter-reset: c; -} - -.typeset .h3-counter { - counter-reset: d; -} - -.typeset .h4-counter { - counter-reset: e; -} - -.typeset .h5-counter { - counter-reset: f; -} - -.typeset .h1-counter::before { - counter-increment: a; - content: counter(a) ". "; -} - -.typeset .h2-counter::before { - counter-increment: b; - content: counter(a) "." counter(b) ". "; -} - -.typeset .h3-counter::before { - counter-increment: c; - content: counter(a) "." counter(b) "." counter(c) ". "; -} - -.typeset .h4-counter::before { - counter-increment: d; - content: counter(a) "." counter(b) "." counter(c) "." counter(d) ". "; -} - -.typeset .h5-counter::before { - counter-increment: e; - content: counter(a) "." counter(b) "." counter(c) "." counter(d) "." - counter(e) ". "; -} - -.typeset .h6-counter::before { - counter-increment: f; - content: counter(a) "." counter(b) "." counter(c) "." counter(d) "." - counter(e) "." counter(f) ". "; -} - -blockquote, -p { - margin: 0 0 1.5em; -} - -.typeset ol, -.typeset ul { - margin: 0 0 1.25em; -} - -li, -p { - font-feature-settings: "dlig", "liga", "salt", "kern"; -} - -.lead { - color: #242424; - font-size: 17.5px; - font-weight: 400; -} - -article li, -article p { - color: #3d3d3d; -} - -blockquote { - quotes: none; - margin-left: -1rem; - border-left: 0.15rem solid #5b8edb; -} - -blockquote p { - font-family: Merriweather, "Times New Roman", serif; - font-style: italic; - padding: 0.5rem 0 0.5rem 1rem; -} - -code, -pre { - background-color: #f1f0ef; -} - -pre { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - margin: 0 0 2em; - padding: 1em; - white-space: pre-wrap; - word-break: break-all; - word-wrap: break-word; -} - -pre > code { - padding: 0; -} - -code { - font-size: 0.9rem; - line-height: 1.8rem; - padding: 0 0.2rem; - color: #383838; -} - -.typeset a:hover { - background-image: -webkit-gradient( - linear, - left top, - left bottom, - color-stop(50%, transparent), - color-stop(50%, #5b8edb) - ); - background-image: linear-gradient(180deg, transparent 50%, #5b8edb 0); - background-position: 0 85%; - background-repeat: repeat-x; - background-size: 100% 1px; - text-shadow: 0.1rem 0 #fff, 0.15rem 0 #fff, -0.1rem 0 #fff, -0.15rem 0 #fff; -} - -.nav-toggle { - display: -webkit-box; - display: flexbox; - display: flex; - border: 0; - padding: 0 8px; - margin: 0; - font-size: 2rem; - width: 54px; - -webkit-box-flex: 0; - flex: 0 0 54px; - cursor: pointer; - background-color: #f6f6f6; -} - -.nav-toggle:focus { - outline: thin dotted; - outline-offset: -4px; -} - -.nav-toggle-icon, -.nav-toggle-icon::after, -.nav-toggle-icon::before { - display: -webkit-box; - display: flexbox; - display: flex; - height: 6px; - width: 36px; - border-radius: 3px; - transition: all 0.3s ease 0s; - background: #000; -} - -.nav-toggle-icon { - position: relative; -} - -.nav-toggle-icon::after, -.nav-toggle-icon::before { - content: ""; - position: absolute; - left: 0; - transform-origin: 3px center; -} - -.nav-toggle-icon::before { - top: 10px; -} - -.nav-toggle-icon::after { - top: -10px; -} - -.nav-side--expand .nav-toggle-icon::after, -.nav-side--expand .nav-toggle-icon::before { - top: 0; - width: 20px; -} - -.nav-side--expand .nav-toggle-icon::before { - transform: rotate(45deg); -} - -.nav-side--expand .nav-toggle-icon::after { - transform: rotate(-45deg); -} - -.nav-top--expand .nav-toggle-icon { - transform: rotate(-90deg); - width: 30px; -} - -.nav-top--expand .nav-toggle-icon::after, -.nav-top--expand .nav-toggle-icon::before { - left: auto; - right: -5px; - width: 20px; -} - -.nav-top--expand .nav-toggle-icon::after { - transform: rotate(45deg); -} - -.nav-top--expand .nav-toggle-icon::before { - transform: rotate(-45deg); -} - -.nav-side { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - background-color: #f6f6f6; - border-right: 1px solid #e1e1e1; - z-index: 1000; - -ms-flex-preferred-size: 55px; - flex-basis: 55px; - -ms-flex-negative: 0; - flex-shrink: 0; - transition: -webkit-flex-basis 0.2s, -webkit-transform 0.2s; - transition: flex-basis 0.2s, transform 0.2s; - transition: flex-basis 0.2s, transform 0.2s, -webkit-flex-basis 0.2s, - -ms-flex-preferred-size 0.2s, -webkit-transform 0.2s; - height: 100vh; -} - -.nav-side, -.nav-side-header { - display: -webkit-box; - display: flexbox; - display: flex; -} - -.nav-side-header { - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding-bottom: 1rem; -} - -.nav-side-body { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - overflow-y: auto; - background: linear-gradient(#f6f6f6 15px, hsl(0deg 0% 96% / 0%)) 0 0/100% 50px, - radial-gradient(at top, rgb(0 0 0 / 25%), transparent 70%) 0 0/100% 15px, - linear-gradient(0deg, #f6f6f6 15px, hsl(0deg 0% 96% / 0%)) bottom/100% 50px, - radial-gradient(at bottom, rgb(0 0 0 / 25%), transparent 70%) bottom/100% - 15px; - background-repeat: no-repeat; - background-attachment: local, scroll, local, scroll; -} - -.nav-side-body i { - font-size: 2rem; - width: 1.5em; - text-align: center; - -ms-flex-negative: 0; - flex-shrink: 0; -} - -.nav-side-toggle { - width: 54px; - height: 44px; -} - -.nav-side--expand { - -ms-flex-preferred-size: 240px; - flex-basis: 240px; -} - -.nav-side--expand + .page-main { - margin-right: -240px; -} - -.page-main-overlay { - background-color: #000; - transition: left 0.2s, opacity 0.2s, position 0.2s; - opacity: 0; - left: 0; -} - -.nav-side--expand + .page-main + .page-main-overlay { - position: absolute; - inset: 0 0 0 240px; - opacity: 0.4; - z-index: 900; -} - -.nav-side + .page-main { - transition: margin-right 0.2s; -} - -.nav-side-list { - list-style: none; - line-height: 3rem; - font-size: 0; -} - -.nav-side-list:first-child .nav-side-list-header { - margin-top: 0; -} - -.nav-side-list-header, -.nav-side-list a { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: 0.1rem 0.5rem; - text-overflow: ellipsis; - white-space: nowrap; -} - -.nav-side-list-header { - color: #707070; - letter-spacing: 1px; - margin-top: 1rem; - line-height: 2rem; - text-transform: uppercase; - height: 0; - overflow: hidden; - padding: 0; - transition: height 0.2s, padding 0.2s; -} - -.nav-side-header-title { - width: 0; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - font-weight: 500; - color: #575757; - transition: width 0.2s; -} - -.nav-side--expand .nav-side-list-header, -.nav-side--expand .nav-side-list a { - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.nav-side--expand .nav-side-list-header { - height: 2em; -} - -.nav-side--expand .nav-side-header-title { - width: 100%; -} - -.nav-side--expand .nav-side-list { - font-size: 1.25rem; -} - -.nav-side--expand .nav-side-list-header, -.nav-side--expand .nav-side-list a { - padding: 0 0.5rem; -} - -.nav-side--expand .nav-side-list i { - margin-right: 0.5rem; -} - -.nav-side--expand .nav-side-body i:not([class])::before { - content: ""; - display: inline-block; -} - -.nav-side-list a { - color: #265bab; - transition: color 0.2s, background-color 0.2s; -} - -.nav-side-list a.active, -.nav-side-list a:hover { - color: #fff; - background: #5b8edb; -} - -.nav-side-list a.ember-transitioning-in { - color: #fff; - background: #8cb0e6; -} - -.nav-side-footer .nav-hide { - display: none; -} - -@media only screen and (width >=768px) { - .nav-side:not(.nav-side--autohide) { - position: relative; - display: -webkit-box; - display: flexbox; - display: flex; - -ms-flex-preferred-size: auto; - flex-basis: auto; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - background-color: #f6f6f6; - border-right: 1px solid #e1e1e1; - } - - .nav-side--expand + .page-main + .page-main-overlay, - .nav-side-toggle { - display: none; - } - - .nav-side--expand + .page-main { - margin-right: 0; - } - - .nav-side--right { - -webkit-box-ordinal-group: 2; - -ms-flex-order: 1; - order: 1; - border-right: none; - border-left: 1px solid #e1e1e1; - } - - .nav-side:not(.nav-side--autohide) .nav-side-header-title { - width: 100%; - margin-top: 1rem; - padding-right: 1rem; - } - - .nav-side-header { - height: 4rem; - -ms-flex-negative: 0; - flex-shrink: 0; - } - - .nav-side-header, - .nav-side-header > a { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - text-align: left; - } - - .nav-side-header > a { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - } - - .nav-side-header-logo { - width: 32px; - height: 32px; - -ms-flex-negative: 0; - flex-shrink: 0; - background: url("../pictures/logo/sy.png") 50% / contain; - margin: 1rem 0.5rem 0 1rem; - border-radius: 4px; - } - - .nav-side--autohide .nav-side-header-logo { - margin: 1rem auto 0; - } - - .nav-side:not(.nav-side--autohide) .nav-side-body { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - overflow-y: auto; - width: auto; - } - - .nav-side-body i { - font-size: inherit; - } - - .nav-side:not(.nav-side--autohide) .nav-side-list { - padding: 0 1rem 0 0; - font-size: 0.85rem; - line-height: 1.5 !important; - } - - .nav-side:not(.nav-side--autohide) .nav-side--right .nav-side-list { - padding: 0 0 0 1rem; - } - - .nav-side:not(.nav-side--autohide) .nav-side-list-header, - .nav-side:not(.nav-side--autohide) .nav-side-list a { - padding: 0.3rem 1rem; - } - - .nav-side:not(.nav-side--autohide) .nav-side-list a { - font-size: inherit; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - } - - .nav-side--right .nav-side-list a { - border-radius: 3px 0 0 3px; - } - - .nav-side-list-header { - height: 2em; - } - - .nav-side-list i { - margin-right: 0.5rem; - text-align: center; - width: 1.5em; - } - - .nav-side--autohide .nav-side-list i { - font-size: 1.25rem; - margin: 0; - } - - .nav-side-body i:not([class])::before { - content: ""; - } - - .nav-side-footer { - -ms-flex-negative: 0; - flex-shrink: 0; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - flex-direction: row; - height: 3rem; - } - - .nav-side-footer, - .nav-side-footer .nav-hide { - display: -webkit-box; - display: flexbox; - display: flex; - } -} - -.nav-side--sub { - display: none; - -ms-flex-negative: 1; - flex-shrink: 1; - border-right: 1px solid #eaeaea; - z-index: 999; -} - -.nav-side--sub .nav-side-list { - margin-top: 1rem; - font-size: inherit; -} - -.nav-side--sub .nav-side-list:first-child { - margin-top: 0; -} - -@media only screen and (width >=768px) { - .nav-side--sub { - display: -webkit-box; - display: flexbox; - display: flex; - background-color: #fbfbfb; - } - - .nav-side--sub .nav-side-header { - padding-left: 1rem; - } - - .nav-side--sub .nav-side-body { - background: linear-gradient(#fbfbfb 15px, hsl(0deg 0% 98% / 0%)) 0 0/100% - 50px, - radial-gradient(at top, rgb(0 0 0 / 25%), transparent 70%) 0 0/100% 15px, - linear-gradient(0deg, #fbfbfb 15px, hsl(0deg 0% 98% / 0%)) bottom/100% - 50px, - radial-gradient(at bottom, rgb(0 0 0 / 25%), transparent 70%) bottom/100% - 15px; - background-repeat: no-repeat; - background-attachment: local, scroll, local, scroll; - } - - .nav-side--sub .nav-side-list { - padding: 0 1rem 0 0; - font-size: 0.85rem; - line-height: 1.5 !important; - } -} - -.nav-top { - position: relative; - width: 100%; - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - background-color: #f6f6f6; - border-bottom: 1px solid #e1e1e1; - z-index: 1000; -} - -.nav-top--fixed { - position: fixed; - width: 100%; - top: 0; - left: 0; -} - -.nav-top--fixed + * { - margin-top: 51px; -} - -.nav-top + .page-content--scroll { - height: calc(100vh - 51px); -} - -.nav-top-header, -.nav-top-header a { - display: -webkit-box; - display: flexbox; - display: flex; -} - -.nav-top-header { - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; -} - -.nav-top-header-logo { - width: 40px; - height: 40px; - background: url("../pictures/logo/sy.png"); - background-size: 40px 40px; - border-radius: 4px; - margin-right: 0.5rem; -} - -.nav-top-header-logo, -.nav-top-header-title { - -ms-flex-item-align: center; - align-self: center; -} - -.nav-top-header-title { - color: #575757; - margin-right: 0.5rem; -} - -.nav-top--expand .nav-top-body { - display: block; - max-height: 400px; - overflow-y: auto; - transition: max-height 0.7s; -} - -.nav-top-body { - max-height: 0; - overflow: hidden; -} - -.nav-top-list { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - font-size: 1.25rem; - line-height: 2rem; - list-style: none; -} - -.nav-top-list, -.nav-top-list a { - display: -webkit-box; - display: flexbox; - display: flex; -} - -.nav-top-list a { - -webkit-box-align: baseline; - -ms-flex-align: baseline; - align-items: baseline; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - padding: 0.75rem 0.75rem 0.75rem 0.5rem; -} - -.nav-top-list .fa { - -webkit-box-flex: 0; - flex: 0 0 2em; - text-align: center; -} - -.nav-top-list a:hover { - color: #fff; - background: #5b8edb; -} - -.nav-top-list-item { - display: -webkit-box; - display: flexbox; - display: flex; -} - -.nav-top-list a { - color: #265bab; - transition: color 0.2s, background-color 0.2s; -} - -.nav-top-list--right { - border-top: 1px solid #e1e1e1; -} - -@media only screen and (width >=768px) { - .nav-top { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - flex-direction: row; - padding: 0 1.5em; - } - - .nav-top-toggle { - display: none; - } - - .nav-top-header { - -webkit-box-pack: left; - -ms-flex-pack: left; - justify-content: left; - } - - .nav-top-body { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - max-height: 50px; - transition: none; - } - - .nav-top-list { - height: 50px; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - flex-direction: row; - font-size: 0.85rem; - } - - .nav-top-list--right { - border-top: 0; - margin-left: auto; - } - - .nav-top-list a { - display: block; - -ms-flex-item-align: center; - align-self: center; - padding: 1rem 0.5rem; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; - } -} - -.table { - display: table; - width: 100%; - max-width: 100%; - margin-bottom: 1rem; - border-collapse: collapse; -} - -.table--bordered, -.table--bordered > tbody > tr > td, -.table--bordered > tbody > tr > th, -.table--bordered > tfoot > tr > td, -.table--bordered > tfoot > tr > th, -.table--bordered > thead > tr > td, -.table--bordered > thead > tr > th { - border: 1px solid #e1e1e1; -} - -.table--striped > tbody > tr:nth-of-type(odd) { - background-color: #f3f3f3; -} - -.table--hover > tbody > tr:hover { - background-color: #ececec; -} - -.table caption { - color: #7d7d7d; - text-align: left; -} - -.table > tbody > tr > td, -.table > tbody > tr > th, -.table > tfoot > tr > td, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > thead > tr > th { - padding: 0.5rem; - vertical-align: top; - border-top: 1px solid #e1e1e1; -} - -.table--condensed > tbody > tr > td, -.table--condensed > tbody > tr > th, -.table--condensed > tfoot > tr > td, -.table--condensed > tfoot > tr > th, -.table--condensed > thead > tr > td, -.table--condensed > thead > tr > th { - padding: 0.25rem; -} - -.table > thead > tr > th { - font-weight: 500; - text-align: left; - vertical-align: bottom; - border-bottom: 2px solid #e1e1e1; -} - -.table > caption + thead > tr:first-child > td, -.table > caption + thead > tr:first-child > th, -.table > colgroup + thead > tr:first-child > td, -.table > colgroup + thead > tr:first-child > th, -.table > thead:first-child > tr:first-child > td, -.table > thead:first-child > tr:first-child > th { - border-top: 0; -} - -.table > tbody > tr.primary { - background-color: #c0d2ec; -} - -.table--striped > tbody > tr.primary:nth-of-type(odd) { - background-color: #c8d7ef; -} - -.table--hover > tbody > tr.primary:hover { - background-color: #b0c8ee; -} - -.table tr.success { - background-color: #b3d5b3; -} - -.table--striped > tbody > tr.success:nth-of-type(odd) { - background-color: #bad9ba; -} - -.table--hover > tbody > tr.success:hover { - background-color: #a3d7a3; -} - -.table tr.info { - background-color: #bfe2ed; -} - -.table--striped > tbody > tr.info:nth-of-type(odd) { - background-color: #c7e6ef; -} - -.table--hover > tbody > tr.info:hover { - background-color: #afe0ef; -} - -.table tr.warning { - background-color: #f5ddbc; -} - -.table--striped > tbody > tr.warning:nth-of-type(odd) { - background-color: #f6e2c5; -} - -.table--hover > tbody > tr.warning:hover { - background-color: #f8d8ab; -} - -.table tr.danger { - background-color: #e9b6b4; -} - -.table--striped > tbody > tr.danger:nth-of-type(odd) { - background-color: #ebbebc; -} - -.table--hover > tbody > tr.danger:hover { - background-color: #eba5a3; -} - -.btn { - display: -webkit-box; - display: flexbox; - display: flex; - -ms-flex-negative: 0; - flex-shrink: 0; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - flex-direction: row; - margin-bottom: 0; - padding: calc(0.75rem + 1px) 1.25rem 0.75rem; - border: 1px solid #e1e1e1; - border-bottom-width: 2px; - background: #fff; - border-radius: 4px; - text-align: center; - text-decoration: none; - text-transform: uppercase; - text-shadow: none; - white-space: nowrap; - height: 100%; - min-height: 3rem; - letter-spacing: 1px; - font-size: 1rem; - line-height: 1.2; - font-weight: 400; - cursor: pointer; - user-select: none; - box-shadow: 0 1px 0 hsl(0deg 0% 100% / 15%) inset; - box-shadow: inset 0 1px 0 hsl(0deg 0% 100% / 15%); - transition: color 0.2s ease 0s, background 0.2s ease 0s, - border-color 0.2s ease 0s; -} - -@media only screen and (width >=768px) { - .btn { - font-size: 0.75rem; - padding: calc(0.5rem + 1px) 1rem 0.5rem; - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - align-items: flex-start; - min-height: 2rem; - } -} - -.btn, -.btn:visited { - color: #707070; -} - -.btn-danger, -.btn-danger:visited, -.btn-info, -.btn-info:visited, -.btn-primary, -.btn-primary:visited, -.btn-success, -.btn-success:visited, -.btn-warning, -.btn-warning:visited { - color: #fff; -} - -.btn:not([disabled]):hover { - color: #5b8edb; - border-color: #b0c8ee; - text-decoration: none; -} - -.btn:focus { - outline: none; - box-shadow: 0 0 6px 2px hsl(0deg 0% 88% / 60%); -} - -.btn.active:not(.no-active-class), -.btn:active { - box-shadow: 0 1px 10px rgb(0 0 0 / 20%) inset, - 0 -1px 0 hsl(0deg 0% 100% / 20%) inset; - box-shadow: inset 0 1px 10px rgb(0 0 0 / 20%), - inset 0 -1px 0 hsl(0deg 0% 100% / 20%); - padding: 0.75rem 1.25rem calc(0.75rem + 1px); - border-top-width: 2px; - border-bottom-width: 1px; -} - -@media only screen and (width >=768px) { - .btn.active:not(.no-active-class), - .btn:active { - padding: 0.5rem 1rem calc(0.5rem + 1px); - } -} - -.btn.active:not(.no-active-class):focus, -.btn:active:focus { - box-shadow: none; -} - -.btn-primary { - background-color: #5b8edb; - border-color: #4780d7; -} - -.btn-primary:not([disabled]):hover { - background-color: #2c71d8; - border-color: #265bab; - color: #fff; -} - -.btn-primary:focus { - box-shadow: 0 0 2px 2px rgb(91 142 219 / 50%); -} - -.btn-success { - background-color: #5cb85c; - border-color: #4cae4c; -} - -.btn-success:not([disabled]):hover { - background-color: #3fa23f; - border-color: #357935; - color: #fff; -} - -.btn-success:focus { - box-shadow: 0 0 2px 2px rgb(92 184 92 / 50%); -} - -.btn-info { - background-color: #5bc0de; - border-color: #45b6d9; -} - -.btn-info:not([disabled]):hover { - background-color: #29b1db; - border-color: #248dae; - color: #fff; -} - -.btn-info:focus { - box-shadow: 0 0 2px 2px rgb(91 192 222 / 50%); -} - -.btn-warning { - background-color: #f0ad4e; - border-color: #eda135; -} - -.btn-warning:not([disabled]):hover { - background-color: #f29718; - border-color: #c57a11; - color: #fff; -} - -.btn-warning:focus { - box-shadow: 0 0 2px 2px rgb(240 173 78 / 50%); -} - -.btn-danger { - background-color: #d9534f; - border-color: #d4403a; -} - -.btn-danger:not([disabled]):hover { - background-color: #cf2c26; - border-color: #9f2723; - color: #fff; -} - -.btn-danger:focus { - box-shadow: 0 0 2px 2px rgb(217 83 79 / 50%); -} - -.btn-link { - color: #5b8edb; - padding: 0; - margin: 0; - border: none; - display: inline; - line-height: inherit; - text-transform: none; - min-height: auto; - letter-spacing: normal; -} - -.btn-link, -.btn-link.active:not(.no-active-class), -.btn-link:active, -.btn-link:focus, -.btn-link:hover { - border-color: transparent; - background: none; - box-shadow: none; -} - -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - cursor: not-allowed; - opacity: 0.4; -} - -.btn-group { - display: -webkit-box; - display: flexbox; - display: flex; - flex-wrap: nowrap; -} - -.btn-group > .btn { - z-index: 1; -} - -.btn-group > .btn.active:not(.no-active-class) + .btn, -.btn-group > .btn:active + .btn, -.btn-group > .btn:focus + .btn, -.btn-group > .btn:hover + .btn { - z-index: 0; -} - -.btn-group > .btn:first-child:not(:last-child, .dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.btn-group > .btn:first-child { - margin-left: 0; -} - -.btn-group > .btn:not(:first-child, :last-child, .dropdown-toggle) { - border-radius: 0; -} - -.btn-group > .btn + .btn, -.btn-group > .btn + .btn-group, -.btn-group > .btn-group + .btn, -.btn-group > .btn-group + .btn-group { - margin-left: -1px; -} - -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.btn-group--vertical { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; -} - -.btn-group--vertical > .btn:first-child:not(:last-child, .dropdown-toggle) { - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.btn-group--vertical > .btn:not(:first-child) { - box-shadow: none; -} - -.btn-group--vertical > .btn.active:not(.no-active-class), -.btn-group--vertical > .btn:active, -.btn-group--vertical > .btn:last-child.active:not(.no-active-class), -.btn-group--vertical > .btn:last-child:active { - box-shadow: 0 1px 10px rgb(0 0 0 / 20%) inset, - 0 -1px 0 hsl(0deg 0% 100% / 20%) inset; - box-shadow: inset 0 1px 10px rgb(0 0 0 / 20%), - inset 0 -1px 0 hsl(0deg 0% 100% / 20%); -} - -.btn-group--vertical > .btn:not(:last-child) { - border-bottom-color: transparent; -} - -.btn-group--vertical > .btn + .btn, -.btn-group--vertical > .btn + .btn-group, -.btn-group--vertical > .btn-group + .btn, -.btn-group--vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} - -.btn-group--vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-left-radius: 4px; -} - -.btn-group--vertical - > .btn-group:last-child:not(:first-child) - > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.btn-toolbar { - display: -webkit-box; - display: flexbox; - display: flex; - margin-left: -5px; -} - -.btn-toolbar > .btn, -.btn-toolbar > .btn-group, -.btn-toolbar > .input-group { - margin-left: 5px; -} - -.form-group { - margin-bottom: 1rem; -} - -.form-group label { - display: inline-block; - max-width: 100%; - margin-bottom: 0.25rem; - font-weight: 500; -} - -.form-control::input-placeholder { - color: #999; - opacity: 1; -} - -.form-control:input-placeholder { - color: #999; - opacity: 1; -} - -.form-control::placeholder { - color: #999; - opacity: 1; -} - -.form-control { - display: block; - width: 100%; - min-height: 3rem; - padding: 0.3rem 0.5rem; - font-size: 1.2rem; - line-height: 1.5; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset; - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%); - transition: border-color 0.15s, -webkit-box-shadow 0.15s; - transition: border-color 0.15s, box-shadow 0.15s; - transition: border-color 0.15s, box-shadow 0.15s, -webkit-box-shadow 0.15s; -} - -@media only screen and (width >=768px) { - .form-control { - font-size: 0.9rem; - min-height: 2rem; - } -} - -select.form-control[multiple] { - height: auto; - padding: 0.1rem 0.2rem; -} - -select.form-control[multiple] > option { - margin: 2px 0; - padding: 2px 0.3rem; -} - -select.form-control[multiple] > :checked, -select.form-control[multiple] > [selected] { - border-radius: 4px; -} - -select.form-control { - appearance: none; -} - -select.form-control::-ms-expand { - display: none; -} - -select.form-control:not([multiple]) { - background-image: url('data:image/svg+xml;charset=utf-8,'); - background-position: right 0.5rem center; - background-size: 22px; - background-repeat: no-repeat; - padding-right: 2rem; -} - -.form-control:focus { - border-color: #7ca5e2; - outline: 0; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, 0 0 8px rgb(91 142 219 / 60%); - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%), 0 0 8px rgb(91 142 219 / 60%); -} - -.form-control.success { - border-color: #7dc67d; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, 0 0 8px rgb(92 184 92 / 60%); - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%), 0 0 8px rgb(92 184 92 / 60%); -} - -.form-control.info { - border-color: #7ccde5; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, 0 0 8px rgb(91 192 222 / 60%); - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%), 0 0 8px rgb(91 192 222 / 60%); -} - -.form-control.warning { - border-color: #f3bd71; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, 0 0 8px rgb(240 173 78 / 60%); - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%), 0 0 8px rgb(240 173 78 / 60%); -} - -.form-control.invalid, -.form-control:invalid { - border-color: #e17572; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, 0 0 8px rgb(217 83 79 / 60%); - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%), 0 0 8px rgb(217 83 79 / 60%); -} - -.form-control[disabled], -fieldset[disabled] .form-control { - cursor: not-allowed; -} - -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - background-color: #eee; -} - -@media only screen and (width >=768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - - .form-inline .checkbox, - .form-inline .radio { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - - .form-inline .btn { - display: inline-block; - } -} - -.checkbox, -.radio { - position: relative; - display: block; - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} - -.checkbox > input[type="checkbox"]:checked, -.checkbox > input[type="checkbox"]:not(:checked), -.checkbox > input[type="radio"]:checked, -.checkbox > input[type="radio"]:not(:checked), -.radio > input[type="checkbox"]:checked, -.radio > input[type="checkbox"]:not(:checked), -.radio > input[type="radio"]:checked, -.radio > input[type="radio"]:not(:checked) { - position: absolute; - left: -99999px; -} - -.checkbox > input[type="checkbox"]:checked + label, -.checkbox > input[type="checkbox"]:not(:checked) + label, -.checkbox > input[type="radio"]:checked + label, -.checkbox > input[type="radio"]:not(:checked) + label, -.radio > input[type="checkbox"]:checked + label, -.radio > input[type="checkbox"]:not(:checked) + label, -.radio > input[type="radio"]:checked + label, -.radio > input[type="radio"]:not(:checked) + label { - position: relative; - display: -webkit-box; - display: flexbox; - display: flex; - padding-left: 2.5rem; - line-height: 2rem; - cursor: pointer; -} - -.checkbox > input[type="checkbox"]:checked + label::before, -.checkbox > input[type="checkbox"]:not(:checked) + label::before, -.checkbox > input[type="radio"]:checked + label::before, -.checkbox > input[type="radio"]:not(:checked) + label::before, -.radio > input[type="checkbox"]:checked + label::before, -.radio > input[type="checkbox"]:not(:checked) + label::before, -.radio > input[type="radio"]:checked + label::before, -.radio > input[type="radio"]:not(:checked) + label::before { - content: ""; - position: absolute; - left: 0; - width: 2rem; - height: 2rem; - border: 1px solid #ccc; - background-color: #fff; - background-image: none; - border-radius: 4px; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset; - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%); - transition: border-color 0.15s, -webkit-box-shadow 0.15s; - transition: border-color 0.15s, box-shadow 0.15s; - transition: border-color 0.15s, box-shadow 0.15s, -webkit-box-shadow 0.15s; -} - -.checkbox > input[type="radio"]:checked + label::before, -.checkbox > input[type="radio"]:not(:checked) + label::before, -.radio > input[type="radio"]:checked + label::before, -.radio > input[type="radio"]:not(:checked) + label::before { - border-radius: 50%; -} - -.checkbox > input[type="checkbox"]:checked + label::after, -.checkbox > input[type="checkbox"]:not(:checked) + label::after, -.checkbox > input[type="radio"]:checked + label::after, -.checkbox > input[type="radio"]:not(:checked) + label::after, -.radio > input[type="checkbox"]:checked + label::after, -.radio > input[type="checkbox"]:not(:checked) + label::after, -.radio > input[type="radio"]:checked + label::after, -.radio > input[type="radio"]:not(:checked) + label::after { - content: "\2713"; - position: absolute; - left: 0.4rem; - top: 0.1rem; - line-height: 1; - font-size: 2rem; - font-weight: 500; - color: #5cb85c; - transition: all 0.2s; -} - -.checkbox > input[type="radio"]:checked + label::after, -.checkbox > input[type="radio"]:not(:checked) + label::after, -.radio > input[type="radio"]:checked + label::after, -.radio > input[type="radio"]:not(:checked) + label::after { - content: "\2022"; - left: 0.465rem; - top: -0.035rem; -} - -.checkbox > input[type="checkbox"]:not(:checked) + label::after, -.checkbox > input[type="radio"]:not(:checked) + label::after, -.radio > input[type="checkbox"]:not(:checked) + label::after, -.radio > input[type="radio"]:not(:checked) + label::after { - opacity: 0; - transform: scale(0); -} - -.checkbox > input[type="checkbox"]:checked + label::after, -.checkbox > input[type="radio"]:checked + label::after, -.radio > input[type="checkbox"]:checked + label::after, -.radio > input[type="radio"]:checked + label::after { - opacity: 1; - transform: scale(1); -} - -.checkbox > input[type="checkbox"]:checked:disabled + label::before, -.checkbox > input[type="checkbox"]:not(:checked):disabled + label::before, -.checkbox > input[type="radio"]:checked:disabled + label::before, -.checkbox > input[type="radio"]:not(:checked):disabled + label::before, -.radio > input[type="checkbox"]:checked:disabled + label::before, -.radio > input[type="checkbox"]:not(:checked):disabled + label::before, -.radio > input[type="radio"]:checked:disabled + label::before, -.radio > input[type="radio"]:not(:checked):disabled + label::before { - box-shadow: none; - border-color: #bbb; - background-color: #ddd; -} - -.checkbox > input[type="checkbox"]:disabled:checked + label::after, -.checkbox > input[type="radio"]:disabled:checked + label::after, -.radio > input[type="checkbox"]:disabled:checked + label::after, -.radio > input[type="radio"]:disabled:checked + label::after { - color: #999; -} - -.checkbox > input[type="checkbox"]:disabled + label, -.checkbox > input[type="radio"]:disabled + label, -.radio > input[type="checkbox"]:disabled + label, -.radio > input[type="radio"]:disabled + label { - cursor: not-allowed; - color: #aaa; -} - -.checkbox > input[type="checkbox"]:checked:focus + label::before, -.checkbox > input[type="checkbox"]:not(:checked):focus + label::before, -.checkbox > input[type="radio"]:checked:focus + label::before, -.checkbox > input[type="radio"]:not(:checked):focus + label::before, -.radio > input[type="checkbox"]:checked:focus + label::before, -.radio > input[type="checkbox"]:not(:checked):focus + label::before, -.radio > input[type="radio"]:checked:focus + label::before, -.radio > input[type="radio"]:not(:checked):focus + label::before { - border-color: #7ca5e2; - outline: 0; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, 0 0 8px rgb(91 142 219 / 60%); - box-shadow: inset 0 1px 1px rgb(0 0 0 / 7.5%), 0 0 8px rgb(91 142 219 / 60%); -} - -.checkbox > input[type="checkbox"]:checked + label:hover::before, -.checkbox > input[type="checkbox"]:not(:checked) + label:hover::before, -.checkbox > input[type="radio"]:checked + label:hover::before, -.checkbox > input[type="radio"]:not(:checked) + label:hover::before, -.radio > input[type="checkbox"]:checked + label:hover::before, -.radio > input[type="checkbox"]:not(:checked) + label:hover::before, -.radio > input[type="radio"]:checked + label:hover::before, -.radio > input[type="radio"]:not(:checked) + label:hover::before { - border-color: #adc7ed; -} - -@media only screen and (width >=768px) { - .checkbox > input[type="checkbox"]:checked + label::before, - .checkbox > input[type="checkbox"]:not(:checked) + label::before, - .checkbox > input[type="radio"]:checked + label::before, - .checkbox > input[type="radio"]:not(:checked) + label::before, - .radio > input[type="checkbox"]:checked + label::before, - .radio > input[type="checkbox"]:not(:checked) + label::before, - .radio > input[type="radio"]:checked + label::before, - .radio > input[type="radio"]:not(:checked) + label::before { - width: 1rem; - height: 1rem; - } - - .checkbox > input[type="checkbox"]:checked + label::after, - .checkbox > input[type="checkbox"]:not(:checked) + label::after, - .checkbox > input[type="radio"]:checked + label::after, - .checkbox > input[type="radio"]:not(:checked) + label::after, - .radio > input[type="checkbox"]:checked + label::after, - .radio > input[type="checkbox"]:not(:checked) + label::after, - .radio > input[type="radio"]:checked + label::after, - .radio > input[type="radio"]:not(:checked) + label::after { - font-size: 1rem; - left: 0.2rem; - top: -0.025rem; - } - - .checkbox > input[type="checkbox"]:checked + label, - .checkbox > input[type="checkbox"]:not(:checked) + label, - .checkbox > input[type="radio"]:checked + label, - .checkbox > input[type="radio"]:not(:checked) + label, - .radio > input[type="checkbox"]:checked + label, - .radio > input[type="checkbox"]:not(:checked) + label, - .radio > input[type="radio"]:checked + label, - .radio > input[type="radio"]:not(:checked) + label { - padding-left: 1.5rem; - line-height: 1; - } - - .checkbox > input[type="radio"]:checked + label::after, - .checkbox > input[type="radio"]:not(:checked) + label::after, - .radio > input[type="radio"]:checked + label::after, - .radio > input[type="radio"]:not(:checked) + label::after { - left: 0.25rem; - } -} - -.page-login .page-content { - background: -webkit-gradient( - linear, - left top, - left bottom, - from(#867f7c), - to(#a29b96) - ); - background: linear-gradient(180deg, #867f7c, #a29b96); - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; -} - -.page-login .btn { - width: 100%; - overflow: hidden; - text-overflow: ellipsis; -} - -.page-login .form-group { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.page-login .form-control { - border: none; - box-shadow: none; - width: 265px; - background: #e1e1e1; - padding-left: 2.5rem; -} - -.page-login .form-control:focus { - background: #f0f0f0; -} - -.page-login .btn-link, -.page-login .btn-link:active { - color: #fff; -} - -.page-login .btn-link:focus, -.page-login .btn-link:hover { - color: #edeeee; - text-decoration: underline; -} - -@media only screen and (width >=768px) { - .page-login .btn { - width: auto; - } - - .page-login .form-group { - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - } -} - -.login-form { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - margin: 0 auto; -} - -.login-form, -.login-form > form { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; -} - -.login-form > form { - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - width: 100%; -} - -.login-form .btn-primary { - margin-bottom: 1rem; -} - -.login-form-email, -.login-form-password, -.login-form-user { - position: relative; -} - -.login-form-email::before, -.login-form-password::before, -.login-form-user::before { - font-family: FontAwesome; - position: absolute; - top: 8px; - left: 1rem; - width: 16px; - text-align: center; -} - -.login-form-user::before { - content: "\f007"; -} - -.login-form-email::before { - content: "\f0e0"; -} - -.login-form-password::before { - content: "\f023"; -} - -@media only screen and (width >=768px) { - .login-form { - width: 670px; - } - - .login-form > form { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - flex-direction: row; - } - - .login-form--password-reset { - width: auto; - } - - .login-form--password-reset > form { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - } - - .login-form .btn-primary { - margin-bottom: 0; - } - - .login-form-password-reset-btn { - margin-top: 0.5rem; - -ms-flex-item-align: start; - align-self: flex-start; - } - - .login-form--password-reset .btn { - width: 100%; - } -} - -.alert { - padding: 1rem; - margin-bottom: 1.25rem; - border: 1px solid transparent; - border-radius: 4px; -} - -.alert-dismissable, -.alert-dismissible { - padding-right: 35px; -} - -.alert-dismissable .close, -.alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} - -.alert-success { - color: #458a45; - border-color: #aedcae; - background-color: #d6edd6; -} - -.alert-info { - color: #4490a7; - border-color: #ade0ef; - background-color: #d6eff7; -} - -.alert-warning { - color: #b4823b; - border-color: #f8d6a7; - background-color: #fbebd3; -} - -.alert-danger { - color: #a33e3b; - border-color: #eca9a7; - background-color: #f6d4d3; -} - -.pagination { - display: -webkit-box; - display: flexbox; - display: flex; -} - -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} - -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} - -.pagination > li > a:focus, -.pagination > li > a:hover, -.pagination > li > span:focus, -.pagination > li > span:hover { - background-color: #f0f0f0; -} - -.pagination > li { - display: none; - font-feature-settings: "lnum"; - z-index: 1; -} - -.pagination > li.active + li, -.pagination > li:focus + li, -.pagination > li:hover + li { - z-index: 0; -} - -.pagination > .active, -.pagination > .next, -.pagination > .previous { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.pagination > li > a, -.pagination > li > span { - padding: 0.3rem 0.9rem; - margin-left: -1px; - color: #5b8edb; - background-color: #fff; - border: 1px solid #e1e1e1; - text-align: center; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.pagination > .active > a, -.pagination > .active > a:focus, -.pagination > .active > a:hover, -.pagination > .active > span, -.pagination > .active > span:focus, -.pagination > .active > span:hover { - color: #fff; - cursor: default; - background-color: #5b8edb; - border-color: #5b8edb; -} - -.pagination > .disabled > a, -.pagination > .disabled > a:focus, -.pagination > .disabled > a:hover, -.pagination > .disabled > span, -.pagination > .disabled > span:focus, -.pagination > .disabled > span:hover { - color: #7c7c7c; - cursor: not-allowed; - background-color: #fff; - border: 1px solid #e1e1e1; -} - -@media only screen and (width >=768px) { - .pagination > li { - display: -webkit-box; - display: flexbox; - display: flex; - } - - .pagination > .active, - .pagination > .next, - .pagination > .previous { - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - } -} - -.nav-tabs { - list-style: none; - padding-left: 0; - margin-bottom: 0; - border-bottom: 1px solid #e1e1e1; -} - -.nav-tabs, -.nav-tabs > li { - display: -webkit-box; - display: flexbox; - display: flex; -} - -.nav-tabs > li { - margin-bottom: -1px; -} - -.nav-tabs > li > a { - padding: 0.5rem 1rem; - margin-right: 2px; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a.ember-transitioning-in { - color: #fff; - background: #8cb0e6; -} - -.nav-tabs > li > a:focus { - outline: 0; - border-style: dotted; -} - -.nav-tabs > li > a.active { - border-color: #e1e1e1; - border-style: solid; - background-color: #fff; - color: #777; -} - -.nav-tabs > li > a:focus { - border-color: #8cb0e6; -} - -.nav-tabs > li > a.active, -.nav-tabs > li > a:focus { - border-bottom-color: transparent; -} - -.tab-content { - padding-top: 0.75rem; -} - -.tab-content > .tab-pane { - display: none; -} - -.tab-content > .active { - display: block; -} - -.breadcrumb { - display: -webkit-box; - display: flexbox; - display: flex; - flex-wrap: wrap; - padding-bottom: 0.5rem; - margin-bottom: 1rem; - border-bottom: 1px solid #e1e1e1; -} - -.breadcrumb:empty { - display: none; -} - -.breadcrumb > li { - display: block; - white-space: nowrap; -} - -.breadcrumb > li::before { - content: "/"; - margin: 0 0.5rem; - color: #9e9e9e; -} - -.breadcrumb > li:first-child::before { - display: none; -} - -.breadcrumb > li:first-child { - display: block; -} - -@media only screen and (width >=480px) { - .breadcrumb--first-mobileonly > li:first-child, - .breadcrumb--first-mobileonly > li:first-child + li::before { - display: none; - } -} - -.list-group { - padding-left: 0; - margin-top: 0; - margin-bottom: 0; -} - -.list-group-item { - position: relative; - display: block; - padding: 0.5rem 1rem; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #e1e1e1; -} - -.list-group-item.active { - z-index: 2; - color: #fff; - background-color: #5b8edb; - border-color: #5b8edb; -} - -.list-group-item.disabled, -.list-group-item[disabled] { - cursor: not-allowed; - background-color: #867f7c; - border-color: #7a7371; - color: #d1cdcb; - border-width: 1px; - box-shadow: none; -} - -.list-group-item.disabled:focus, -.list-group-item[disabled]:focus { - outline: none; -} - -.list-group-item:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} - -.list-group--flush .list-group-item { - border-width: 1px 0; - border-radius: 0; -} - -.card { - position: relative; - margin-bottom: 0.5rem; - background-color: #fff; - border: 1px solid #e1e1e1; - border-radius: 3px; -} - -.card--inverse { - border-color: #867f7c; - background-color: #867f7c; -} - -.card--inverse .card-blockquote, -.card--inverse .card-footer, -.card--inverse .card-header, -.card--inverse .card-title { - color: #fff; -} - -.card--inverse .card-blockquote > footer, -.card--inverse .card-link, -.card--inverse .card-text { - color: hsl(0deg 0% 100% / 70%); -} - -.card--primary { - background-color: #5b8edb; - border-color: #5b8edb; -} - -.card--success { - background-color: #5cb85c; - border-color: #5cb85c; -} - -.card--info { - background-color: #5bc0de; - border-color: #5bc0de; -} - -.card--warning { - background-color: #f0ad4e; - border-color: #f0ad4e; -} - -.card--danger { - background-color: #d9534f; - border-color: #d9534f; -} - -.card-block { - padding: 1rem; -} - -.card-title { - margin: 0 0 0.5rem; -} - -.card-subtitle { - margin-top: -0.25rem; -} - -.card-subtitle, -.card-text:last-child { - margin-bottom: 0; -} - -.card-link + .card-link { - margin-left: 1rem; -} - -.card-img, -.card-img-bottom, -.card-img-top { - width: 100%; -} - -.card-img { - border-radius: 3px; -} - -.card-img-overlay { - position: absolute; - inset: 0; - padding: 1rem; -} - -.card-img-top { - border-radius: 3px 3px 0 0; -} - -.card-img-bottom { - border-radius: 0 0 3px 3px; -} - -.card-footer, -.card-header { - padding: 0.5rem 1rem; - background-color: #f5f5f5; -} - -.card-header:first-child { - border-radius: 3px 3px 0 0; -} - -.card-header { - border-bottom: 1px solid #e1e1e1; -} - -.card-footer:last-child { - border-radius: 0 0 3px 3px; -} - -.card-footer { - border-top: 1px solid #e1e1e1; -} - -.modal { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - padding: 1.5rem; - opacity: 0; - position: fixed; - content: ""; - inset: 0; - z-index: 1001; - background-color: rgb(0 0 0 / 25%); - pointer-events: none; - transition: opacity 0.5s ease; -} - -.modal--visible { - pointer-events: all; - opacity: 1; -} - -.modal-dialog { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - max-height: 100%; - z-index: 1002; - width: 100%; - margin-top: 100%; - border: thin solid #e1e1e1; - border-radius: 6px; - box-shadow: 0 0 0.5rem 0.3rem rgb(0 0 0 / 25%); - transition: margin-top 0.75s ease; -} - -.modal--visible .modal-dialog { - margin-top: 0; -} - -.modal-body, -.modal-footer, -.modal-header { - background-color: #fff; -} - -.modal-footer, -.modal-header { - padding: 0.7rem; -} - -.modal-header { - border-bottom: thin solid #dedede; - font-size: 1.3rem; - font-weight: 500; -} - -.modal-header h1, -.modal-header h2, -.modal-header h3, -.modal-header h4, -.modal-header h5 { - display: inline-block; - margin: 0; -} - -.modal-body { - padding: 1.4rem 0.7rem; - overflow-y: auto; - -ms-flex-negative: 1; - flex-shrink: 1; -} - -.modal-footer { - display: -webkit-box; - display: flexbox; - display: flex; - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - border-top: thin solid #dedede; -} - -@media only screen and (width >=992px) { - .modal-dialog:not( - .modal-dialog--fullscreen, - .modal-dialog--auto, - .modal-dialog--small, - .modal-dialog--large - ) { - width: 600px; - } - - .modal-dialog--small { - width: 400px; - } - - .modal-dialog--large { - width: 1000px; - } - - .modal-dialog--auto { - width: auto; - } -} diff --git a/frontend/app/styles/analysis.scss b/frontend/app/styles/analysis.scss deleted file mode 100644 index 7ab92a27a..000000000 --- a/frontend/app/styles/analysis.scss +++ /dev/null @@ -1,65 +0,0 @@ -@use "sass:color"; - -.table--analysis { - margin-bottom: 0; - table-layout: fixed; -} - -.table--analysis > tbody > tr.pointer { - color: rgb(0 0 0); -} - -.table--analysis > tbody > tr.pointer > td:last-child { - box-shadow: inset -2px 0 0 $color-primary; -} - -.table--analysis > tbody > tr:first-of-type td { - border-top: none; -} - -.table--analysis > colgroup > col { - &:nth-child(1), - &:nth-child(2), - &:nth-child(3) { - width: 7%; - } - - &:nth-child(4), - &:nth-child(5), - &:nth-child(6) { - width: 10%; - } - - &:nth-child(8) { - width: 8%; - } - - &:nth-child(9), - &:nth-child(10), - &:nth-child(11), - &:nth-child(12) { - width: 5%; - } - - &:nth-child(7) { - width: 21%; - } -} - -.export-buttons { - text-align: right; - margin-top: 1rem; -} - -.table--analysis tr.selected { - background-color: lighten($color-primary, 20%) !important; -} - -.table--analysis tr.selected + tr td, -.table--analysis tr.selected td { - border-color: lighten($color-primary, 20%) !important; -} - -.highlight { - color: color.adjust($color-primary, $lightness: -10%); -} diff --git a/frontend/app/styles/app.css b/frontend/app/styles/app.css new file mode 100644 index 000000000..378e28e8f --- /dev/null +++ b/frontend/app/styles/app.css @@ -0,0 +1,8 @@ +@import "tailwindcss/base"; +@import "./base.css" layer(base); + +@import "tailwindcss/components"; +@import "./components.css" layer(components); + +@import "tailwindcss/utilities"; +@import "./utilities.css" layer(utilities); diff --git a/frontend/app/styles/app.scss b/frontend/app/styles/app.scss deleted file mode 100644 index bd7bc673e..000000000 --- a/frontend/app/styles/app.scss +++ /dev/null @@ -1,457 +0,0 @@ -/* AdCSSy variables */ -@import "adcssy"; /* TODO: Pick only relevant styles and delete duplicate color variables */ -@import "variables"; - -/* Plugin customizations */ -@import "ember-power-calendar"; -@import "ember-basic-dropdown"; -@import "ember-power-select-custom"; - -/* Custom styles */ -@import "activities"; -@import "analysis"; -@import "attendances"; -@import "badge"; -@import "filter-sidebar"; -@import "form-list"; -@import "loader"; -@import "projects"; -@import "reports"; -@import "statistics"; -@import "toolbar"; -@import "tour"; -@import "users-navigation"; -@import "users"; -@import "login"; - -/* Component styles */ -@import "components/attendance-slider"; -@import "components/balance-donut"; -@import "components/date-buttons"; -@import "components/date-navigation"; -@import "components/filter-sidebar--group"; -@import "components/filter-sidebar--label"; -@import "components/loading-icon"; -@import "components/magic-link-btn"; -@import "components/nav-top"; -@import "components/progress-tooltip"; -@import "components/record-button"; -@import "components/scroll-container"; -@import "components/sort-header"; -@import "components/statistic-list-bar"; -@import "components/sy-calendar"; -@import "components/sy-checkbox"; -@import "components/sy-datepicker"; -@import "components/sy-durationpicker-day"; -@import "components/sy-modal"; -@import "components/sy-toggle"; -@import "components/timed-clock"; -@import "components/tracking-bar"; -@import "components/weekly-overview"; -@import "components/weekly-overview-benchmark"; -@import "components/weekly-overview-day"; -@import "components/welcome-modal"; - -html { - hyphens: auto; -} - -hr { - border: none; - width: 100%; - height: 7px; - background: linear-gradient(to bottom, rgb(0 0 0 / 3%), rgb(0 0 0 / 0%)); -} - -strong { - font-weight: bold; -} - -.flex { - display: flex; -} - -.margin-small-left { - margin-left: 0.5rem; -} - -.margin-small-right { - margin-left: 0.5rem; -} - -.margin-small-top { - margin-top: 0.5rem; -} - -.margin-small-bottom { - margin-bottom: 0.5rem; -} - -.margin-medium-left { - margin-left: 1rem; -} - -.margin-medium-right { - margin-left: 1rem; -} - -.margin-medium-top { - margin-top: 1rem; -} - -.margin-medium-bottom { - margin-bottom: 1rem; -} - -.flex-grow { - flex: 1; -} - -.flex-shrink { - flex: 0; -} - -.height-100 { - height: 100%; -} - -.pointer { - cursor: pointer; -} - -.table > tfoot > tr > td > .pagination { - margin-left: -10px; -} - -.pagination > li { - margin-right: 5px; -} - -.pagination > li > a { - border: none !important; - border-radius: 4px; - padding: 0.3rem 0.8rem; -} - -.btn-noclick { - pointer-events: none; -} - -.btn-toolbar--right { - justify-content: flex-end; -} - -.page-main { - position: relative; -} - -.nav-tabs { - position: relative; - - > li > a { - white-space: nowrap; - } -} - -.card-block .table { - margin: 0; -} - -.worktime-balance { - border-bottom: 3px double rgb(0 0 0); - font-weight: bold; -} - -.worktime-balance.color-danger { - border-bottom-color: $color-danger; -} - -.worktime-balance.color-success { - border-bottom-color: $color-success; - - &::before { - display: inline-block; - margin-right: -0.2em; - content: "+"; - } -} - -.error-text, -.invalid-feedback { - font-size: 80%; - margin: 0; - color: $color-danger; -} - -.form-group.has-error { - label { - color: $color-danger; - } - - .form-control { - border-color: lighten($color-danger, 20%); - - &:focus, - &:focus-within { - border-color: lighten($color-danger, 20%); - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, - 0 0 8px opacify($color-danger, 0.6); - } - } -} - -.form-control { - &:focus-within { - border-color: lighten($color-primary, 20%); - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, - 0 0 8px opacify($color-primary, 0.6); - } - - &.duration-day { - text-align: center; - } - - &.extendend-durationpicker-day { - padding-bottom: unset; - padding-top: unset; - } - - input { - border: none; - outline: none; - } -} - -.comment-field { - padding-right: 35px; -} - -.btn-group--auto .btn { - flex-grow: 1; -} - -.no-margin { - margin: 0 !important; -} - -.no-padding { - padding: 0 !important; -} - -.nav-tab--buttons { - position: absolute; - right: 0; - bottom: 0; - - .btn { - margin-left: 0.5rem; - z-index: 0; - border-bottom-width: 1px; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } -} - -.calendar { - @include ember-power-calendar($cell-size: 50px); - - .ember-power-calendar-day:not(:disabled) { - cursor: pointer; - transition: background-color 300ms ease; - } - - .ember-power-calendar-day--selected { - background-color: $color-primary; - color: rgb(255 255 255); - - &:not(:disabled):hover { - background-color: lighten($color-primary, 25%); - color: rgb(255 255 255); - } - } - - .ember-power-calendar-day--focused { - box-shadow: inset 0 -2px 0 0 $color-primary; - } -} - -@media #{$sm-viewport} { - .login-form .btn { - width: 125px; - } - - .table--activities tr td:last-child { - display: flex; - } - - .table--activities tr { - height: 45px; - display: flex; - min-width: 0; - - td { - display: flex; - align-items: center; - - &:nth-child(1) { - flex-basis: 10%; - } - - &:nth-child(2) { - flex-basis: 25%; - - // inline-grid property because it doesnt work the right way - display: inline-grid; - - div { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - } - - &:nth-child(3) { - flex-basis: 35%; - display: inline-grid; - - div { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - } - - &:nth-child(4) { - flex-basis: 20%; - justify-content: space-around; - - div.i { - margin-right: 5px; - } - } - - &:nth-child(5) { - flex-basis: 5%; - } - - &:nth-child(6) { - flex-basis: 5%; - justify-content: flex-end; - - .btn { - margin-left: 10px; - } - } - } - } -} - -@media screen and (width <=680px) { - .table--activities tr td { - display: flex; - - &:nth-child(4) { - div { - margin-right: 10px; - } - - div > i { - margin-right: 5px; - } - } - } -} - -.total { - border-bottom: 3px double $body-color; -} - -.table--absence-types > thead > tr > th, -.table--absence-types > tbody > tr > td { - .grid { - margin: 0; - } - - .credit-row { - font-size: 70%; - - &:nth-child(1) { - padding-top: 0.5rem; - } - - .grid-cell:first-child { - padding-left: 1rem; - } - } -} - -.empty { - color: darken($color-border, 25%); - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - - .svg-inline--fa { - margin-bottom: 1rem; - font-size: 10rem; - color: $color-border; - } - - .loading-spinner { - --color: darken($color-border, 25%); - } - - h3 { - color: inherit; - } -} - -.activity-customer-visible-icon { - position: relative; - float: right; - z-index: 1; -} - -.customer-visible-icon { - position: relative; - float: right; - margin-top: -1.7rem; - margin-right: 0.8rem; - z-index: 1; -} - -@media (width <= 680px) { - .activity-customer-visible-icon { - margin-top: 0; - margin-right: 10px; - } - - .customer-visible-icon { - margin-top: -2.5rem; - } -} - -.customer-visible-icon { - margin-top: -1.7rem; -} - -@media #{$sm-viewport} { - .activity-customer-visible-icon { - margin-top: -2rem; - margin-left: 85%; - } -} - -@media #{$md-viewport} { - .activity-customer-visible-icon { - margin-top: -30px; - margin-left: 95%; - } - - .customer-visible-icon { - margin-top: -1.7rem; - } -} diff --git a/frontend/app/styles/attendances.scss b/frontend/app/styles/attendances.scss deleted file mode 100644 index fb2899652..000000000 --- a/frontend/app/styles/attendances.scss +++ /dev/null @@ -1,15 +0,0 @@ -.table--attendances > tbody > tr > td { - &:nth-child(1), - &:nth-child(2) { - width: auto; - } - - &:nth-child(3) { - width: 105px; - text-align: right; - - .btn { - display: inline-flex; - } - } -} diff --git a/frontend/app/styles/badge.scss b/frontend/app/styles/badge.scss deleted file mode 100644 index f7b5862ce..000000000 --- a/frontend/app/styles/badge.scss +++ /dev/null @@ -1,35 +0,0 @@ -.badge { - display: inline-block; - min-width: 10px; - padding: 0.2rem 0.4rem; - margin-left: 0.2rem; - font-size: $font-size-base * 0.8; - line-height: 1; - color: rgb(255 255 255); - text-align: center; - white-space: nowrap; - vertical-align: middle; - background-color: $color-secondary; - border-radius: 10px; -} - -a.active .badge, -.badge--primary { - background-color: $color-primary; -} - -.badge--success { - background-color: $color-success; -} - -.badge--info { - background-color: $color-info; -} - -.badge--warning { - background-color: $color-warning; -} - -.badge--danger { - background-color: $color-danger; -} diff --git a/frontend/app/styles/base.css b/frontend/app/styles/base.css new file mode 100644 index 000000000..517b3367a --- /dev/null +++ b/frontend/app/styles/base.css @@ -0,0 +1,214 @@ +@import "./base/typography.css"; +@import "./base/form.css"; + +:root { + /* taken from https://adfinis.com/en/about-us/branding/ */ + + --dark-blue: 28 46 93; + --dark-moderate-blue: 46 75 152; + --green: 46 152 123; + --black: 15 15 15; + --dark-grey: 139 139 140; + --light-grey: 245 246 245; + + /* not taken from https://adfinis.com/en/about-us/branding/ */ + --white: 255 255 255; + --red: 239 68 68; + --amber: 245 158 11; + + --background: var(--white); + --background-muted: rgb(var(--light-grey)); + --background-secondary: var(--dark-grey); + --danger: rgb(var(--red)); + --danger-accent: color-mix( + in srgb, + var(--danger) 95%, + rgb(var(--foreground-muted)) + ); + --danger-light: color-mix(in srgb, var(--danger) 90%, rgb(var(--white))); + --foreground-muted: var(--dark-grey); + --foreground-primary: var(--white); + --foreground-secondary: var(--foreground-primary); + --foreground-accent: rgb(var(--black)); + --foreground: rgb(var(--black)); + --foreground-light: color-mix( + in srgb, + var(--background-muted) 80%, + rgb(var(--white)) + ); + + --tertiary-dark: rgb(var(--dark-blue)); + --tertiary: color-mix(in srgb, var(--tertiary-dark) 80%, rgb(var(--white))); + --tertiary-light: color-mix(in srgb, var(--tertiary) 80%, rgb(var(--white))); + + --primary-dark: rgb(var(--dark-moderate-blue)); + --primary: color-mix(in srgb, var(--primary-dark) 80%, rgb(var(--white))); + --primary-light: color-mix(in srgb, var(--primary) 80%, rgb(var(--white))); + + --secondary: rgb(var(--dark-grey)); + --secondary-light: color-mix( + in srgb, + var(--secondary) 70%, + rgb(var(--white)) + ); + --secondary-dark: color-mix(in srgb, var(--secondary) 80%, rgb(var(--black))); + + --success: rgb(var(--green)); + + --success-accent: color-mix(in srgb, var(--success) 95%, rgb(var(--black))); + --success-light: color-mix(in srgb, var(--success) 90%, rgb(var(--white))); + + --warning: rgb(var(--amber)); + + --warning-light: color-mix(in srgb, var(--warning) 90%, rgb(var(--white))); + --warning-accent: color-mix(in srgb, var(--warning) 95%, var(--danger)); + + --border-radius: 4px; + --border: color-mix( + in srgb, + rgb(var(--background)), + rgb(var(--foreground-muted)) + ); + + /* give simple ways to override */ + --overview-workday-active: var(--overview-active); + --overview-workday-hf: var(--overview-hf); + --overview-absence-active: var(--overview-active); + --overview-absence-hf: var(--overview-hf); + --overview-weekend-active: var(--overview-active); + --overview-weekend-hf: var(--overview-hf); + + --clock: var(--foreground); + --clock-accent: var(--success); +} + +.regular { + --overview-workday: color-mix( + in srgb, + var(--primary-light) 80%, + rgb(var(--white)) + ); + + --overview-workday-hf: var(--primary); + + --overview-workday-active: var(--primary-dark); + + --overview-absence: color-mix( + in srgb, + var(--warning-light) 80%, + rgb(var(--white)) + ); + + --overview-absence-hf: var(--warning-light); + + --overview-absence-active: var(--warning); + + --overview-weekend: color-mix(in srgb, var(--secondary), rgb(var(--white))); + --overview-weekend-hf: color-mix( + in srgb, + var(--overview-weekend) 90%, + rgb(var(--black)) + ); + --overview-weekend-active: var(--secondary); +} + +/* experimental dark theme */ +.dark.regular { + --background: var(--black); + --background-muted: color-mix( + in srgb, + rgb(var(--background)) 90%, + var(--foreground) + ); + --background-secondary: var(--light-grey); + --foreground-muted: rgb(var(--dark-grey)); + --foreground-accent: rgb(var(--white)); + --foreground: color-mix( + in srgb, + var(--foreground-accent) 80%, + rgb(var(--background)) + ); + --primary: color-mix(in srgb, var(--primary-dark) 75%, rgb(var(--white))); + --primary-light: color-mix(in srgb, var(--primary) 90%, rgb(var(--white))); + --tertiary-dark: rgb(var(--dark-moderate-blue)); +} + +/* experimental old theme */ +.old { + --old-primary: 91 142 219; + --old-tertiary-dark: 38 91 171; + --old-foreground: 61 61 61; + --old-success: 92 184 92; + --old-danger: 217 83 79; + --old-warning: 240 173 78; + --old-secondary: 150 150 150; + --old-background-muted: 238 238 238; + --old-background-secondary: 230 230 230; + --old-weekend: 220 220 220; + --old-overview-hoverorfocus: 121 148 189; + + --primary: rgb(var(--old-primary)); + --primary-dark: color-mix( + in srgb, + var(--primary) 90%, + rgb(var(--dark-moderate-blue)) + ); + + --secondary: rgb(var(--old-secondary)); + --tertiary-dark: rgb(var(--old-tertiary-dark)); + + --background: var(--white); + --background-muted: rgb(var(--old-background-muted)); + --background-secondary: var(--old-background-secondary); + --foreground-secondary: var(--foreground); + --foreground-muted: var(--dark-grey); + --foreground: rgb(var(--old-foreground)); + --success: rgb(var(--old-success)); + --danger: rgb(var(--old-danger)); + --warning: rgb(var(--old-warning)); + + --overview-workday: var(--secondary); + --overview-absence: var(--warning); + --overview-weekend: rgb(var(--old-weekend)); + --overview-active: var(--primary); + --overview-hf: rgb(var(--old-overview-hoverorfocus)); + + --clock-accent: var(--danger); +} + +.dark.old { + --background: var(--black); + --background-muted: color-mix( + in srgb, + rgb(var(--background)) 85%, + var(--foreground) + ); + + --primary-dark: rgb(var(--old-tertiary-dark)); + --primary: color-mix(in srgb, var(--primary-dark) 80%, rgb(var(--white))); + --primary-light: color-mix( + in srgb, + var(--primary) 90%, + rgb(var(--old-primary)) + ); + + --tertiary-dark: rgb(var(--old-primary)); + --foreground: color-mix( + in srgb, + rgb(var(--white)) 84%, + rgb(var(--background)) + ); + --foreground-accent: rgb(var(--white)); + + --secondary: color-mix( + in srgb, + rgb(var(--old-secondary)) 80%, + rgb(var(--background)) + ); + + --warning: rgb(var(--amber)); + --success: color-mix(in srgb, rgb(var(--old-success)), rgb(var(--green))); + --danger: color-mix(in srgb, rgb(var(--red)), rgb(var(--old-danger))); + + --clock: rgb(var(--foreground-muted)); +} diff --git a/frontend/app/styles/base/form.css b/frontend/app/styles/base/form.css new file mode 100644 index 000000000..1f8e01d52 --- /dev/null +++ b/frontend/app/styles/base/form.css @@ -0,0 +1,52 @@ +[type="text"], +[type="email"], +[type="url"], +[type="password"], +[type="number"], +[type="date"], +[type="datetime-local"], +[type="month"], +[type="search"], +[type="tel"], +[type="time"], +[type="week"], +[multiple], +textarea, +select, +.form-input, +.form-textarea, +.form-select, +.form-multiselect { + @apply focus:border-primary-light focus:ring-primary-light border transition-[border-color]; + @apply placeholder-foreground-muted bg-background w-full py-1.5 text-sm xl:text-base !important; +} + +:is( + [type="text"], + [type="email"], + [type="url"], + [type="password"], + [type="number"], + [type="date"], + [type="datetime-local"], + [type="month"], + [type="search"], + [type="tel"], + [type="time"], + [type="week"], + [type="checkbox"], + [multiple], + textarea, + select, + .form-input, + .form-textarea, + .form-select, + .form-multiselect + ):is(:disabled, [aria-disabled="true"]) { + @apply text-foreground-muted cursor-not-allowed; + @apply bg-background-muted !important; +} + +[type="checkbox"] { + @apply text-primary; +} diff --git a/frontend/app/styles/base/typography.css b/frontend/app/styles/base/typography.css new file mode 100644 index 000000000..87e6a8188 --- /dev/null +++ b/frontend/app/styles/base/typography.css @@ -0,0 +1,23 @@ +h1 { + @apply text-primary text-4xl; +} + +h2 { + @apply text-3xl; +} + +h3 { + @apply text-2xl; +} + +h4 { + @apply text-xl; +} + +h5 { + @apply text-lg; +} + +strong { + @apply font-medium; +} diff --git a/frontend/app/styles/components.css b/frontend/app/styles/components.css new file mode 100644 index 000000000..ec689d11f --- /dev/null +++ b/frontend/app/styles/components.css @@ -0,0 +1,10 @@ +@import "./components/alert.css"; +@import "./components/basic-dropdown.css"; +@import "./components/button.css"; +@import "./components/customer-comment.css"; +@import "./components/form.css"; +@import "./components/power-calendar.css"; +@import "./components/power-select.css"; +@import "./components/remaining-effort.css"; +@import "./components/slider.css"; +@import "./components/shepherd.css"; diff --git a/frontend/app/styles/components/alert.css b/frontend/app/styles/components/alert.css new file mode 100644 index 000000000..15a0b13a0 --- /dev/null +++ b/frontend/app/styles/components/alert.css @@ -0,0 +1,15 @@ +.ember-notify.alert { + @apply rounded; +} + +.ember-notify.alert-danger { + @apply bg-danger-light text-foreground-primary border-danger/80; +} + +.ember-notify.alert-info { + @apply bg-primary-light text-foreground-primary border-primary/80; +} + +.ember-notify.alert-success { + @apply bg-success-light text-foreground-primary border-success/80; +} diff --git a/frontend/app/styles/components/attendance-slider.scss b/frontend/app/styles/components/attendance-slider.scss deleted file mode 100644 index 9fd6a46ed..000000000 --- a/frontend/app/styles/components/attendance-slider.scss +++ /dev/null @@ -1,81 +0,0 @@ -.attendance-slider { - padding-top: 1rem; - position: relative; - - .noUi-handle-lower { - cursor: w-resize; - } - - .noUi-handle-upper { - cursor: e-resize; - } - - .noUi-handle { - right: 0 !important; - width: 8px; - height: 25px; - top: -4px; - border-radius: 0; - - &::after, - &::before { - display: none; - } - } - - .noUi-tooltip { - left: 50%; - transform: translateX(-50%); - background: transparent; - border: none; - font-size: 10px; - font-family: $font-family-mono; - } - - .noUi-handle-lower .noUi-tooltip, - .noUi-handle-upper .noUi-tooltip { - top: -18px; - } - - .noUi-connect { - background: $color-primary; - } - - .noUi-draggable { - cursor: move; - } - - .slider-labels { - position: relative; - height: 3rem; - } - - .slider-label { - display: flex; - font-family: $font-family-mono; - position: absolute; - font-size: 0.6rem; - top: 1rem; - transform: translateX(-75%); - - &--sm { - font-size: 0.5rem; - color: desaturate($body-color, 50%); - } - } - - .slider-label-text { - transform: rotate(-45deg); - } - - .slider-title { - position: absolute; - top: 0; - left: 0; - font-size: 12px; - - .fa-trash-can { - cursor: pointer; - } - } -} diff --git a/frontend/app/styles/components/balance-donut.scss b/frontend/app/styles/components/balance-donut.scss deleted file mode 100644 index 33d47d08d..000000000 --- a/frontend/app/styles/components/balance-donut.scss +++ /dev/null @@ -1,108 +0,0 @@ -.balance-donut { - --max-offset: 0; - - transition: transform 1s ease; - transform: translateY(calc(var(--max-offset) * var(--offset-multiplicator))); - - .donut-title { - color: $body-color; - font-size: 1.5rem; - word-break: break-all; - hyphens: auto; - } - - .donut { - position: relative; - } - - .donut-ring { - stroke: rgb(200 200 200); - } - - .donut-content { - animation: donut-content 1s ease-in-out; - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; - font-size: 1.2rem; - padding: 1rem; - word-break: break-all; - - div:first-child:not(:last-child) { - font-size: 60%; - color: lighten($body-color, 30%); - } - } - - @keyframes donut-content { - 0% { - opacity: 0; - transform: scale(0); - } - - 80% { - transform: scale(1.06); - } - - 90% { - transform: scale(0.94); - } - - 95% { - transform: scale(1.02); - } - - 100% { - opacity: 1; - transform: scale(1); - } - } - - @mixin donut-segment($color-name, $color) { - stroke: $color; - animation-name: donut-segment-#{$color-name}; - - @keyframes donut-segment-#{$color-name} { - from { - stroke: darken($color, 50%); - stroke-dasharray: 0 100; - } - } - } - - .donut-segment { - @include donut-segment("primary", $color-primary); - - animation-duration: 1s; - animation-timing-function: ease-in-out; - } - - &.success .donut-segment { - @include donut-segment("success", $color-success); - } - - &.info .donut-segment { - @include donut-segment("info", $color-info); - } - - &.warning .donut-segment { - @include donut-segment("warning", $color-warning); - } - - &.danger .donut-segment { - @include donut-segment("danger", $color-danger); - } - - @media #{$lg-viewport} { - & { - --max-offset: -90px; - } - } -} diff --git a/frontend/app/styles/components/basic-dropdown.css b/frontend/app/styles/components/basic-dropdown.css new file mode 100644 index 000000000..23d469093 --- /dev/null +++ b/frontend/app/styles/components/basic-dropdown.css @@ -0,0 +1,7 @@ +.ember-basic-dropdown-content { + @apply border-border bg-background absolute z-30 w-auto rounded border p-2; +} + +.ember-basic-dropdown-content-wormhole-origin { + @apply hidden; +} diff --git a/frontend/app/styles/components/button.css b/frontend/app/styles/components/button.css new file mode 100644 index 000000000..8e4872159 --- /dev/null +++ b/frontend/app/styles/components/button.css @@ -0,0 +1,64 @@ +.btn { + @apply border-border block rounded border px-4 py-1.5 transition-all; +} + +.btn:disabled, +.btn[aria-disabled="true"] { + @apply cursor-not-allowed border-opacity-40 bg-opacity-40 text-opacity-85; + + &.btn-default { + @apply bg-background-muted/70 text-foreground-muted/85; + } +} + +.btn:not(:disabled, [aria-disabled="true"]) { + @apply shadow-sm hover:shadow; + + &.btn-default { + @apply hover:text-primary dark:hover:text-primary-light hover:border-primary hover:shadow-primary/10; + } + + &.btn-primary { + @apply shadow-primary/15 hover:border-primary-dark/85 hover:shadow-tertiary/50; + } + + &.btn-danger { + @apply shadow-danger/15 hover:shadow-danger/50 hover:border-danger-accent/90; + } + + &.btn-success { + @apply shadow-success/15 hover:shadow-success/50 hover:border-success-accent/90; + } + + &.btn-warning { + @apply shadow-warning/15 hover:shadow-warning/50 hover:border-warning-accent/90; + } +} + +.btn-default { + @apply bg-background border-border; +} + +.btn-primary { + @apply bg-primary-light text-foreground-primary border-primary; +} + +.btn-danger { + @apply bg-danger-light text-foreground-primary border-danger/40; +} + +.btn-success { + @apply bg-success-light text-foreground-primary border-success/40; +} + +.btn-warning { + @apply bg-warning-light text-foreground-primary border-warning/40; +} + +.btn-group { + @apply flex; +} + +.btn-group .btn { + @apply whitespace-nowrap rounded-none first:rounded-l last:rounded-r; +} diff --git a/frontend/app/styles/components/customer-comment.css b/frontend/app/styles/components/customer-comment.css new file mode 100644 index 000000000..43527a533 --- /dev/null +++ b/frontend/app/styles/components/customer-comment.css @@ -0,0 +1,8 @@ +/* add eye icon into input */ +input.customer-comment { + background-image: url("/assets/eye-regular.svg") !important; + background-position: right 0.5rem center; + print-color-adjust: exact; + background-size: 1.5em; + @apply bg-no-repeat pr-9; +} diff --git a/frontend/app/styles/components/date-buttons.scss b/frontend/app/styles/components/date-buttons.scss deleted file mode 100644 index ac4e692ef..000000000 --- a/frontend/app/styles/components/date-buttons.scss +++ /dev/null @@ -1,3 +0,0 @@ -.date-button { - width: 32.5%; -} diff --git a/frontend/app/styles/components/date-navigation.scss b/frontend/app/styles/components/date-navigation.scss deleted file mode 100644 index 945ee85f5..000000000 --- a/frontend/app/styles/components/date-navigation.scss +++ /dev/null @@ -1,22 +0,0 @@ -.date-navigation { - display: flex; - flex-grow: 1; - justify-content: space-between; - padding: 1rem 0; -} - -.btn-group { - margin-right: 10px; -} - -.date-navigation-container { - flex-grow: 1; - display: flex; -} - -@media #{$sm-viewport} { - .date-navigation { - justify-content: flex-end; - padding: 0; - } -} diff --git a/frontend/app/styles/components/filter-sidebar--group.scss b/frontend/app/styles/components/filter-sidebar--group.scss deleted file mode 100644 index 48237e757..000000000 --- a/frontend/app/styles/components/filter-sidebar--group.scss +++ /dev/null @@ -1,47 +0,0 @@ -.filter-sidebar-group { - display: flex; - flex-direction: column; - - &.filter-sidebar-group--expanded .filter-sidebar-group-label .fa { - transform: rotate(90deg); - } - - &.filter-sidebar-group--expanded .filter-sidebar-group-label, - .filter-sidebar-group-label:hover { - color: $body-color; - } - - &.filter-sidebar-group--expanded .filter-sidebar-group-body { - max-height: 450px; - } - - .filter-sidebar-group-label { - display: flex; - justify-content: space-between; - align-items: center; - cursor: pointer; - padding: 1rem; - color: lighten($body-color, 50%); - border-top: 1px solid $color-border; - transition: color 0.3s ease; - - &:focus { - outline: none; - } - } - - .filter-sidebar-group-body { - display: block; - overflow: hidden; - max-height: 0; - transition: max-height 0.3s ease; - } - - .filter-sidebar-group-content { - padding: 0.5rem 1rem; - } - - .filter-sidebar-group-label .fa { - transition: transform 0.3s ease; - } -} diff --git a/frontend/app/styles/components/filter-sidebar--label.scss b/frontend/app/styles/components/filter-sidebar--label.scss deleted file mode 100644 index c6775b30a..000000000 --- a/frontend/app/styles/components/filter-sidebar--label.scss +++ /dev/null @@ -1,11 +0,0 @@ -.filter-sidebar-label { - display: block; - font-size: 0.75rem; - font-weight: 500; - padding: 0.5rem 0; -} - -.filter-sidebar-label > * { - font-weight: 300; - margin-top: 0.3rem; -} diff --git a/frontend/app/styles/components/form.css b/frontend/app/styles/components/form.css new file mode 100644 index 000000000..9ce767c15 --- /dev/null +++ b/frontend/app/styles/components/form.css @@ -0,0 +1,5 @@ +/* style 3rd-party classes that we can't change */ + +.invalid-feedback { + @apply text-danger; +} diff --git a/frontend/app/styles/components/loading-icon.scss b/frontend/app/styles/components/loading-icon.scss deleted file mode 100644 index eac27cfcd..000000000 --- a/frontend/app/styles/components/loading-icon.scss +++ /dev/null @@ -1,84 +0,0 @@ -.loading-icon { - --size: 140px; - - display: inline-flex; - flex-wrap: wrap; - height: var(--size); - width: var(--size); - animation: loading-pop-up 1s ease forwards; - - .loading-dot { - height: calc(1 / 3 * var(--size)); - width: calc(1 / 3 * var(--size)); - position: relative; - opacity: 0.75; - - &:nth-child(5)::before { - animation-delay: 0ms; - background-color: darken($color-primary, 40%); - height: 80%; - width: 80%; - } - - &:nth-child(1)::before, - &:nth-child(3)::before, - &:nth-child(7)::before, - &:nth-child(9)::before { - animation-delay: -500ms; - background-color: darken($color-primary, 0%); - height: 60%; - width: 60%; - } - - &:nth-child(2)::before, - &:nth-child(4)::before, - &:nth-child(6)::before, - &:nth-child(8)::before { - animation-delay: -1000ms; - background-color: darken($color-primary, 20%); - height: 70%; - width: 70%; - } - - &::before { - content: ""; - display: block; - position: absolute; - top: 50%; - left: 50%; - border-radius: 50%; - transform-origin: center center; - opacity: 1; - transform: translate(-50%, -50%) scale(1); - will-change: opacity, transform; - animation: loading-flash 3000ms ease-in-out infinite; - } - } -} - -@keyframes loading-pop-up { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} - -@keyframes loading-flash { - 0% { - opacity: 1; - transform: translate(-50%, -50%) scale(1); - } - - 50% { - opacity: 0.4; - transform: translate(-50%, -50%) scale(0.9); - } - - 100% { - opacity: 1; - transform: translate(-50%, -50%) scale(1); - } -} diff --git a/frontend/app/styles/components/magic-link-btn.scss b/frontend/app/styles/components/magic-link-btn.scss deleted file mode 100644 index 6efc845d9..000000000 --- a/frontend/app/styles/components/magic-link-btn.scss +++ /dev/null @@ -1,7 +0,0 @@ -.ember-basic-dropdown-content { - z-index: 1002; -} - -.magic-link-modal { - min-width: 500px; -} diff --git a/frontend/app/styles/components/nav-top.scss b/frontend/app/styles/components/nav-top.scss deleted file mode 100644 index cb4a2cef2..000000000 --- a/frontend/app/styles/components/nav-top.scss +++ /dev/null @@ -1,53 +0,0 @@ -nav { - .nav-top-header-title { - display: none; - font-weight: 500; - } - - .timed-clock { - padding: 0.3rem 0; - margin-right: 0.3rem; - } - - .nav-top-toggle { - display: block; - } - - .nav-top-list-item a { - display: grid; - grid-template-columns: 2em 1fr; - align-items: center; - } - - @media #{$nav-top-mobile-width} { - .nav-top-header-title { - display: block; - } - - .nav-top-header-title-version { - color: rgb(150 150 150); - font-size: 0.5rem; - font-family: $font-family-mono; - } - - .nav-top-list-item a.active { - background-color: $color-primary; - color: #fff; - } - - .nav-top-list-item a:hover { - background-color: lighten($color-primary, 20%); - color: #fff; - } - - .nav-top-list-item a { - padding: 0.6rem 0.8rem; - border-radius: 0; - display: revert; - } - - .nav-top-toggle { - display: none; - } - } -} diff --git a/frontend/app/styles/components/power-calendar.css b/frontend/app/styles/components/power-calendar.css new file mode 100644 index 000000000..5a15c7400 --- /dev/null +++ b/frontend/app/styles/components/power-calendar.css @@ -0,0 +1,60 @@ +.ember-power-calendar { + --size: 3rem; +} + +.ember-power-calendar-day-grid { + @apply grid gap-0.5; +} + +.ember-power-calendar-row { + @apply flex justify-between gap-0.5; +} + +.ember-power-calendar-day, +.ember-power-calendar-weekday { + @apply grid h-[--size] max-h-[--size] w-[--size] max-w-[--size] place-items-center; +} + +.ember-power-calendar-day--interactive[disabled] { + @apply opacity-40; +} + +.ember-power-calendar-day:not([disabled]) { + @apply transition-colors; +} + +.ember-power-calendar-day--other-month { + @apply text-foreground-muted; +} + +.ember-power-calendar-day--current-month { + @apply bg-background-muted; +} + +.ember-power-calendar-day--selected { + @apply bg-primary text-foreground-primary; +} + +.ember-power-calendar-day--current-month:not([disabled]) { + @apply hover:bg-background-secondary/50; +} + +.ember-power-calendar-day--other-month:not([disabled]):hover { + @apply text-foreground bg-background-secondary/40; +} + +.ember-power-calendar-day--selected:not([disabled]):hover { + @apply bg-primary-light text-foreground-primary; +} + +.ember-power-calendar-nav { + @apply flex items-center justify-between; +} + +.ember-power-calendar-nav-title { + @apply font-medium; +} + +.ember-power-calendar-nav-control { + @apply text-primary text-2xl; +} diff --git a/frontend/app/styles/components/power-select.css b/frontend/app/styles/components/power-select.css new file mode 100644 index 000000000..8c12de757 --- /dev/null +++ b/frontend/app/styles/components/power-select.css @@ -0,0 +1,60 @@ +.ember-power-select-dropdown { + @apply min-w-64 lg:min-w-72; +} + +.ember-power-select-trigger { + @apply form-select focus:border-primary-light focus:ring-primary-light relative flex overflow-hidden; +} + +.ember-power-select-selected-item { + @apply w-full; +} + +.ember-power-select-option div { + @apply cursor-pointer px-2; +} + +.ember-power-select-option[aria-current="true"] div { + @apply text-foreground-primary bg-primary-light; +} + +.ember-power-select-option[aria-selected="true"] div { + @apply bg-primary-dark text-foreground-primary; +} + +.ember-power-select-option div.inactive { + @apply bg-secondary-light/70 text-foreground-secondary; +} + +.ember-power-select-option[aria-current="true"] div.inactive { + @apply bg-secondary-light/90; +} + +.ember-power-select-option[aria-selected="true"] div.inactive { + @apply bg-secondary-dark text-foreground-primary; +} + +.ember-power-select-visually-hidden { + @apply hidden; +} + +.ember-power-select-placeholder { + @apply truncate; +} + +.ember-power-select-trigger[aria-disabled="false"] + .ember-power-select-placeholder { + @apply text-foreground-accent/70; +} + +.ember-basic-dropdown-trigger--above { + @apply rounded-t-none; +} + +.ember-basic-dropdown-trigger--below { + @apply rounded-b-none; +} + +.ember-power-select-options[role="listbox"] { + @apply max-h-96 overflow-y-auto lg:max-h-[28rem]; +} diff --git a/frontend/app/styles/components/progress-tooltip.scss b/frontend/app/styles/components/progress-tooltip.scss deleted file mode 100644 index 162cafc0d..000000000 --- a/frontend/app/styles/components/progress-tooltip.scss +++ /dev/null @@ -1,81 +0,0 @@ -$progress-tooltip-arrow-size: 0.5rem; -$progress-tooltip-color: rgb(87 87 87); - -.progress-tooltip { - z-index: 1000; - background: $progress-tooltip-color; - box-shadow: 0 1px 5px rgb(23 23 23 / 50%); - max-width: initial; - color: rgb(255 255 255); - font-size: 0.9rem; - padding: 0.3rem 0.5rem; - border-radius: 0.3rem; - animation: 200ms ease slide-in; - - .time-info { - display: grid; - grid-template-columns: 1fr auto; - grid-template-rows: auto; - grid-gap: 0.25rem 0.5rem; - margin: 0.25rem; - - :nth-child(1) { - grid-area: 1 / 1 / 2 / 2; - } - - :nth-child(2) { - grid-area: 1 / 2 / 2 / 3; - } - - :nth-child(3) { - grid-area: 2 / 1 / 3 / 2; - } - - :nth-child(4) { - grid-area: 2 / 2 / 3 / 3; - } - - :nth-child(5) { - grid-area: 3 / 1 / 4 / 3; - } - - :nth-child(6) { - grid-area: 4 / 1 / 5 / 2; - } - - :nth-child(7) { - grid-area: 4 / 2 / 5 / 3; - } - - .progress-badge { - display: flex; - justify-content: end; - } - } - - &::after { - content: ""; - display: block; - width: 0; - height: 0; - position: absolute; - right: 0; - top: 50%; - transform: translate(100%, -50%); - border-top: $progress-tooltip-arrow-size solid transparent; - border-bottom: $progress-tooltip-arrow-size solid transparent; - border-left: $progress-tooltip-arrow-size solid $progress-tooltip-color; - } -} - -@keyframes slide-in { - from { - opacity: 0; - left: -15px; - } - - to { - opacity: 1; - left: 0; - } -} diff --git a/frontend/app/styles/components/record-button.scss b/frontend/app/styles/components/record-button.scss deleted file mode 100644 index bc2fa7146..000000000 --- a/frontend/app/styles/components/record-button.scss +++ /dev/null @@ -1,80 +0,0 @@ -.record-button-container { - display: flex; - justify-content: center; - position: relative; - background: rgb(80 80 80); - border-radius: 1.5rem; - height: 3rem; - width: 3rem; - margin: 0 auto; - transition: width 300ms ease; - font-family: $font-family-mono; - font-size: 14px; - - &--recording { - width: 10rem; - } - - .record-button { - position: absolute; - top: 0.4rem; - left: 0.4rem; - width: 2.2rem; - height: 2.2rem; - padding: 0; - border-radius: 50%; - border: none; - cursor: pointer; - background: radial-gradient( - circle at center, - rgb(240 240 240) 50%, - rgb(180 180 180) 80% - ); - z-index: 2; - - svg { - vertical-align: middle; - } - - &--start, - &--stop { - color: $color-danger; - } - } - - .record-button-timer { - position: absolute; - right: 0.8rem; - top: 50%; - transform: translateY(-50%); - color: white; - overflow: hidden; - pointer-events: none; - text-align: right; - } -} - -@media #{$md-viewport} { - .record-button-container--recording { - width: 9rem; - } -} - -@media #{$lg-viewport} { - .record-button-container { - justify-content: flex-start; - height: 2rem; - width: 2rem; - - &--recording { - width: 7.5rem; - } - - .record-button { - height: 1.6rem; - width: 1.6rem; - top: 0.2rem; - left: 0.2rem; - } - } -} diff --git a/frontend/app/styles/components/remaining-effort.css b/frontend/app/styles/components/remaining-effort.css new file mode 100644 index 000000000..f29a12f91 --- /dev/null +++ b/frontend/app/styles/components/remaining-effort.css @@ -0,0 +1,8 @@ +/* add remaining effort icon into input */ +input.remaining-effort { + background-image: url("/assets/remaining-effort.svg") !important; + background-position: left 0.5rem center; + print-color-adjust: exact; + background-size: 1.5em; + @apply bg-no-repeat pl-9; +} diff --git a/frontend/app/styles/components/scroll-container.scss b/frontend/app/styles/components/scroll-container.scss deleted file mode 100644 index 95ceb24e8..000000000 --- a/frontend/app/styles/components/scroll-container.scss +++ /dev/null @@ -1,25 +0,0 @@ -.scroll-container { - max-height: 100%; - min-height: 20px; - overflow-y: auto; - - &::after, - &::before { - content: ""; - position: absolute; - z-index: 1; - left: 0; - right: 0; - height: 7px; - background: linear-gradient(to bottom, rgb(0 0 0 / 3%), rgb(0 0 0 / 0%)); - } - - &::before { - top: 0; - } - - &::after { - bottom: 0; - transform: rotate(180deg); - } -} diff --git a/frontend/app/styles/components/shepherd.css b/frontend/app/styles/components/shepherd.css new file mode 100644 index 000000000..f51f423c1 --- /dev/null +++ b/frontend/app/styles/components/shepherd.css @@ -0,0 +1,94 @@ +.shepherd-header { + @apply bg-background-muted border-b px-4 py-2 first:rounded-t; /* same as card-header */ +} + +.shepherd-text { + @apply p-4; /* same as card-block */ +} + +.sheperd-text p { + @apply py-1; +} + +.shepherd-content { + @apply bg-background text-foreground rounded; +} + +.shepherd-footer { + @apply bg-background-muted border-t px-4 py-2 last:rounded-b; /* same as card-footer */ + @apply flex justify-between; +} + +.shepherd-element { + @apply bg-background invisible z-[80] m-0 w-full max-w-96 rounded opacity-0 shadow-sm outline-none transition-[visibility,opacity] duration-300; +} + +.shepherd-enabled.shepherd-element { + @apply visible opacity-100; +} + +.shepherd-element[data-popper-reference-hidden]:not(.shepherd-centered) { + @apply pointer-events-none invisible opacity-0; +} + +.shepherd-arrow, +.shepherd-arrow::before { + @apply absolute -z-[1] h-4 w-4; +} + +.shepherd-arrow::before { + @apply bg-background rotate-45 content-[""]; +} + +.shepherd-element[data-popper-placement^="top"] > .shepherd-arrow { + @apply -bottom-2; +} + +.shepherd-element[data-popper-placement^="bottom"] > .shepherd-arrow { + @apply -top-2; +} + +.shepherd-element[data-popper-placement^="left"] > .shepherd-arrow { + @apply -right-2; +} + +.shepherd-element[data-popper-placement^="right"] > .shepherd-arrow { + @apply -left-2; +} + +.shepherd-element.shepherd-centered > .shepherd-arrow { + @apply opacity-0; +} + +.shepherd-element.shepherd-has-title[data-popper-placement^="bottom"] + > .shepherd-arrow::before { + @apply bg-background-muted; +} + +.shepherd-target-click-disabled.shepherd-enabled.shepherd-target, +.shepherd-target-click-disabled.shepherd-enabled.shepherd-target * { + @apply pointer-events-none; +} + +.shepherd-modal-overlay-container { + @apply pointer-events-none fixed left-0 top-0 z-[70] h-0 w-screen overflow-hidden opacity-0; + + transition: + all 0.3s ease-out, + height 0s 0.3s, + opacity 0.3s 0s; +} + +.shepherd-modal-overlay-container.shepherd-modal-is-visible { + @apply fill-foreground-muted h-screen opacity-50; + + transform: translateZ(0); + transition: + all 0.3s ease-out, + height 0s 0s, + opacity 0.3s 0s; +} + +.shepherd-modal-overlay-container.shepherd-modal-is-visible path { + @apply pointer-events-all; +} diff --git a/frontend/app/styles/components/slider.css b/frontend/app/styles/components/slider.css new file mode 100644 index 000000000..2367615e4 --- /dev/null +++ b/frontend/app/styles/components/slider.css @@ -0,0 +1,32 @@ +.noUi-tooltip { + @apply text-foreground -top-[18px] left-1/2 translate-x-1/2 border-none bg-transparent text-xs; +} + +.noUi-handle { + @apply -top-1 right-0 h-6 w-2 rounded-sm !important; +} + +.noUi-connect { + @apply bg-primary; +} + +.noUi-connects { + @apply relative overflow-hidden; +} + +.noUi-handle::after, +.noUi-handle::before { + @apply hidden; +} + +.noUi-handle-lower { + @apply cursor-w-resize; +} + +.noUi-handle-upper { + @apply cursor-e-resize; +} + +.noUi-draggable { + @apply cursor-move; +} diff --git a/frontend/app/styles/components/sort-header.scss b/frontend/app/styles/components/sort-header.scss deleted file mode 100644 index 511c04442..000000000 --- a/frontend/app/styles/components/sort-header.scss +++ /dev/null @@ -1,4 +0,0 @@ -.sort-header { - white-space: nowrap; - cursor: pointer; -} diff --git a/frontend/app/styles/components/statistic-list-bar.scss b/frontend/app/styles/components/statistic-list-bar.scss deleted file mode 100644 index 8a0ab71da..000000000 --- a/frontend/app/styles/components/statistic-list-bar.scss +++ /dev/null @@ -1,85 +0,0 @@ -.statistic-list-bar-wrapper { - height: 20px; - - .statistic-list-bar { - width: 100%; - height: 20px; - position: relative; - overflow: hidden; - z-index: 3; - - --value: 0; - - &::before { - content: ""; - display: block; - height: 100%; - width: 100%; - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - background-color: $color-primary; - transform: translateX(calc((1 - var(--value)) * -100%)); - transition: transform 0.5s cubic-bezier(0.86, 0, 0.07, 1); - animation: slide-in-statistic-bar 0.5s cubic-bezier(0.86, 0, 0.07, 1); - } - - &.strong-success::before { - background-color: $color-success; - } - - &.strong-danger::before { - background-color: $color-danger; - } - - &.success::before { - background-color: $color-success-lighter; - } - - &.danger::before { - background-color: $color-danger-lighter; - } - - &.remaining { - // align on the same level as progress bar - top: -20px; - z-index: 2; - } - } - - .statistic-list-bar-goal { - position: relative; - height: 30px; - width: 100%; - overflow: hidden; - - --goal: 0; - - &::before { - content: ""; - display: block; - height: 100%; - width: 100%; - background-color: transparent; - border-left: 2px dotted $color-danger-darker; - transform: translateX(calc(var(--goal) * 100%)); - transition: transform 0.5s cubic-bezier(0.86, 0, 0.07, 1); - animation: slide-in-statistic-bar 0.5s cubic-bezier(0.86, 0, 0.07, 1); - } - } - - // case: remaining effort tracking is disabled - :nth-child(2).statistic-list-bar-goal { - top: -25px; - } - - // case: remaining effort tracking is enabled - :nth-child(3).statistic-list-bar-goal { - top: -45px; - } - - @keyframes slide-in-statistic-bar { - 0% { - transform: translateX(-100%); - } - } -} diff --git a/frontend/app/styles/components/sy-calendar.scss b/frontend/app/styles/components/sy-calendar.scss deleted file mode 100644 index 21585cc5a..000000000 --- a/frontend/app/styles/components/sy-calendar.scss +++ /dev/null @@ -1,44 +0,0 @@ -.sy-calendar { - @include ember-power-calendar($cell-size: 35px); - - .ember-power-calendar-nav-control { - color: $color-primary; - cursor: pointer; - } - - .nav-select-month, - .nav-select-year { - position: relative; - - select { - position: absolute; - inset: 0; - opacity: 0; - } - } - - .ember-power-calendar-day { - cursor: pointer; - transition: background-color 300ms ease, color 300ms ease; - - &--focused { - box-shadow: inset 0 -2px 0 0 $color-primary; - } - - &--selected { - color: rgb(255 255 255); - background-color: lighten($color-primary, 20%); - - &:hover { - color: rgb(255 255 255); - background-color: lighten($color-primary, 30%); - } - } - } -} - -.sy-calendar.sy-datepicker { - border: 1px solid $color-border; - padding: 0.5rem; - box-shadow: 2px 2px 10px rgb(0 0 0 / 20%); -} diff --git a/frontend/app/styles/components/sy-checkbox.scss b/frontend/app/styles/components/sy-checkbox.scss deleted file mode 100644 index 8a5b40d22..000000000 --- a/frontend/app/styles/components/sy-checkbox.scss +++ /dev/null @@ -1,6 +0,0 @@ -.sy-checkbox > input[type="checkbox"]:indeterminate + label::after { - content: "\2012"; - opacity: 1; - transform: scale(1); - left: 0.23rem; -} diff --git a/frontend/app/styles/components/sy-datepicker.scss b/frontend/app/styles/components/sy-datepicker.scss deleted file mode 100644 index 779a857c7..000000000 --- a/frontend/app/styles/components/sy-datepicker.scss +++ /dev/null @@ -1,15 +0,0 @@ -.sy-datepicker-trigger.ember-basic-dropdown-trigger { - position: relative; - - span.clear { - cursor: pointer; - color: #555; - line-height: 1.5; - font-size: 0.9rem; - background-color: #fff; - padding: 0 2px; - right: 0.75rem; - top: 50%; - transform: translateY(-50%); - } -} diff --git a/frontend/app/styles/components/sy-durationpicker-day.scss b/frontend/app/styles/components/sy-durationpicker-day.scss deleted file mode 100644 index fd1c1228f..000000000 --- a/frontend/app/styles/components/sy-durationpicker-day.scss +++ /dev/null @@ -1,18 +0,0 @@ -.extendend-durationpicker-day { - display: flex; - justify-content: space-between; - align-items: center; - - * { - flex: 0 0 1.25rem; - } - - input { - width: 100%; - flex: 1 0 70%; - } - - :nth-child(2) { - margin-left: 0.25rem; - } -} diff --git a/frontend/app/styles/components/sy-modal.scss b/frontend/app/styles/components/sy-modal.scss deleted file mode 100644 index f7336e914..000000000 --- a/frontend/app/styles/components/sy-modal.scss +++ /dev/null @@ -1,17 +0,0 @@ -#sy-modals > * { - overflow-x: hidden; - - > .form-group:last-child { - margin-bottom: 0; - } -} - -.modal-footer { - .btn:not(:last-of-type) { - margin-right: 0.7rem; - } -} - -.modal-overlay { - transition: none; -} diff --git a/frontend/app/styles/components/sy-toggle.scss b/frontend/app/styles/components/sy-toggle.scss deleted file mode 100644 index 52fc6921d..000000000 --- a/frontend/app/styles/components/sy-toggle.scss +++ /dev/null @@ -1,26 +0,0 @@ -@use "sass:color"; - -.sy-toggle { - display: flex; - align-items: center; - cursor: pointer; - margin: auto; - - &.active { - color: color.adjust($color-primary, $lightness: -10%); - } - - &.inactive { - color: $color-secondary; - } - - &.form-control { - background-color: unset; - border: unset; - box-shadow: unset; - } -} - -.form-list-cell > .margin-small-right { - margin-right: 0.5rem; -} diff --git a/frontend/app/styles/components/timed-clock.scss b/frontend/app/styles/components/timed-clock.scss deleted file mode 100644 index ad36357e9..000000000 --- a/frontend/app/styles/components/timed-clock.scss +++ /dev/null @@ -1,25 +0,0 @@ -.timed-clock { - --clock-size: 50px; - --clock-color: rgb(87 87 87); - --clock-color-secondary: rgb(217 83 79); - - width: var(--clock-size); - height: var(--clock-size); - - .circle { - fill: transparent; - stroke: var(--clock-color); - } - - .hour { - stroke: var(--clock-color); - } - - .minute { - stroke: var(--clock-color); - } - - .second { - stroke: var(--clock-color-secondary); - } -} diff --git a/frontend/app/styles/components/tracking-bar.scss b/frontend/app/styles/components/tracking-bar.scss deleted file mode 100644 index 550836b2c..000000000 --- a/frontend/app/styles/components/tracking-bar.scss +++ /dev/null @@ -1,36 +0,0 @@ -.tracking-bar { - background: white; - border-bottom: 1px solid rgb(220 220 220); - padding-bottom: 1.5rem; - margin-bottom: 1.5rem; - - @media #{$lg-viewport} { - #task-form { - display: flex; - flex-direction: row; - - .form-group { - margin-bottom: 0; - } - - .form-group:not(:last-child) { - margin-right: 0.5rem; - flex-grow: 2; - } - - .form-group:nth-last-child(2) { - flex-grow: 3; - } - } - - .form-control { - width: 100%; - } - } - - @media #{$xs-viewport} { - .form-control { - padding-right: 35px; - } - } -} diff --git a/frontend/app/styles/components/weekly-overview-benchmark.scss b/frontend/app/styles/components/weekly-overview-benchmark.scss deleted file mode 100644 index 4a4058f59..000000000 --- a/frontend/app/styles/components/weekly-overview-benchmark.scss +++ /dev/null @@ -1,39 +0,0 @@ -.weekly-overview-benchmark { - display: flex; - align-items: center; - position: absolute; - inset: 0; - - &.expected { - hr { - background-color: $color-primary; - } - - span { - color: $color-primary; - } - } - - hr { - margin: 0; - border: none; - height: 1px; - width: 100%; - background-color: transparentize($color-primary, 0.7); - position: absolute; - left: 0; - right: 0; - } - - span { - width: 30px; - font-family: $font-family-mono; - font-size: 12px; - text-align: right; - color: transparentize($color-primary, 0.7); - transform: translateY(50%); - position: absolute; - left: -35px; - right: 0; - } -} diff --git a/frontend/app/styles/components/weekly-overview-day.scss b/frontend/app/styles/components/weekly-overview-day.scss deleted file mode 100644 index 2c2b65d8c..000000000 --- a/frontend/app/styles/components/weekly-overview-day.scss +++ /dev/null @@ -1,74 +0,0 @@ -@use "sass:color"; - -.weekly-overview-day { - height: 0%; - width: 15px; - position: relative; - z-index: 1; - cursor: pointer; - transition: height 300ms ease; - - .bar { - background-color: rgb(150 150 150); - height: 100%; - width: 100%; - transition: background-color 300ms ease; - } - - .day { - position: absolute; - font-family: $font-family-mono; - font-size: 12px; - left: 50%; - bottom: -35px; - text-align: center; - transform: translateX(-50%); - color: rgb(150 150 150); - transition: color 300ms ease; - } - - &.weekend, - &.holiday { - .bar { - background-color: rgb(220 220 220); - } - - .day { - color: rgb(220 220 220); - } - } - - &.absence { - .bar { - background-color: $color-warning; - } - - .day { - color: $color-warning; - } - } - - &.active { - .bar { - background-color: $color-primary; - } - - .day { - color: $color-primary; - font-weight: bold; - padding: 0 5px 5px; - margin-bottom: -5px; - border-bottom: 2px solid $color-primary; - } - } - - &:hover { - .bar { - background-color: color.adjust($color-primary, $saturation: -30%); - } - - .day { - color: color.adjust($color-primary, $saturation: -30%); - } - } -} diff --git a/frontend/app/styles/components/weekly-overview.scss b/frontend/app/styles/components/weekly-overview.scss deleted file mode 100644 index ed027b94c..000000000 --- a/frontend/app/styles/components/weekly-overview.scss +++ /dev/null @@ -1,15 +0,0 @@ -.weekly-overview { - width: 100%; - padding: 20px 0 50px 50px; - overflow: hidden; - display: none; - display: flex; - - .weekly-overview-children { - flex-grow: 1; - position: relative; - display: flex; - justify-content: space-around; - align-items: flex-end; - } -} diff --git a/frontend/app/styles/components/welcome-modal.scss b/frontend/app/styles/components/welcome-modal.scss deleted file mode 100644 index 0c5fcd7bf..000000000 --- a/frontend/app/styles/components/welcome-modal.scss +++ /dev/null @@ -1,5 +0,0 @@ -.welcome-modal-body { - .logo { - max-width: 50%; - } -} diff --git a/frontend/app/styles/ember-power-select-custom.scss b/frontend/app/styles/ember-power-select-custom.scss deleted file mode 100644 index 6f8d72b1a..000000000 --- a/frontend/app/styles/ember-power-select-custom.scss +++ /dev/null @@ -1,137 +0,0 @@ -@import "ember-power-select"; - -.ember-power-select-dropdown { - min-width: 250px; -} - -.ember-power-select-options[role="listbox"] { - max-height: 425px; - position: relative; -} - -.ember-power-select-option:not( - .ember-power-select-option--no-matches-message, - .ember-power-select-option--loading-message - ) { - padding: 0; - line-height: 1; - - div { - padding: 0 8px; - line-height: 1.6; - - &.inactive { - background-color: rgb(230 230 230); - } - - .history { - display: inline-flex; - align-items: center; - - .fa { - padding-right: 0.5rem; - } - - .history-text { - display: inline-flex; - flex-direction: column; - - small { - font-size: 0.6rem; - margin: 0.2rem 0 -0.2rem; - } - } - } - } - - &[aria-current="true"] .inactive, - &[aria-selected="true"] .inactive { - background-color: transparent; - } - - &[aria-selected="true"] { - background-color: $color-primary; - color: rgb(255 255 255); - } - - &[aria-current="true"] { - background-color: opacify($color-primary, 0.6); - } -} - -.ember-power-select-placeholder, -.ember-power-select-selected-item, -.ember-power-select-option { - white-space: nowrap; - overflow-x: hidden; - text-overflow: ellipsis; -} - -.ember-power-select-placeholder, -.ember-power-select-selected-item { - margin: 0; - position: absolute; - top: 50%; - transform: translateY(-50%); -} - -.ember-power-select-trigger { - display: block; - overflow: hidden; - width: 100%; - min-height: 3rem; - padding: 0.3rem 0.5rem; - font-size: 1.2rem; - line-height: 1.5; - color: rgb(85 85 85); - background-color: rgb(255 255 255); - border: 1px solid rgb(204 204 204); - border-radius: $input-border-radius; - box-shadow: $input-box-shadow; - transition: border-color 0.15s, box-shadow 0.15s; - padding-right: 2rem; - - &:focus { - border-color: lighten($color-primary, 20%); - outline: 0; - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, - 0 0 8px opacify($color-primary, 0.6); - } - - &[aria-disabled="true"] { - .ember-power-select-status-icon { - background-color: rgb(238 238 238); - } - } - - .ember-power-select-clear-btn { - background-color: rgb(255 255 255); - padding: 0 2px; - right: 2rem; - top: 50%; - transform: translateY(-50%); - } - - .ember-power-select-status-icon { - background-color: rgb(255 255 255); - transform: none !important; - width: 2rem; - border: none; - height: calc(100% - 2px); - border-top-right-radius: $input-border-radius; - border-bottom-right-radius: $input-border-radius; - right: 0; - top: 1px; - background-image: url('data:image/svg+xml,'); - background-position: right 0.5rem center; - background-size: 22px; - background-repeat: no-repeat; - } -} - -@media #{$sm-viewport} { - .ember-power-select-trigger { - font-size: 0.9rem; - min-height: 2rem; - } -} diff --git a/frontend/app/styles/filter-sidebar.scss b/frontend/app/styles/filter-sidebar.scss deleted file mode 100644 index cce15776b..000000000 --- a/frontend/app/styles/filter-sidebar.scss +++ /dev/null @@ -1,132 +0,0 @@ -.filter-sidebar { - position: fixed; - top: 50px; - right: 0; - bottom: 0; - z-index: 999; - display: flex; - min-width: 300px; - max-width: 340px; - flex-direction: column; - background: rgb(255 255 255); - transform: translateX(100%); - transition: transform 300ms ease; -} - -.filter-sidebar--visible { - box-shadow: 0 0 10px rgb(0 0 0 / 20%); - transform: translateX(0); -} - -.filter-sidebar-content { - overflow-y: auto; - flex-grow: 1; -} - -.filter-sidebar-content - > .filter-sidebar-group:first-child - > .filter-sidebar-group-label { - border-top: none; -} - -.filter-sidebar-title { - padding: 1rem; - display: flex; - flex-shrink: 0; - justify-content: space-between; - border-bottom: 1px solid $color-border; - font-weight: 700; -} - -.filter-sidebar-toggle { - position: absolute; - left: 0; - top: 1rem; - transform: translateX(-100%); - border: none; - cursor: pointer; - background: transparent; - width: 6.5rem; - height: 4rem; - text-align: right; - color: rgb(255 255 255); - overflow: hidden; - padding: 0.5rem 0; - outline: none; -} - -.filter-sidebar-toggle-background, -.filter-sidebar-toggle-icon, -.filter-sidebar-toggle-text { - display: flex; - align-items: center; - justify-content: center; - position: absolute; - right: 0; - top: 0.5rem; - height: 3rem; -} - -.filter-sidebar-toggle-background { - width: 100%; - background-color: $color-primary; - box-shadow: 0 0 10px rgb(0 0 0 / 20%); - border-top-left-radius: 0.3rem; - border-bottom-left-radius: 0.3rem; - transform: translateX(3.5rem); - transition: transform 300ms ease; -} - -.filter-sidebar-toggle-icon { - width: 3rem; -} - -.filter-sidebar-toggle-icon > .fa { - font-size: 1.3rem; -} - -.filter-sidebar-toggle-icon-badge { - position: absolute; - top: 0.5rem; - right: 0.5rem; - font-size: 0.6rem; - font-weight: bold; - background-color: $color-success; - padding: 0.1rem 0.3rem; - border-radius: 50%; - box-shadow: 0 0 10px rgb(0 0 0 / 20%); -} - -.filter-sidebar-toggle-text { - flex-shrink: 1; - width: 3rem; - left: 0.75rem; - right: auto; - opacity: 0; - transform: translateX(3.5rem); - transition: transform 300ms ease, opacity 300ms ease; -} - -.filter-sidebar-toggle:hover > .filter-sidebar-toggle-background { - transform: translateX(0); -} - -.filter-sidebar-toggle:hover > .filter-sidebar-toggle-text { - transform: translateX(0); - opacity: 1; -} - -.filter-sidebar-overlay { - position: fixed; - inset: 50px 0 0; - background-color: rgb(0 0 0 / 20%); - opacity: 0; - pointer-events: none; - transition: opacity 300ms ease; -} - -.filter-sidebar-overlay--visible { - pointer-events: all; - opacity: 1; - z-index: 1; -} diff --git a/frontend/app/styles/form-list.scss b/frontend/app/styles/form-list.scss deleted file mode 100644 index f2de8342c..000000000 --- a/frontend/app/styles/form-list.scss +++ /dev/null @@ -1,122 +0,0 @@ -.form-list { - width: 100%; - display: flex; - flex-direction: column; - flex: 1 0 auto; - - .form-list-body, - .form-list-row { - display: flex; - } - - .form-list-body { - flex-direction: column; - } - - .form-list-row { - border-top: 1px solid $color-border; - flex: 1 0 100%; - flex-wrap: wrap; - padding: 0.5rem; - } - - .form-list-cell { - flex: 1 0 100%; - } - - .form-list-body > .form-list-row:nth-of-type(2n + 1) { - background-color: darken($body-background-color, 5%); - } - - /* Form list head, foot and caption are not allowed for mobile devices */ - .form-list-head, - .form-list-foot, - .form-list-caption { - display: none; - } -} - -@mixin form-list--inline { - display: table; - - .form-list-head { - display: table-header-group; - - .form-list-row:first-child > .form-list-cell { - border-top: 0; - } - - .form-list-row > .form-list-cell { - font-weight: 500; - text-align: left; - vertical-align: bottom; - border-bottom: 2px solid $color-border; - } - } - - .form-list-body { - display: table-row-group; - - .form-list-row:first-child > .form-list-cell { - border-top: 0; - } - } - - .form-list-foot { - display: table-footer-group; - } - - .form-list-row { - display: table-row; - } - - .form-list-cell { - display: table-cell; - padding: 0.5rem; - vertical-align: top; - border-top: 1px solid $color-border; - } - - .form-list-cell-flex { - display: flex; - } - - .form-list-caption { - display: table-caption; - caption-side: bottom; - } -} - -.form-list--inline { - @include form-list--inline; -} - -@media #{$xs-viewport} { - .form-list-xs--inline { - @include form-list--inline; - } -} - -@media #{$sm-viewport} { - .form-list-sm--inline { - @include form-list--inline; - } -} - -@media #{$md-viewport} { - .form-list-md--inline { - @include form-list--inline; - } -} - -@media #{$lg-viewport} { - .form-list-lg--inline { - @include form-list--inline; - } -} - -@media #{$xl-viewport} { - .form-list-xl--inline { - @include form-list--inline; - } -} diff --git a/frontend/app/styles/loader.scss b/frontend/app/styles/loader.scss deleted file mode 100644 index 08c69dad3..000000000 --- a/frontend/app/styles/loader.scss +++ /dev/null @@ -1,49 +0,0 @@ -.loader { - height: 2px; - width: 100%; - position: absolute; - top: 0; - right: 0; - left: 0; - z-index: 9999; - overflow: hidden; - background-color: #ddd; -} - -.loader::before { - display: block; - position: absolute; - content: ""; - left: -200px; - width: 200px; - height: 4px; - background-color: $color-primary; - animation: loading 2s linear infinite; -} - -@keyframes loading { - 0% { - left: -200px; - width: 30%; - } - - 50% { - width: 30%; - } - - 70% { - width: 70%; - } - - 80% { - left: 50%; - } - - 95% { - left: 120%; - } - - 100% { - left: 100%; - } -} diff --git a/frontend/app/styles/login.scss b/frontend/app/styles/login.scss deleted file mode 100644 index 305dacfa1..000000000 --- a/frontend/app/styles/login.scss +++ /dev/null @@ -1,18 +0,0 @@ -.login { - text-align: center; - - h1 { - margin-top: 0.8rem; - } - - .timed-clock { - margin: 0 auto 0.5rem; - } - - @media only screen and (width <= 768px) { - .btn-primary { - margin-left: 0.5rem; - margin-right: 0.5rem; - } - } -} diff --git a/frontend/app/styles/projects.scss b/frontend/app/styles/projects.scss deleted file mode 100644 index 86b399515..000000000 --- a/frontend/app/styles/projects.scss +++ /dev/null @@ -1,100 +0,0 @@ -.header { - display: flex; - border-bottom: 1px solid rgb(220 220 220); - padding-bottom: 1.5rem; - margin-bottom: 1.5rem; -} - -.header-item { - flex: 50%; - margin-right: 0.5rem; -} - -.header-left { - float: left; -} - -.header-right { - float: right; -} - -.task-form-container { - margin-top: 20px; -} - -.task-form-container-row { - display: flex; -} - -.task-form-container-column { - flex: 50%; -} - -.task-form-container-column:first-child { - margin-right: 20px; -} - -.task-table-container { - height: 400px; - margin-bottom: 20px; -} - -.table--projects tr.selected { - background-color: lighten($color-primary, 20%) !important; -} - -.table--projects tr.selected + tr td, -.table--projects tr.selected td { - border-color: lighten($color-primary, 20%) !important; -} - -// Table -.table--projects { - margin-bottom: 0; - table-layout: fixed; -} - -.table--projects > tbody > tr.pointer { - color: rgb(0 0 0); -} - -.table--projects > tbody > tr.pointer > td:last-child { - box-shadow: inset -2px 0 0 $color-primary; -} - -.table--projects > tbody > tr:first-of-type td { - border-top: none; -} - -.table--projects th { - position: sticky; - background-color: white; - top: 0; -} - -.table--projects > colgroup > col { - &.title { - width: 10%; - } - - &.reference { - width: 20%; - } - - &.duration { - width: 8%; - } - - &.archived { - width: 5%; - } -} - -.validation-error-icon { - margin: auto 0.5rem; - color: $color-warning; -} - -.archived-background-color { - background-color: $color-secondary; -} diff --git a/frontend/app/styles/reports.scss b/frontend/app/styles/reports.scss deleted file mode 100644 index 026f3ba1b..000000000 --- a/frontend/app/styles/reports.scss +++ /dev/null @@ -1,78 +0,0 @@ -.form-list--reports { - white-space: nowrap; - - .form-list-body > .form-list-row > .form-list-cell { - &.cell-duration, - &.cell-remaining-effort, - &.cell-review-billable-icons, - &.cell-review, - &.cell-buttons, - &.cell-not-billable { - flex-basis: 25%; - flex-grow: 0; - margin: 0; - } - - &.cell-review, - &.cell-review-billable-icons, - &.cell-remaining-effort { - padding-left: 1rem; - } - - &.cell-review-billable-icons { - display: flex; - justify-content: space-evenly; - - > .sy-toggle { - flex: 0 0 1.5rem; - } - } - - &.cell-buttons { - text-align: right; - flex-grow: 1; - - .btn { - display: inline-flex; - } - } - - &.cell-remaining-effort { - padding-left: 1rem; - } - } -} - -@media #{$lg-viewport} { - .form-list--reports { - @include form-list--inline; - - .form-list-body > .form-list-row > .form-list-cell { - &:nth-child(1), - &:nth-child(2), - &:nth-child(3) { - width: 15%; - } - - &:nth-child(4) { - width: auto; - } - - &.cell-review-billable-icons { - padding-left: 0.5rem; - } - - &.cell-duration { - width: 75px; - } - - &.cell-buttons { - width: 110px; - } - - &.cell-remaining-effort { - width: 100px; - } - } - } -} diff --git a/frontend/app/styles/statistics.scss b/frontend/app/styles/statistics.scss deleted file mode 100644 index 08d2646a0..000000000 --- a/frontend/app/styles/statistics.scss +++ /dev/null @@ -1,4 +0,0 @@ -.table--statistics td:last-child, -.table--statistics th:last-child { - width: 50%; -} diff --git a/frontend/app/styles/toolbar.scss b/frontend/app/styles/toolbar.scss deleted file mode 100644 index e142d20a4..000000000 --- a/frontend/app/styles/toolbar.scss +++ /dev/null @@ -1,15 +0,0 @@ -.toolbar { - display: flex; - flex-direction: row; -} - -.toolbar-content { - display: flex; - flex-grow: 1; - justify-content: flex-start; - margin-bottom: 1rem; -} - -.toolbar-content--right { - justify-content: flex-end; -} diff --git a/frontend/app/styles/tour.scss b/frontend/app/styles/tour.scss deleted file mode 100644 index 2793e802b..000000000 --- a/frontend/app/styles/tour.scss +++ /dev/null @@ -1,85 +0,0 @@ -div.hopscotch-bubble { - z-index: 99; // The dropdowns have 100 and we don't want to hide them - border: 1px solid $color-border; - border-color: lighten($color-primary, 20%); - box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset, - 0 0 8px opacify($color-primary, 0.6); - - .hopscotch-bubble-number { - display: none; - } - - .hopscotch-bubble-content { - margin: 0; - } - - .hopscotch-title, - .hopscotch-content { - color: $body-color; - } - - .hopscotch-title { - margin: 5px 0 0; - } - - .hopscotch-content { - margin: 10px 0; - padding: 0; - } - - .hopscotch-pagination { - display: none; - } - - .hopscotch-bubble-arrow-container { - pointer-events: none; - - &.up { - top: -17px; - - .hopscotch-bubble-arrow { - top: -16px; - } - - .hopscotch-bubble-arrow-border { - border-bottom-color: lighten($color-primary, 20%); - } - } - - &.down { - bottom: -35px; - - .hopscotch-bubble-arrow { - top: -19px; - } - - .hopscotch-bubble-arrow-border { - border-top-color: lighten($color-primary, 20%); - } - } - - &.left { - left: -17px; - - .hopscotch-bubble-arrow { - left: 2px; - } - - .hopscotch-bubble-arrow-border { - border-right-color: lighten($color-primary, 20%); - } - } - - &.right { - right: -35px; - - .hopscotch-bubble-arrow { - left: -2px; - } - - .hopscotch-bubble-arrow-border { - border-left-color: lighten($color-primary, 20%); - } - } - } -} diff --git a/frontend/app/styles/users-navigation.scss b/frontend/app/styles/users-navigation.scss deleted file mode 100644 index 54561435b..000000000 --- a/frontend/app/styles/users-navigation.scss +++ /dev/null @@ -1,49 +0,0 @@ -.user-navigation { - margin: 0 ($page-padding-h * -1); - border-bottom: 1px solid $color-border; - background-color: rgb(255 255 255); - box-shadow: 0 2px 6px rgb(0 0 0 / 10%); -} - -.user-navigation > ul { - list-style: none; - display: flex; - width: 100%; - justify-content: center; -} - -.user-navigation > ul > li { - flex: 1 0 auto; - display: flex; -} - -.user-navigation > ul > li > a { - flex-grow: 1; - text-align: center; - padding: 0.9rem 2rem; - color: rgb(180 180 180); - font-size: 1.1rem; -} - -.user-navigation > ul > li > a.active { - color: $color-primary; - box-shadow: inset 0 -2px 0 $color-primary; -} - -@media #{$md-viewport} { - .user-navigation > ul > li { - flex-grow: 0; - } -} - -@media #{$lg-viewport} { - .user-navigation { - margin: 0 ($page-padding-h * 1.25 * -1); - } -} - -@media #{$xl-viewport} { - .user-navigation { - margin: 0 ($page-padding-h * 1.5 * -1); - } -} diff --git a/frontend/app/styles/users.scss b/frontend/app/styles/users.scss deleted file mode 100644 index 6a861eabd..000000000 --- a/frontend/app/styles/users.scss +++ /dev/null @@ -1,262 +0,0 @@ -$user-header-padding-v: 0.5rem; -$user-header-padding-h: $page-padding-h; -$user-header-margin-top-extra: 0; - -.user-header { - display: flex; - flex-shrink: 0; - flex-direction: column; - position: relative; - margin: calc(#{$page-padding-v} * -1 + #{$user-header-margin-top-extra}) - calc(#{$page-padding-h} * -1) 0; - padding: $user-header-padding-v $user-header-padding-h; - background-color: rgb(240 240 240); - border-bottom: 1px solid $color-border; - - .nav-top--fixed + & { - $user-header-margin-top-extra: 51px !global; - } -} - -.user-content { - display: flex; - flex-grow: 1; - flex-shrink: 0; - flex-direction: column; - padding-top: $page-padding-v; - position: relative; - - .grid { - position: relative; - } - - .year-select { - position: absolute; - top: 0; - right: 0; - - select { - width: 6rem; - } - } - - h4 { - color: $body-color; - font-weight: 300; - line-height: 3rem; - } - - .card { - opacity: 0; - transform: translateY(50px); - animation: card-slide-up 250ms ease-out forwards; - - .empty { - margin: 2rem 0; - } - } - - @for $i from 0 to 10 { - .grid-cell:nth-of-type(#{$i}) .card { - animation-delay: calc(100ms * #{$i}); - } - } -} - -.user-general-info { - width: 100%; - - tr > td { - vertical-align: top; - padding: 0.25rem 0; - } - - tr > td:first-child { - font-weight: 500; - } - - tr > td:last-child { - text-align: right; - } -} - -/* General info */ -.user-header-info { - text-align: center; - - h1 { - display: inline-flex; - color: $body-color; - font-size: 3.5rem; - line-height: 3.5rem; - margin: 0; - position: relative; - flex-direction: column; - margin-top: 1rem; - } -} - -/* Loading */ - -.user-header-loading { - display: flex; - min-height: 370px; - justify-content: center; - align-items: center; -} - -/* Worktime balance */ -.user-header-worktime-balance-container { - display: flex; - justify-content: center; - flex-wrap: wrap; -} - -.user-header-worktime-balance-title { - font-size: 2rem; - flex: 1 1 100%; - font-weight: 300; - margin: 1.5rem 0; - text-transform: uppercase; - text-align: center; - color: darken($color-border, 20%); -} - -.user-header-worktime-balance { - width: 350px; - position: relative; - order: 2; -} - -.user-header-worktime-balance-last-valid-timesheet { - order: 0; -} - -.user-header-worktime-balance-today { - order: 1; -} - -.user-header-worktime-balance-last-valid-timesheet, -.user-header-worktime-balance-today { - text-align: center; - font-size: 2rem; - flex: 0 0 50%; - padding: 0 0 1rem; - - h2 { - font-size: 1.1rem; - font-weight: 300; - margin: 0; - text-transform: uppercase; - color: darken($color-border, 20%); - } -} - -/* Absence balance */ -.user-header-absence-balance-container { - display: flex; - flex-grow: 1; - flex-flow: row wrap; - justify-content: space-around; -} - -.user-header-absence-balance { - display: flex; - flex: 0 1 50%; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; -} - -@media #{$sm-viewport} { - .user-header-absence-balance { - flex-basis: 100px; - } - - .user-header-worktime-balance { - order: 1; - } - - .user-header-worktime-balance-title { - font-size: 1.1rem; - margin: 0.5rem 0; - } - - .user-header-worktime-balance-today { - order: 2; - } - - .user-header-worktime-balance-last-valid-timesheet, - .user-header-worktime-balance-today { - flex-basis: 120px; - padding: 2.5rem 0 0; - - h2 { - font-size: 1.1rem; - } - } -} - -@keyframes card-slide-up { - to { - opacity: 1; - transform: translateY(0); - } -} - -@media #{$md-viewport} { - .user-header-info { - h1 { - font-size: 3rem; - margin-top: 0; - } - } -} - -@media #{$lg-viewport} { - .user-header { - margin: calc( - #{$page-padding-v} * 1.25 * -1 + #{$user-header-margin-top-extra} - ) - calc(#{$page-padding-h} * 1.25 * -1) 0; - padding: calc(#{$user-header-padding-v} * 1.25) - calc(#{$user-header-padding-h} * 1.25); - } - - .user-content { - padding-top: $page-padding-v * 1.25; - - .year-select select { - width: 5rem; - } - - h4 { - line-height: 2rem; - } - } -} - -@media #{$xl-viewport} { - .user-header { - margin: calc( - #{$page-padding-v} * 1.5 * -1 + #{$user-header-margin-top-extra} - ) - calc(#{$page-padding-h} * 1.5 * -1) 0; - padding: calc(#{$user-header-padding-v} * 1.5) - calc(#{$user-header-padding-h} * 1.5); - } - - .user-content { - padding-top: $page-padding-v * 1.5; - } - - .user-header-absence-balance { - flex-basis: 120px; - } - - .user-header-worktime-balance-last-valid-timesheet, - .user-header-worktime-balance-today { - flex-basis: 200px; - } -} diff --git a/frontend/app/styles/utilities.css b/frontend/app/styles/utilities.css new file mode 100644 index 000000000..ccb0aa059 --- /dev/null +++ b/frontend/app/styles/utilities.css @@ -0,0 +1,11 @@ +.striped { + @apply [&:nth-child(even)]:bg-secondary-light/5 [&:nth-child(odd)]:bg-secondary-light/15; +} + +.total { + @apply border-b-4 border-double border-current font-medium; +} + +.pointer-events-all { + pointer-events: all; +} diff --git a/frontend/app/styles/variables.scss b/frontend/app/styles/variables.scss deleted file mode 100644 index 0d4615f54..000000000 --- a/frontend/app/styles/variables.scss +++ /dev/null @@ -1,41 +0,0 @@ -$xs-viewport: "only screen and (min-width: 480px)"; -$sm-viewport: "only screen and (min-width: 768px)"; -$md-viewport: "only screen and (min-width: 992px)"; -$lg-viewport: "only screen and (min-width: 1200px)"; -$xl-viewport: "only screen and (min-width: 1440px)"; -$nav-top-mobile-width: "only screen and (min-width: 768px)"; -$color-primary: rgb(91 142 219); -$color-secondary: rgb(162 155 150); -$color-tertiary: rgb(134 127 124); -$color-border: rgb(225 225 225); -$color-menu: rgb(246 246 246); -$color-modal: rgb(255 255 255); -$color-success: rgb(92 184 92); -$color-info: rgb(91 192 222); -$color-warning: rgb(240 173 78); -$color-danger: rgb(217 83 79); -$color-success-lighter: lighten($color-success, 20%); -$color-success-darker: darker($color-success, 5%); -$color-danger-lighter: lighten($color-danger, 20%); -$color-danger-darker: darken($color-danger, 5%); -$font-family-sans-serif: "TheSansLT", "Open Sans", sans-serif; -$font-family-serif: "Merriweather", "Times New Roman", serif; -$font-family-mono: menlo, monaco, consolas, "Courier New", monospace; -$font-family-base: $font-family-sans-serif; -$font-weight-base: 300; -$font-size-base: 16px; -$font-size-large: 1.25rem; -$font-size-small: 0.85rem; -$body-background-color: #fff; -$body-color: rgb(61 61 61); -$body-font-weight: $font-weight-base; -$body-font-family: $font-family-base; -$body-min-font-size: $font-size-base - 3px; -$body-max-font-size: $font-size-base + 2px; -$body-min-font-size-break: 420px; -$body-max-font-size-break: 1440px; -$button-border-radius: 4px; -$input-border-radius: 4px; -$input-box-shadow: 0 1px 1px rgb(0 0 0 / 7.5%) inset; -$page-padding-v: 1em; -$page-padding-h: 1.5em; diff --git a/frontend/app/tours/index/activities.js b/frontend/app/tours/index/activities.js index be66ac8f7..9e573506c 100644 --- a/frontend/app/tours/index/activities.js +++ b/frontend/app/tours/index/activities.js @@ -39,7 +39,7 @@ export default [ }, { id: "generatingTimesheet", - target: ".btn-toolbar .btn-success", + target: "#generate-timesheet", placement: "left", title: "Generating the timesheet", content: ` diff --git a/frontend/app/tours/index/attendances.js b/frontend/app/tours/index/attendances.js index 8d1a19920..96cbc85cd 100644 --- a/frontend/app/tours/index/attendances.js +++ b/frontend/app/tours/index/attendances.js @@ -1,7 +1,7 @@ export default [ { id: "addAttendance", - target: ".btn-toolbar .btn-success", + target: "#add-attendance", placement: "left", title: "Add attendance", content: ` diff --git a/frontend/app/tours/index/reports.js b/frontend/app/tours/index/reports.js index fcc2668ae..d687326f1 100644 --- a/frontend/app/tours/index/reports.js +++ b/frontend/app/tours/index/reports.js @@ -1,7 +1,7 @@ export default [ { id: "timesheet", - target: ".form-list-body", + target: ".reports", placement: "top", title: "Timesheet", content: ` @@ -31,7 +31,7 @@ export default [ }, { id: "newEntry", - target: ".form-list-row", + target: ".reports .report-row", placement: "bottom", title: "New entry", content: ` @@ -43,7 +43,7 @@ export default [ }, { id: "reschedule", - target: ".btn-toolbar .btn-success", + target: "#reschedule", placement: "left", title: "Reschedule", content: ` diff --git a/frontend/app/users/edit/controller.js b/frontend/app/users/edit/controller.js index 4ce1e2a1d..7d066b195 100644 --- a/frontend/app/users/edit/controller.js +++ b/frontend/app/users/edit/controller.js @@ -60,7 +60,7 @@ export default class UsersEditController extends Controller { }); return balance[0]; - }) + }), ); } } diff --git a/frontend/app/users/edit/credits/absence-credits/edit/template.hbs b/frontend/app/users/edit/credits/absence-credits/edit/template.hbs index d5cad23cd..b98812320 100644 --- a/frontend/app/users/edit/credits/absence-credits/edit/template.hbs +++ b/frontend/app/users/edit/credits/absence-credits/edit/template.hbs @@ -5,57 +5,76 @@ (and (not credit.isNew) (can "edit absence-credit")) ) }} -
    +
    -
    - -

    {{if credit.isNew "New" "Edit"}} - absence credit

    -
    -
    - -
    - {{#each this.absenceTypes.lastSuccessful.value as |type|}} - - {{/each}} -
    -
    - - - - - -
    - Cancel - {{#unless credit.isNew}} + + + +

    {{if credit.isNew "New" "Edit"}} + absence credit

    + + +
    + {{#each this.absenceTypes.lastSuccessful.value as |type|}} - {{/unless}} - + {{on "click" (fn fi.update type)}} + >{{type.name}} + {{/each}}
    +
    +
    + + +
    -
    - -
    + + + + + + Cancel +
    + {{#unless credit.isNew}} + + {{/unless}} + +
    +
    + +
    {{else}} @@ -65,4 +84,4 @@
    {{/if}} -{{/let}} +{{/let}} \ No newline at end of file diff --git a/frontend/app/users/edit/credits/index/controller.js b/frontend/app/users/edit/credits/index/controller.js index 8d95c6471..c75b1c00b 100644 --- a/frontend/app/users/edit/credits/index/controller.js +++ b/frontend/app/users/edit/credits/index/controller.js @@ -98,7 +98,7 @@ export default class UsersEditCredits extends Controller { if (this.can.can("edit absence-credit")) { yield this.router.transitionTo( "users.edit.credits.absence-credits.edit", - id + id, ); } } @@ -108,7 +108,7 @@ export default class UsersEditCredits extends Controller { if (this.can.can("edit overtime-credit")) { yield this.router.transitionTo( "users.edit.credits.overtime-credits.edit", - id + id, ); } } diff --git a/frontend/app/users/edit/credits/index/template.hbs b/frontend/app/users/edit/credits/index/template.hbs index 3fd270cad..00ad22a41 100644 --- a/frontend/app/users/edit/credits/index/template.hbs +++ b/frontend/app/users/edit/credits/index/template.hbs @@ -1,9 +1,9 @@ -
    -
    +
    +
    {{#if this.allowTransfer}} {{/if}} @@ -14,7 +14,7 @@