Browse Source

Improve datetime editor. (#864)

* Improve datetime editor.

* Fix CSS
pull/866/head
Sebastian Stehle 4 years ago
committed by GitHub
parent
commit
23bace0599
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      frontend/.storybook/main.js
  2. 21
      frontend/.storybook/preview.js
  3. 21
      frontend/.storybook/tsconfig.json
  4. 11
      frontend/.storybook/typings.d.ts
  5. 58010
      frontend/package-lock.json
  6. 13
      frontend/package.json
  7. 59
      frontend/src/app/framework/angular/forms/editors/date-time-editor.component.html
  8. 87
      frontend/src/app/framework/angular/forms/editors/date-time-editor.component.scss
  9. 16
      frontend/src/app/framework/angular/forms/editors/date-time-editor.component.ts
  10. 71
      frontend/src/app/framework/angular/forms/editors/date-time-editor.stories.ts
  11. 4
      frontend/tsconfig.app.json

22
frontend/.storybook/main.js

@ -0,0 +1,22 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions"
],
"framework": "@storybook/angular",
"core": {
"builder": "@storybook/builder-webpack5"
}
}

21
frontend/.storybook/preview.js

@ -0,0 +1,21 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
export const parameters = {
actions: {
argTypesRegex: "^on[A-Z].*"
},
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
docs: {
inlineStories: true
},
}

21
frontend/.storybook/tsconfig.json

@ -0,0 +1,21 @@
{
"extends": "../tsconfig.app.json",
"compilerOptions": {
"types": [
"node"
],
"allowSyntheticDefaultImports": true
},
"exclude": [
"../src/test.ts",
"../src/**/*.spec.ts",
"../projects/**/*.spec.ts"
],
"include": [
"../src/**/*",
"../projects/**/*"
],
"files": [
"./typings.d.ts"
]
}

11
frontend/.storybook/typings.d.ts

@ -0,0 +1,11 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
declare module '*.md' {
const content: string;
export default content;
}

58010
frontend/package-lock.json

File diff suppressed because it is too large

13
frontend/package.json

@ -10,7 +10,9 @@
"start": "ng serve",
"test": "ng test",
"test:coverage": "ng test --no-watch --code-coverage --browsers=ChromeHeadlessNoSandbox",
"watch": "ng build --watch --configuration development"
"watch": "ng build --watch --configuration development",
"storybook": "start-storybook -p 6006",
"storybook-build": "build-storybook"
},
"private": true,
"dependencies": {
@ -78,6 +80,15 @@
"@angular/compiler-cli": "~13.1.0",
"@angular/elements": "^13.1.1",
"@babel/core": "^7.16.7",
"@compodoc/compodoc": "^1.1.19",
"@storybook/addon-actions": "^6.4.20",
"@storybook/addon-essentials": "^6.4.20",
"@storybook/addon-interactions": "^6.4.20",
"@storybook/addon-links": "^6.4.20",
"@storybook/angular": "^6.4.20",
"@storybook/builder-webpack5": "^6.4.20",
"@storybook/manager-webpack5": "^6.4.20",
"@storybook/testing-library": "^0.0.9",
"@types/codemirror": "0.0.108",
"@types/core-js": "2.5.5",
"@types/jasmine": "3.10.2",

59
frontend/src/app/framework/angular/forms/editors/date-time-editor.component.html

@ -1,37 +1,34 @@
<div class="d-flex" (sqxResizeCondition)="setCompact($event)" [sqxResizeMinWidth]="500" [sqxResizeMaxWidth]="0">
<div class="d-flex">
<div class="form-group me-1">
<div *ngIf="!isCompact && isDateTimeMode && shouldShowDateTimeModeButton">
<button type="button" class="btn btn-text-secondary btn-sm btn-time-mode" (click)="setLocalMode(false)" *ngIf="snapshot.isLocal">
{{ 'common.dateTimeEditor.local' | sqxTranslate }}
</button>
<button type="button" class="btn btn-text-secondary btn-sm btn-time-mode" (click)="setLocalMode(true)" *ngIf="!snapshot.isLocal">
{{ 'common.dateTimeEditor.utc' | sqxTranslate }}
</button>
</div>
<div class="input-group">
<input type="text" class="form-control form-date" [formControl]="dateControl" placeholder="{{ 'common.date' | sqxTranslate }}"
[class.form-date-only]="!isDateTimeMode"
[class.form-date-time-only]="!isCompact && isDateTimeMode && shouldShowDateTimeModeButton"
(blur)="callTouched()" maxlength="10" #dateInput>
<input type="text" class="form-control form-time" [formControl]="timeControl" placeholder="{{ 'common.time' | sqxTranslate }}" (blur)="callTouched()" *ngIf="isDateTimeMode">
</div>
<button type="button" class="btn btn-text-secondary btn-sm btn-clear" [class.hidden]="!hasValue"
[disabled]="snapshot.isDisabled" (click)="reset()" *ngIf="!hideClear">
<i class="icon-close"></i>
<div class="d-flex root" (sqxResized)="setSize($event)" [class.mini]="size === 'Mini'" [class.compact]="size === 'Compact'">
<div class="form-group flex-grow me-1">
<div *ngIf="isDateTimeMode && shouldShowDateTimeModeButton">
<button type="button" class="btn btn-text-secondary btn-sm btn-time-mode" (click)="setLocalMode(false)" *ngIf="snapshot.isLocal">
{{ 'common.dateTimeEditor.local' | sqxTranslate }}
</button>
</div>
<div class="form-group" *ngIf="isDateTimeMode && shouldShowDateButtons">
<button type="button" class="btn btn-text-secondary" [disabled]="snapshot.isDisabled" (click)="writeNow()" title="i18n:common.dateTimeEditor.nowTooltip">
{{ 'common.dateTimeEditor.now' | sqxTranslate }}
<button type="button" class="btn btn-text-secondary btn-sm btn-time-mode" (click)="setLocalMode(true)" *ngIf="!snapshot.isLocal">
{{ 'common.dateTimeEditor.utc' | sqxTranslate }}
</button>
</div>
<div class="form-group" *ngIf="!isDateTimeMode && shouldShowDateButtons">
<button type="button" class="btn btn-text-secondary" [disabled]="snapshot.isDisabled" (click)="writeToday()" title="i18n:common.dateTimeEditor.todayTooltip">
{{ 'common.dateTimeEditor.today' | sqxTranslate }}
</button>
<div class="input-group flex-grow">
<input type="text" class="form-control form-date" [formControl]="dateControl" placeholder="{{ 'common.date' | sqxTranslate }}"
[class.with-buttons]="isDateTimeMode && shouldShowDateTimeModeButton"
(blur)="callTouched()" maxlength="10" #dateInput>
<input type="text" class="form-control form-time" [formControl]="timeControl" placeholder="{{ 'common.time' | sqxTranslate }}" (blur)="callTouched()" *ngIf="isDateTimeMode">
</div>
<button type="button" class="btn btn-text-secondary btn-sm btn-clear" [class.hidden]="!hasValue"
[disabled]="snapshot.isDisabled" (click)="reset()" *ngIf="!hideClear">
<i class="icon-close"></i>
</button>
</div>
<div class="form-group" *ngIf="isDateTimeMode && shouldShowDateButtons">
<button type="button" class="btn btn-text-secondary btn-quick" [disabled]="snapshot.isDisabled" (click)="writeNow()" title="i18n:common.dateTimeEditor.nowTooltip">
{{ 'common.dateTimeEditor.now' | sqxTranslate }}
</button>
</div>
<div class="form-group" *ngIf="!isDateTimeMode && shouldShowDateButtons">
<button type="button" class="btn btn-text-secondary btn-quick" [disabled]="snapshot.isDisabled" (click)="writeToday()" title="i18n:common.dateTimeEditor.todayTooltip">
{{ 'common.dateTimeEditor.today' | sqxTranslate }}
</button>
</div>
</div>

87
frontend/src/app/framework/angular/forms/editors/date-time-editor.component.scss

@ -1,35 +1,75 @@
@import 'mixins';
@import 'vars';
.root {
max-width: 400px;
}
.flex-grow {
flex-grow: 1;
}
.form-group {
position: relative;
}
.input-group {
.form-control {
&:last-child {
padding-left: .75rem;
padding-right: 2rem;
position: relative;
}
.form-time {
width: 45%;
}
.form-date {
width: 55%;
&.with-buttons {
padding-left: 3.3rem;
}
}
.form-control {
&:last-child {
padding-left: .75rem;
padding-right: 2rem;
position: relative;
}
}
.btn {
&-clear {
@include absolute(auto, 4px, 3px, auto);
z-index: 100;
}
&-time-mode {
@include absolute(1px, auto, -1px, auto);
z-index: 100;
}
&:focus {
box-shadow: none;
}
}
.compact {
.btn-time-mode {
display: none;
}
.form-date {
width: 8.5rem;
padding-left: .75rem;
}
}
.form-date-only {
width: 8.5rem;
.mini {
.btn-time-mode {
display: none;
}
.form-date-time-only {
padding-left: 3.3rem;
padding-right: .75rem;
width: 11rem;
.btn-quick {
display: none;
}
.form-time {
width: 7rem;
.form-date {
padding-left: .75rem;
}
}
@ -44,19 +84,4 @@
}
}
}
}
.btn {
&-clear {
@include absolute(auto, 4px, 3px, auto);
}
&-time-mode {
@include absolute(1px, auto, -1px, auto);
z-index: 1000;
}
&:focus {
box-shadow: none;
}
}

16
frontend/src/app/framework/angular/forms/editors/date-time-editor.component.ts

@ -59,7 +59,7 @@ export class DateTimeEditorComponent extends StatefulControlComponent<State, str
public hideDateTimeModeButton?: boolean | null;
@Input()
public isCompact?: boolean | null;
public size: 'Normal' | 'Compact' | 'Mini' = 'Normal';
@Input()
public set disabled(value: boolean | undefined | null) {
@ -69,8 +69,8 @@ export class DateTimeEditorComponent extends StatefulControlComponent<State, str
@ViewChild('dateInput', { static: false })
public dateInput!: ElementRef<HTMLInputElement>;
public timeControl = new FormControl();
public dateControl = new FormControl();
public readonly timeControl = new FormControl();
public readonly dateControl = new FormControl();
public get shouldShowDateButtons() {
return !this.hideDateButtonsSettings && !this.hideDateButtons;
@ -252,8 +252,14 @@ export class DateTimeEditorComponent extends StatefulControlComponent<State, str
this.updateControls();
}
public setCompact(isCompact: boolean) {
this.isCompact = isCompact;
public setSize(size: DOMRect) {
if (size.width < 300) {
this.size = 'Mini';
} else if (size.width < 350) {
this.size = 'Compact';
} else {
this.size = 'Normal';
}
}
}

71
frontend/src/app/framework/angular/forms/editors/date-time-editor.stories.ts

@ -0,0 +1,71 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { moduleMetadata } from '@storybook/angular';
import { Meta, Story } from '@storybook/angular/types-6-0';
import { LocalizerService, SqxFrameworkModule, UIOptions } from '@app/framework';
import { DateTimeEditorComponent } from './date-time-editor.component';
const translations = {
'common.date': 'Date',
'common.dateTimeEditor.local': 'Local',
'common.dateTimeEditor.now': 'Now',
'common.dateTimeEditor.today': 'Today',
'common.dateTimeEditor.utc': 'UTC',
'common.time': 'Time',
};
export default {
title: 'Framework/DateTimeEditor',
component: DateTimeEditorComponent,
argTypes: {
hideClear: {
control: 'boolean',
},
hideDateButtons: {
control: 'boolean',
},
hideDateTimeModeButton: {
control: 'boolean',
},
mode: {
control: 'radio',
options: [
'Date',
'DateTime',
],
},
},
decorators: [
moduleMetadata({
imports: [
SqxFrameworkModule,
SqxFrameworkModule.forRoot(),
],
providers: [
{ provide: LocalizerService, useFactory: () => new LocalizerService(translations) },
{ provide: UIOptions, useFactory: () => new UIOptions({}) },
],
}),
],
} as Meta;
const Template: Story<DateTimeEditorComponent> = (args: DateTimeEditorComponent) => ({
props: args,
});
export const Date = Template.bind({});
Date.args = {
mode: 'Date',
};
export const DateTime = Template.bind({});
DateTime.args = {
mode: 'DateTime',
};

4
frontend/tsconfig.app.json

@ -1,4 +1,3 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
@ -11,5 +10,8 @@
],
"include": [
"src/**/*.d.ts"
],
"exclude": [
"**/*.stories.*"
]
}

Loading…
Cancel
Save