Skip to content

Commit

Permalink
Add date range form field
Browse files Browse the repository at this point in the history
  • Loading branch information
BurntimeX committed Nov 12, 2024
1 parent bc229c1 commit 6f873e4
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 0 deletions.
23 changes: 23 additions & 0 deletions com.woltlab.wcf/templates/shared_dateRangeFormField.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<input
type="{if $field->supportsTime()}datetime{else}date{/if}"
id="{$field->getPrefixedId()}_from"
name="{$field->getPrefixedId()}[from]"
value="{$field->getFromValue()}"
data-placeholder="{lang}wcf.date.period.start{/lang}"
{if !$field->getFieldClasses()|empty} class="{implode from=$field->getFieldClasses() item='class' glue=' '}{$class}{/implode}"{/if}
{if $field->isAutofocused()} autofocus{/if}
{if $field->isRequired()} required{/if}
{if $field->isImmutable()} disabled{/if}
{foreach from=$field->getFieldAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}
>
<input
type="{if $field->supportsTime()}datetime{else}date{/if}"
id="{$field->getPrefixedId()}_to"
name="{$field->getPrefixedId()}[to]"
value="{$field->getToValue()}"
data-placeholder="{lang}wcf.date.period.end{/lang}"
{if !$field->getFieldClasses()|empty} class="{implode from=$field->getFieldClasses() item='class' glue=' '}{$class}{/implode}"{/if}
{if $field->isRequired()} required{/if}
{if $field->isImmutable()} disabled{/if}
{foreach from=$field->getFieldAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}
>
43 changes: 43 additions & 0 deletions ts/WoltLabSuite/Core/Form/Builder/Field/DateRange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Data handler for a date range form builder field in an Ajax form.
*
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
import Field from "./Field";
import { FormBuilderData } from "../Data";
import DatePicker from "../../../Date/Picker";

class DateRange extends Field {
#fromField: HTMLElement | null;
#toField: HTMLElement | null;

constructor(fieldId: string) {
super(fieldId);

this.#fromField = document.getElementById(this._fieldId + "_from");
if (this.#fromField === null) {
throw new Error("Unknown field with id '" + this._fieldId + "'.");
}

this.#toField = document.getElementById(this._fieldId + "_to");
if (this.#toField === null) {
throw new Error("Unknown field with id '" + this._fieldId + "'.");
}
}

protected _getData(): FormBuilderData {
return {
[this._fieldId]: {
from: DatePicker.getValue(this.#fromField as HTMLInputElement),
to: DatePicker.getValue(this.#toField as HTMLInputElement),
},
};
}

protected _readField(): void {}
}

export = DateRange;

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php

namespace wcf\system\form\builder\field;

use wcf\system\form\builder\field\validation\FormFieldValidationError;

/**
* Implementation of a form field for a date range (with a time).
*
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
class DateRangeFormField extends AbstractFormField implements
IAttributeFormField,
IAutoFocusFormField,
ICssClassFormField,
IImmutableFormField,
INullableFormField
{
use TAttributeFormField;
use TAutoFocusFormField;
use TCssClassFormField;
use TImmutableFormField;
use TNullableFormField;

/**
* is `true` if not only the date, but also the time can be set
* @var bool
*/
protected $supportsTime = false;

/**
* @inheritDoc
*/
protected $javaScriptDataHandlerModule = 'WoltLabSuite/Core/Form/Builder/Field/DateRange';

/**
* @inheritDoc
*/
protected $templateName = 'shared_dateRangeFormField';

const DATE_FORMAT = 'Y-m-d';

const TIME_FORMAT = 'Y-m-d\TH:i:sP';

/**
* @inheritDoc
*/
public function getSaveValue()
{
if ($this->getValue() === null && $this->isNullable()) {
return null;
}

return $this->getFromValue() . ';' . $this->getToValue();
}

/**
* @inheritDoc
*/
public function readValue()
{
if (
$this->getDocument()->hasRequestData($this->getPrefixedId())
&& \is_array($this->getDocument()->getRequestData($this->getPrefixedId()))
) {
$this->value = $this->getDocument()->getRequestData($this->getPrefixedId());
}

return $this;
}

/**
* Sets if not only the date, but also the time can be set.
*/
public function supportTime($supportsTime = true): static
{
if ($this->value !== null) {
throw new \BadFunctionCallException(
"After a value has been set, time support cannot be changed for field '{$this->getId()}'."
);
}

$this->supportsTime = $supportsTime;

return $this;
}

/**
* Returns `true` if not only the date, but also the time can be set, and
* returns `false` otherwise.
*
* By default, the time cannot be set.
*/
public function supportsTime(): bool
{
return $this->supportsTime;
}

/**
* @inheritDoc
*/
public function validate()
{
if ($this->isRequired() && (!$this->getFromValue() || !$this->getToValue())) {
$this->addValidationError(new FormFieldValidationError('empty'));
}

if ($this->getFromValue()) {
$dateTime = \DateTime::createFromFormat(
$this->supportsTime() ? self::TIME_FORMAT : self::DATE_FORMAT,
$this->getFromValue()
);
if ($dateTime === false) {
$this->addValidationError(new FormFieldValidationError('invalid'));
}
}

if ($this->getToValue()) {
$dateTime = \DateTime::createFromFormat(
$this->supportsTime() ? self::TIME_FORMAT : self::DATE_FORMAT,
$this->getToValue()
);
if ($dateTime === false) {
$this->addValidationError(new FormFieldValidationError('invalid'));
}
}
}

/**
* @inheritDoc
*/
public function value($value)
{
$values = \explode(';', $value);
if (\count($values) !== 2) {
throw new \InvalidArgumentException(
"Given value does not match format for field '{$this->getId()}'."
);
}

$this->value = [
'from' => $values[0],
'to' => $values[1],
];

return $this;
}

public function getFromValue(): string
{
return $this->value['from'] ?? '';
}

public function getToValue(): string
{
return $this->value['to'] ?? '';
}
}

0 comments on commit 6f873e4

Please sign in to comment.