Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: define the date range of date questions #2521

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/-ember-caluma/mirage/scenarios/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export default function (server) {
label: "When?",
formIds: [form.id],
type: "DATE",
minDate: "2023-09-01",
maxDate: null,
hintText: null,
});
server.create("question", {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,63 @@
</div>
{{/if}}

{{#if (has-question-type f.model "date")}}
<div uk-grid class="uk-grid-small uk-child-width-1-2 uk-margin">
<div class="">
<label for="" class="uk-form-label">
{{t "caluma.form-builder.question.min-date"}}
</label>
<div class="uk-inline uk-width-1-1">
<a
class="uk-form-icon uk-form-icon-flip"
href="#"
{{uk-tooltip (t "caluma.form.delete")}}
{{on "click" this.clearMinDateCalendar}}
>
<UkIcon @icon="close" />
</a>
<EmberFlatpickr
@altFormat={{this.dateFormat}}
class="uk-input form-control input"
@date={{or (changeset-get f.model "minDate") null}}
@onChange={{fn this.onDateMinMaxChange "minDate"}}
@maxDate={{changeset-get f.model "maxDate"}}
@altInput={{true}}
@allowInput={{true}}
@locale={{this.locale}}
@onReady={{this.onMinDateReady}}
/>
</div>
</div>
<div class="">
<label for="" class="uk-form-label">
{{t "caluma.form-builder.question.max-date"}}
</label>
<div class="uk-inline uk-width-1-1">
<a
class="uk-form-icon uk-form-icon-flip"
href="#"
{{uk-tooltip (t "caluma.form.delete")}}
{{on "click" this.clearMaxDateCalendar}}
>
<UkIcon @icon="close" />
</a>
<EmberFlatpickr
@altFormat={{this.dateFormat}}
class="uk-input form-control input"
@date={{or (changeset-get f.model "maxDate") null}}
@onChange={{fn this.onDateMinMaxChange "maxDate"}}
@minDate={{changeset-get f.model "minDate"}}
@altInput={{true}}
@allowInput={{true}}
@locale={{this.locale}}
@onReady={{this.onMaxDateReady}}
/>
</div>
</div>
</div>
{{/if}}

{{#if (has-question-type f.model "choice" "multiple-choice")}}
<f.input
@name="options"
Expand Down
59 changes: 59 additions & 0 deletions packages/form-builder/addon/components/cfb-form-editor/question.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getOwner } from "@ember/application";
import { A } from "@ember/array";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
Expand All @@ -8,6 +9,7 @@ import { queryManager } from "ember-apollo-client";
import Changeset from "ember-changeset";
import lookupValidator from "ember-changeset-validations";
import { dropTask, restartableTask, task } from "ember-concurrency";
import { DateTime } from "luxon";

import { hasQuestionType } from "@projectcaluma/ember-core/helpers/has-question-type";
import slugify from "@projectcaluma/ember-core/utils/slugify";
Expand Down Expand Up @@ -81,6 +83,9 @@ export default class CfbFormEditorQuestion extends Component {

@tracked changeset;

@tracked minDateFlatpickrRef = null;
@tracked maxDateFlatpickrRef = null;

@restartableTask
*data() {
if (!this.args.slug) {
Expand Down Expand Up @@ -162,6 +167,36 @@ export default class CfbFormEditorQuestion extends Component {
});
}

get locale() {
return this.intl.primaryLocale.split("-")[0];
}

get config() {
return getOwner(this).resolveRegistration("config:environment");
}

get dateFormat() {
const {
FLATPICKR_DATE_FORMAT = {
de: "d.m.Y",
fr: "d.m.Y",
en: "m/d/Y",
},
FLATPICKR_DATE_FORMAT_DEFAULT = "m/d/Y",
} = this.config["ember-caluma"] || {};

return FLATPICKR_DATE_FORMAT[this.locale] ?? FLATPICKR_DATE_FORMAT_DEFAULT;
}

@action
onDateMinMaxChange(key, [date]) {
// Change Javascript date to ISO string if not null.
this.changeset.set(
key,
date ? DateTime.fromJSDate(date).toISODate() : null,
);
}

get possibleTypes() {
return Object.keys(TYPES).map((value) => ({
value,
Expand Down Expand Up @@ -281,6 +316,8 @@ export default class CfbFormEditorQuestion extends Component {
_getDateQuestionInput(changeset) {
return {
hintText: changeset.get("hintText"),
maxDate: changeset.get("maxDate"),
minDate: changeset.get("minDate"),
};
}

Expand Down Expand Up @@ -506,4 +543,26 @@ export default class CfbFormEditorQuestion extends Component {
updateRowForm(value, changeset) {
changeset.set("rowForm.slug", value.slug);
}

@action
onMinDateReady(_selectedDates, _dateStr, flatpickrRef) {
this.minDateFlatpickrRef = flatpickrRef;
}

@action
onMaxDateReady(_selectedDates, _dateStr, flatpickrRef) {
this.maxDateFlatpickrRef = flatpickrRef;
}

@action
clearMinDateCalendar(e) {
e.stopPropagation();
this.minDateFlatpickrRef.clear();
}

@action
clearMaxDateCalendar(e) {
e.stopPropagation();
this.maxDateFlatpickrRef.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ mutation SaveDateQuestion($input: SaveDateQuestionInput!) {
...QuestionInfo
... on DateQuestion {
hintText
minDate
maxDate
}
}
clientMutationId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ query FormEditorQuestion($slug: String!) {
}
... on DateQuestion {
hintText
minDate
maxDate
defaultAnswer {
id
dateValue: value
Expand Down
2 changes: 2 additions & 0 deletions packages/form-builder/translations/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ caluma:

min-value: "Minimaler Wert"
max-value: "Maximaler Wert"
min-date: "Mindestdatum"
max-date: "Maximales Datum"
min-length: "Minimale Länge"
max-length: "Maximale Länge"
rowForm: "Formular für Tabelleneinträge"
Expand Down
2 changes: 2 additions & 0 deletions packages/form-builder/translations/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ caluma:

min-value: "Minimum value"
max-value: "Maximum value"
min-date: "Minimum date"
max-date: "Maximum date"
min-length: "Minimum length"
max-length: "Maximum length"
rowForm: "Form to use for rows"
Expand Down
2 changes: 2 additions & 0 deletions packages/form-builder/translations/fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ caluma:

min-value: "Valeur minimale"
max-value: "Valeur maximale"
min-date: "Date minimale"
max-date: "Date maximale"
min-length: "Longueur minimale"
max-length: "Longueur maximale"
rowForm: "Formulaire pour les entrées de tableau"
Expand Down
2 changes: 2 additions & 0 deletions packages/form/addon/components/cf-field/input/date.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
@date={{or @field.answer.value null}}
@altFormat={{this.dateFormat}}
@altInput={{true}}
@maxDate={{this.maxDate}}
@minDate={{this.minDate}}
@allowInput={{true}}
@onChange={{this.onChange}}
@onReady={{this.onReady}}
Expand Down
8 changes: 8 additions & 0 deletions packages/form/addon/components/cf-field/input/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ export default class CfFieldInputDateComponent extends Component {

@tracked flatpickrRef = null;

get maxDate() {
return this.args.field?.question?.raw?.maxDate || null;
}

get minDate() {
return this.args.field?.question?.raw?.minDate || null;
}

get locale() {
return this.intl.primaryLocale.split("-")[0];
}
Expand Down
2 changes: 2 additions & 0 deletions packages/form/addon/gql/fragments/field.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ fragment SimpleQuestion on Question {
value
}
hintText
minDate
maxDate
}
... on StaticQuestion {
staticContent
Expand Down
8 changes: 6 additions & 2 deletions packages/form/tests/integration/components/cf-content-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ module("Integration | Component | cf-content", function (hooks) {
this.server.create("question", {
formIds: [form.id],
type: "DATE",
minDate: "2023-01-01",
maxDate: "2030-12-31",
}),
this.server.create("question", {
formIds: [form.id],
Expand Down Expand Up @@ -181,6 +183,8 @@ module("Integration | Component | cf-content", function (hooks) {
formIds: [form.id],
slug: "date-question",
type: "DATE",
minDate: "2023-01-01",
maxDate: null,
});
this.server.create("question", {
formIds: [form.id],
Expand Down Expand Up @@ -229,7 +233,7 @@ module("Integration | Component | cf-content", function (hooks) {
);
await setFlatpickrDate(
`[name="Document:${document.id}:Question:date-question"]`,
new Date(2019, 2, 25), // month is zero based
new Date(2023, 2, 25), // month is zero based
);

await triggerEvent(
Expand Down Expand Up @@ -272,7 +276,7 @@ module("Integration | Component | cf-content", function (hooks) {
},
{
slug: "date-question",
value: "2019-03-25",
value: "2023-03-25",
},
{
slug: "files-question",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,40 @@ module("Integration | Component | cf-field/input/date", function (hooks) {
.hasValue("25.03.2021");
assert.dom(".ember-flatpickr-input[type='hidden']").hasValue("2021-03-25");
});

test("the date accept min date and max date", async function (assert) {
this.value = null;
this.field = {
question: {
raw: {
minDate: "2023-01-01",
maxDate: "2024-01-01",
},
},
};

await render(
hbs`<CfField::Input::Date @field={{this.field}} @onSave={{fn (mut this.value)}} />`,
);

await setLocale("en-us");
await setFlatpickrDate("input", new Date(2023, 6, 10)); // month is zero based
assert.strictEqual(this.value, "2023-07-10");
assert
.dom(".ember-flatpickr-input:not([type='hidden'])")
.hasValue("07/10/2023");
assert.dom(".ember-flatpickr-input[type='hidden']").hasValue("2023-07-10");

// the date here is less then the min dafined date
await setFlatpickrDate("input", new Date(2022, 6, 10)); // month is zero based
assert.strictEqual(this.value, null);
assert.dom(".ember-flatpickr-input:not([type='hidden'])").hasValue("");
assert.dom(".ember-flatpickr-input[type='hidden']").hasValue("");

// the date here is more then the max defined date
await setFlatpickrDate("input", new Date(2024, 6, 10)); // month is zero based
assert.strictEqual(this.value, null);
assert.dom(".ember-flatpickr-input:not([type='hidden'])").hasValue("");
assert.dom(".ember-flatpickr-input[type='hidden']").hasValue("");
});
});
4 changes: 4 additions & 0 deletions packages/testing/addon/mirage-graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,8 @@ type DateQuestion implements Question & Node {
modifiedByGroup: String
slug: String!
label: String!
minDate: Date
maxDate: Date

"""
Required expression is only evaluated when question is not hidden.
Expand Down Expand Up @@ -2831,6 +2833,8 @@ input SaveDateQuestionInput {
isArchived: Boolean
hintText: String
clientMutationId: String
minDate: Date
maxDate: Date
}

type SaveDateQuestionPayload {
Expand Down
2 changes: 2 additions & 0 deletions packages/testing/addon/scenarios/distribution.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export function createBlueprint(server) {
label: "Deadline",
isRequired: "true",
formIds: [inquiryForm.id],
minDate: null,
maxDate: null,
type: "DATE",
});

Expand Down