mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-12-18 16:15:43 +00:00
Merge branch 'ticket-app-master' into 1849-1848-1920-1921-fix-bugs
This commit is contained in:
@@ -11,7 +11,6 @@
|
|||||||
"@hotwired/stimulus": "^3.0.0",
|
"@hotwired/stimulus": "^3.0.0",
|
||||||
"@luminateone/eslint-baseline": "^1.0.9",
|
"@luminateone/eslint-baseline": "^1.0.9",
|
||||||
"@symfony/stimulus-bridge": "^3.2.0",
|
"@symfony/stimulus-bridge": "^3.2.0",
|
||||||
"@symfony/ux-translator": "file:vendor/symfony/ux-translator/assets",
|
|
||||||
"@symfony/webpack-encore": "^4.1.0",
|
"@symfony/webpack-encore": "^4.1.0",
|
||||||
"@tsconfig/node20": "^20.1.4",
|
"@tsconfig/node20": "^20.1.4",
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
|
|||||||
@@ -1,103 +1,98 @@
|
|||||||
<template>
|
<template>
|
||||||
<teleport to="#social-issues-acc">
|
<teleport to="#social-issues-acc">
|
||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<label :class="socialIssuesClassList">{{
|
<label :class="socialIssuesClassList">{{
|
||||||
trans(ACTIVITY_SOCIAL_ISSUES)
|
trans(ACTIVITY_SOCIAL_ISSUES)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<check-social-issue
|
<check-social-issue
|
||||||
v-for="issue in socialIssuesList"
|
v-for="issue in socialIssuesList"
|
||||||
:key="issue.id"
|
:key="issue.id"
|
||||||
:issue="issue"
|
:issue="issue"
|
||||||
:selection="socialIssuesSelected"
|
:selection="socialIssuesSelected"
|
||||||
@updateSelected="updateIssuesSelected"
|
@updateSelected="updateIssuesSelected"
|
||||||
>
|
>
|
||||||
</check-social-issue>
|
</check-social-issue>
|
||||||
|
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<VueMultiselect
|
<VueMultiselect
|
||||||
name="otherIssues"
|
name="otherIssues"
|
||||||
label="text"
|
label="text"
|
||||||
track-by="id"
|
track-by="id"
|
||||||
open-direction="bottom"
|
open-direction="bottom"
|
||||||
:close-on-select="true"
|
:close-on-select="true"
|
||||||
:preserve-search="false"
|
:preserve-search="false"
|
||||||
:reset-after="true"
|
:reset-after="true"
|
||||||
:hide-selected="true"
|
:hide-selected="true"
|
||||||
:taggable="false"
|
:taggable="false"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:searchable="true"
|
:searchable="true"
|
||||||
:allow-empty="true"
|
:allow-empty="true"
|
||||||
:show-labels="false"
|
:show-labels="false"
|
||||||
:loading="issueIsLoading"
|
:loading="issueIsLoading"
|
||||||
:placeholder="trans(ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE)"
|
:placeholder="trans(ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE)"
|
||||||
:options="socialIssuesOther"
|
:options="socialIssuesOther"
|
||||||
@select="addIssueInList"
|
@select="addIssueInList"
|
||||||
>
|
>
|
||||||
</VueMultiselect>
|
</VueMultiselect>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 row">
|
||||||
|
<div class="col-4">
|
||||||
|
<label :class="socialActionsClassList">{{
|
||||||
|
trans(ACTIVITY_SOCIAL_ACTIONS)
|
||||||
|
}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<div v-if="actionIsLoading === true">
|
||||||
|
<i class="chill-green fa fa-circle-o-notch fa-spin fa-lg"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3 row">
|
<span
|
||||||
<div class="col-4">
|
v-else-if="socialIssuesSelected.length === 0"
|
||||||
<label :class="socialActionsClassList">{{
|
class="inline-choice chill-no-data-statement mt-3"
|
||||||
trans(ACTIVITY_SOCIAL_ACTIONS)
|
>
|
||||||
}}</label>
|
{{ trans(ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE) }}
|
||||||
</div>
|
</span>
|
||||||
<div class="col-8">
|
|
||||||
<div v-if="actionIsLoading === true">
|
|
||||||
<i
|
|
||||||
class="chill-green fa fa-circle-o-notch fa-spin fa-lg"
|
|
||||||
></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span
|
<template
|
||||||
v-else-if="socialIssuesSelected.length === 0"
|
v-else-if="
|
||||||
class="inline-choice chill-no-data-statement mt-3"
|
socialActionsList.length > 0 &&
|
||||||
>
|
(socialIssuesSelected.length || socialActionsSelected.length)
|
||||||
{{ trans(ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE) }}
|
"
|
||||||
</span>
|
>
|
||||||
|
<div
|
||||||
|
id="actionsList"
|
||||||
|
v-for="group in socialActionsList"
|
||||||
|
:key="group.issue"
|
||||||
|
>
|
||||||
|
<span class="badge bg-chill-l-gray text-dark">{{
|
||||||
|
group.issue
|
||||||
|
}}</span>
|
||||||
|
<check-social-action
|
||||||
|
v-for="action in group.actions"
|
||||||
|
:key="action.id"
|
||||||
|
:action="action"
|
||||||
|
:selection="socialActionsSelected"
|
||||||
|
@updateSelected="updateActionsSelected"
|
||||||
|
>
|
||||||
|
</check-social-action>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template
|
<span
|
||||||
v-else-if="
|
v-else-if="actionAreLoaded && socialActionsList.length === 0"
|
||||||
socialActionsList.length > 0 &&
|
class="inline-choice chill-no-data-statement mt-3"
|
||||||
(socialIssuesSelected.length ||
|
>
|
||||||
socialActionsSelected.length)
|
{{ trans(ACTIVITY_SOCIAL_ACTION_LIST_EMPTY) }}
|
||||||
"
|
</span>
|
||||||
>
|
</div>
|
||||||
<div
|
</div>
|
||||||
id="actionsList"
|
</teleport>
|
||||||
v-for="group in socialActionsList"
|
|
||||||
:key="group.issue"
|
|
||||||
>
|
|
||||||
<span class="badge bg-chill-l-gray text-dark">{{
|
|
||||||
group.issue
|
|
||||||
}}</span>
|
|
||||||
<check-social-action
|
|
||||||
v-for="action in group.actions"
|
|
||||||
:key="action.id"
|
|
||||||
:action="action"
|
|
||||||
:selection="socialActionsSelected"
|
|
||||||
@updateSelected="updateActionsSelected"
|
|
||||||
>
|
|
||||||
</check-social-action>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-else-if="
|
|
||||||
actionAreLoaded && socialActionsList.length === 0
|
|
||||||
"
|
|
||||||
class="inline-choice chill-no-data-statement mt-3"
|
|
||||||
>
|
|
||||||
{{ trans(ACTIVITY_SOCIAL_ACTION_LIST_EMPTY) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</teleport>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -106,175 +101,174 @@ import CheckSocialIssue from "./SocialIssuesAcc/CheckSocialIssue.vue";
|
|||||||
import CheckSocialAction from "./SocialIssuesAcc/CheckSocialAction.vue";
|
import CheckSocialAction from "./SocialIssuesAcc/CheckSocialAction.vue";
|
||||||
import { getSocialIssues, getSocialActionByIssue } from "../api.js";
|
import { getSocialIssues, getSocialActionByIssue } from "../api.js";
|
||||||
import {
|
import {
|
||||||
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
||||||
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE,
|
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE,
|
||||||
ACTIVITY_SOCIAL_ACTIONS,
|
ACTIVITY_SOCIAL_ACTIONS,
|
||||||
ACTIVITY_SOCIAL_ISSUES,
|
ACTIVITY_SOCIAL_ISSUES,
|
||||||
ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE,
|
ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE,
|
||||||
trans,
|
trans,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "SocialIssuesAcc",
|
name: "SocialIssuesAcc",
|
||||||
components: {
|
components: {
|
||||||
CheckSocialIssue,
|
CheckSocialIssue,
|
||||||
CheckSocialAction,
|
CheckSocialAction,
|
||||||
VueMultiselect,
|
VueMultiselect,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
trans,
|
||||||
|
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
||||||
|
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE,
|
||||||
|
ACTIVITY_SOCIAL_ACTIONS,
|
||||||
|
ACTIVITY_SOCIAL_ISSUES,
|
||||||
|
ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
issueIsLoading: false,
|
||||||
|
actionIsLoading: false,
|
||||||
|
actionAreLoaded: false,
|
||||||
|
socialIssuesClassList: {
|
||||||
|
"col-form-label": true,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
socialActionsClassList: {
|
||||||
|
"col-form-label": true,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
socialIssuesList() {
|
||||||
|
return this.$store.state.activity.accompanyingPeriod.socialIssues;
|
||||||
},
|
},
|
||||||
setup() {
|
socialIssuesSelected() {
|
||||||
return {
|
return this.$store.state.activity.socialIssues;
|
||||||
trans,
|
|
||||||
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
|
||||||
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE,
|
|
||||||
ACTIVITY_SOCIAL_ACTIONS,
|
|
||||||
ACTIVITY_SOCIAL_ISSUES,
|
|
||||||
ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
data() {
|
socialIssuesOther() {
|
||||||
return {
|
return this.$store.state.socialIssuesOther;
|
||||||
issueIsLoading: false,
|
|
||||||
actionIsLoading: false,
|
|
||||||
actionAreLoaded: false,
|
|
||||||
socialIssuesClassList: {
|
|
||||||
"col-form-label": true,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
socialActionsClassList: {
|
|
||||||
"col-form-label": true,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
computed: {
|
socialActionsList() {
|
||||||
socialIssuesList() {
|
return this.$store.getters.socialActionsListSorted;
|
||||||
return this.$store.state.activity.accompanyingPeriod.socialIssues;
|
|
||||||
},
|
|
||||||
socialIssuesSelected() {
|
|
||||||
return this.$store.state.activity.socialIssues;
|
|
||||||
},
|
|
||||||
socialIssuesOther() {
|
|
||||||
return this.$store.state.socialIssuesOther;
|
|
||||||
},
|
|
||||||
socialActionsList() {
|
|
||||||
return this.$store.getters.socialActionsListSorted;
|
|
||||||
},
|
|
||||||
socialActionsSelected() {
|
|
||||||
return this.$store.state.activity.socialActions;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
mounted() {
|
socialActionsSelected() {
|
||||||
/* Load classNames after element is present */
|
return this.$store.state.activity.socialActions;
|
||||||
const socialActionsEl = document.querySelector(
|
},
|
||||||
"input#chill_activitybundle_activity_socialActions",
|
},
|
||||||
);
|
mounted() {
|
||||||
if (socialActionsEl && socialActionsEl.hasAttribute("required")) {
|
/* Load classNames after element is present */
|
||||||
this.socialActionsClassList.required = true;
|
const socialActionsEl = document.querySelector(
|
||||||
|
"input#chill_activitybundle_activity_socialActions",
|
||||||
|
);
|
||||||
|
if (socialActionsEl && socialActionsEl.hasAttribute("required")) {
|
||||||
|
this.socialActionsClassList.required = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const socialIssuesEl = document.querySelector(
|
||||||
|
"input#chill_activitybundle_activity_socialIssues",
|
||||||
|
);
|
||||||
|
if (socialIssuesEl && socialIssuesEl.hasAttribute("required")) {
|
||||||
|
this.socialIssuesClassList.required = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load other issues in multiselect */
|
||||||
|
this.issueIsLoading = true;
|
||||||
|
this.actionAreLoaded = false;
|
||||||
|
|
||||||
|
getSocialIssues().then((response) => {
|
||||||
|
/* Add issues to the store */
|
||||||
|
this.$store.commit("updateIssuesOther", response);
|
||||||
|
|
||||||
|
/* Add in list the issues already associated (if not yet listed) */
|
||||||
|
this.socialIssuesSelected.forEach((issue) => {
|
||||||
|
if (
|
||||||
|
this.socialIssuesList.filter((i) => i.id === issue.id).length !== 1
|
||||||
|
) {
|
||||||
|
this.$store.commit("addIssueInList", issue);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const socialIssuesEl = document.querySelector(
|
/* Remove from multiselect the issues that are not yet in the checkbox list */
|
||||||
"input#chill_activitybundle_activity_socialIssues",
|
this.socialIssuesList.forEach((issue) => {
|
||||||
);
|
this.$store.commit("removeIssueInOther", issue);
|
||||||
if (socialIssuesEl && socialIssuesEl.hasAttribute("required")) {
|
});
|
||||||
this.socialIssuesClassList.required = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load other issues in multiselect */
|
/* Filter issues */
|
||||||
this.issueIsLoading = true;
|
this.$store.commit("filterList", "issues");
|
||||||
this.actionAreLoaded = false;
|
|
||||||
|
|
||||||
getSocialIssues().then((response) => {
|
/* Add in list the actions already associated (if not yet listed) */
|
||||||
/* Add issues to the store */
|
this.socialActionsSelected.forEach((action) => {
|
||||||
this.$store.commit("updateIssuesOther", response);
|
this.$store.commit("addActionInList", action);
|
||||||
|
});
|
||||||
|
|
||||||
/* Add in list the issues already associated (if not yet listed) */
|
/* Filter actions */
|
||||||
this.socialIssuesSelected.forEach((issue) => {
|
this.$store.commit("filterList", "actions");
|
||||||
if (
|
|
||||||
this.socialIssuesList.filter((i) => i.id === issue.id)
|
|
||||||
.length !== 1
|
|
||||||
) {
|
|
||||||
this.$store.commit("addIssueInList", issue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Remove from multiselect the issues that are not yet in the checkbox list */
|
this.issueIsLoading = false;
|
||||||
this.socialIssuesList.forEach((issue) => {
|
this.actionAreLoaded = true;
|
||||||
this.$store.commit("removeIssueInOther", issue);
|
this.updateActionsList();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
/* Filter issues */
|
methods: {
|
||||||
this.$store.commit("filterList", "issues");
|
/* When choosing an issue in multiselect, add it in checkboxes (as selected),
|
||||||
|
|
||||||
/* Add in list the actions already associated (if not yet listed) */
|
|
||||||
this.socialActionsSelected.forEach((action) => {
|
|
||||||
this.$store.commit("addActionInList", action);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Filter actions */
|
|
||||||
this.$store.commit("filterList", "actions");
|
|
||||||
|
|
||||||
this.issueIsLoading = false;
|
|
||||||
this.actionAreLoaded = true;
|
|
||||||
this.updateActionsList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
/* When choosing an issue in multiselect, add it in checkboxes (as selected),
|
|
||||||
remove it from multiselect, and add socialActions concerned
|
remove it from multiselect, and add socialActions concerned
|
||||||
*/
|
*/
|
||||||
addIssueInList(value) {
|
addIssueInList(value) {
|
||||||
//console.log('addIssueInList', value);
|
//console.log('addIssueInList', value);
|
||||||
this.$store.commit("addIssueInList", value);
|
this.$store.commit("addIssueInList", value);
|
||||||
this.$store.commit("removeIssueInOther", value);
|
this.$store.commit("removeIssueInOther", value);
|
||||||
this.$store.dispatch("addIssueSelected", value);
|
this.$store.dispatch("addIssueSelected", value);
|
||||||
this.updateActionsList();
|
this.updateActionsList();
|
||||||
},
|
},
|
||||||
/* Update value for selected issues checkboxes
|
/* Update value for selected issues checkboxes
|
||||||
*/
|
*/
|
||||||
updateIssuesSelected(issues) {
|
updateIssuesSelected(issues) {
|
||||||
//console.log('updateIssuesSelected', issues);
|
//console.log('updateIssuesSelected', issues);
|
||||||
this.$store.dispatch("updateIssuesSelected", issues);
|
this.$store.dispatch("updateIssuesSelected", issues);
|
||||||
this.updateActionsList();
|
this.updateActionsList();
|
||||||
},
|
},
|
||||||
/* Update value for selected actions checkboxes
|
/* Update value for selected actions checkboxes
|
||||||
*/
|
*/
|
||||||
updateActionsSelected(actions) {
|
updateActionsSelected(actions) {
|
||||||
//console.log('updateActionsSelected', actions);
|
//console.log('updateActionsSelected', actions);
|
||||||
this.$store.dispatch("updateActionsSelected", actions);
|
this.$store.dispatch("updateActionsSelected", actions);
|
||||||
},
|
},
|
||||||
/* Add socialActions concerned: after reset, loop on each issue selected
|
/* Add socialActions concerned: after reset, loop on each issue selected
|
||||||
to get social actions concerned
|
to get social actions concerned
|
||||||
*/
|
*/
|
||||||
updateActionsList() {
|
updateActionsList() {
|
||||||
this.resetActionsList();
|
this.resetActionsList();
|
||||||
this.socialIssuesSelected.forEach((item) => {
|
this.socialIssuesSelected.forEach((item) => {
|
||||||
this.actionIsLoading = true;
|
this.actionIsLoading = true;
|
||||||
getSocialActionByIssue(item.id).then(
|
getSocialActionByIssue(item.id).then(
|
||||||
(actions) =>
|
(actions) =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
actions.results.forEach((action) => {
|
actions.results.forEach((action) => {
|
||||||
this.$store.commit("addActionInList", action);
|
this.$store.commit("addActionInList", action);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.$store.commit("filterList", "actions");
|
this.$store.commit("filterList", "actions");
|
||||||
|
|
||||||
this.actionIsLoading = false;
|
this.actionIsLoading = false;
|
||||||
this.actionAreLoaded = true;
|
this.actionAreLoaded = true;
|
||||||
resolve();
|
resolve();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}, this);
|
}, this);
|
||||||
},
|
|
||||||
/* Reset socialActions List: flush list and restore selected actions
|
|
||||||
*/
|
|
||||||
resetActionsList() {
|
|
||||||
this.$store.commit("resetActionsList");
|
|
||||||
this.actionAreLoaded = false;
|
|
||||||
this.socialActionsSelected.forEach((item) => {
|
|
||||||
this.$store.commit("addActionInList", item);
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
/* Reset socialActions List: flush list and restore selected actions
|
||||||
|
*/
|
||||||
|
resetActionsList() {
|
||||||
|
this.$store.commit("resetActionsList");
|
||||||
|
this.actionAreLoaded = false;
|
||||||
|
this.socialActionsSelected.forEach((item) => {
|
||||||
|
this.$store.commit("addActionInList", item);
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -284,18 +278,18 @@ export default {
|
|||||||
@import "ChillMainAssets/chill/scss/chill_variables";
|
@import "ChillMainAssets/chill/scss/chill_variables";
|
||||||
|
|
||||||
span.multiselect__single {
|
span.multiselect__single {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#actionsList {
|
#actionsList {
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
background-color: whitesmoke;
|
background-color: whitesmoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.badge {
|
span.badge {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
@include badge_social($social-issue-color);
|
@include badge_social($social-issue-color);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -44,20 +44,21 @@ span.badge {
|
|||||||
@include badge_social($social-action-color);
|
@include badge_social($social-action-color);
|
||||||
font-size: 95%;
|
font-size: 95%;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 100%;margin-bottom: 5px;
|
max-width: 100%;
|
||||||
|
margin-bottom: 5px;
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 11px;
|
left: 11px;
|
||||||
top: 0;
|
top: 0;
|
||||||
margin: 0 0.3em 0 -0.75em;
|
margin: 0 0.3em 0 -0.75em;
|
||||||
}
|
}
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 1.5em;
|
padding-left: 1.5em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -42,19 +42,21 @@ span.badge {
|
|||||||
@include badge_social($social-issue-color);
|
@include badge_social($social-issue-color);
|
||||||
font-size: 95%;
|
font-size: 95%;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 100%;margin-bottom: 5px;
|
max-width: 100%;
|
||||||
margin-right: 1em;text-align: left;
|
margin-bottom: 5px;
|
||||||
|
margin-right: 1em;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 11px;
|
left: 11px;
|
||||||
top: 0;
|
top: 0;
|
||||||
margin: 0 0.3em 0 -0.75em;
|
margin: 0 0.3em 0 -0.75em;
|
||||||
}
|
}
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 1.5em;
|
padding-left: 1.5em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,166 +1,148 @@
|
|||||||
<template>
|
<template>
|
||||||
<teleport to="#mainUser">
|
<teleport to="#mainUser">
|
||||||
<h2 class="chill-red">Utilisateur principal</h2>
|
<h2 class="chill-red">Utilisateur principal</h2>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="null !== this.$store.getters.getMainUser">
|
<div v-if="null !== this.$store.getters.getMainUser">
|
||||||
<calendar-active :user="this.$store.getters.getMainUser" />
|
<calendar-active :user="this.$store.getters.getMainUser" />
|
||||||
</div>
|
|
||||||
<pick-entity
|
|
||||||
:multiple="false"
|
|
||||||
:types="['user']"
|
|
||||||
:uniqid="'main_user_calendar'"
|
|
||||||
:picked="
|
|
||||||
null !== this.$store.getters.getMainUser
|
|
||||||
? [this.$store.getters.getMainUser]
|
|
||||||
: []
|
|
||||||
"
|
|
||||||
:removable-if-set="false"
|
|
||||||
:display-picked="false"
|
|
||||||
:suggested="this.suggestedUsers"
|
|
||||||
:label="'main_user'"
|
|
||||||
@add-new-entity="setMainUser"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</teleport>
|
<pick-entity
|
||||||
|
:multiple="false"
|
||||||
|
:types="['user']"
|
||||||
|
:uniqid="'main_user_calendar'"
|
||||||
|
:picked="
|
||||||
|
null !== this.$store.getters.getMainUser
|
||||||
|
? [this.$store.getters.getMainUser]
|
||||||
|
: []
|
||||||
|
"
|
||||||
|
:removable-if-set="false"
|
||||||
|
:display-picked="false"
|
||||||
|
:suggested="this.suggestedUsers"
|
||||||
|
:label="'main_user'"
|
||||||
|
@add-new-entity="setMainUser"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</teleport>
|
||||||
|
|
||||||
<concerned-groups />
|
<concerned-groups />
|
||||||
|
|
||||||
<teleport to="#schedule">
|
<teleport to="#schedule">
|
||||||
<div class="row mb-3" v-if="activity.startDate !== null">
|
<div class="row mb-3" v-if="activity.startDate !== null">
|
||||||
<label class="col-form-label col-sm-4">Date</label>
|
<label class="col-form-label col-sm-4">Date</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
{{ $d(activity.startDate, "long") }} -
|
{{ $d(activity.startDate, "long") }} -
|
||||||
{{ $d(activity.endDate, "hoursOnly") }}
|
{{ $d(activity.endDate, "hoursOnly") }}
|
||||||
<span v-if="activity.calendarRange === null"
|
<span v-if="activity.calendarRange === null"
|
||||||
>(Pas de plage de disponibilité sélectionnée)</span
|
>(Pas de plage de disponibilité sélectionnée)</span
|
||||||
>
|
|
||||||
<span v-else>(Une plage de disponibilité sélectionnée)</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</teleport>
|
|
||||||
|
|
||||||
<location />
|
|
||||||
|
|
||||||
<teleport to="#fullCalendar">
|
|
||||||
<div class="calendar-actives">
|
|
||||||
<template v-for="u in getActiveUsers" :key="u.id">
|
|
||||||
<calendar-active
|
|
||||||
:user="u"
|
|
||||||
:invite="this.$store.getters.getInviteForUser(u)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="display-options row justify-content-between"
|
|
||||||
style="margin-top: 1rem"
|
|
||||||
>
|
>
|
||||||
<div class="col-sm-9 col-xs-12">
|
<span v-else>(Une plage de disponibilité sélectionnée)</span>
|
||||||
<div class="input-group mb-3">
|
</div>
|
||||||
<label class="input-group-text" for="slotDuration"
|
</div>
|
||||||
>Durée des créneaux</label
|
</teleport>
|
||||||
>
|
|
||||||
<select
|
<location />
|
||||||
v-model="slotDuration"
|
|
||||||
id="slotDuration"
|
<teleport to="#fullCalendar">
|
||||||
class="form-select"
|
<div class="calendar-actives">
|
||||||
>
|
<template v-for="u in getActiveUsers" :key="u.id">
|
||||||
<option value="00:05:00">5 minutes</option>
|
<calendar-active
|
||||||
<option value="00:10:00">10 minutes</option>
|
:user="u"
|
||||||
<option value="00:15:00">15 minutes</option>
|
:invite="this.$store.getters.getInviteForUser(u)"
|
||||||
<option value="00:30:00">30 minutes</option>
|
/>
|
||||||
<option value="00:45:00">45 minutes</option>
|
</template>
|
||||||
<option value="00:60:00">60 minutes</option>
|
</div>
|
||||||
</select>
|
<div
|
||||||
<label class="input-group-text" for="slotMinTime">De</label>
|
class="display-options row justify-content-between"
|
||||||
<select
|
style="margin-top: 1rem"
|
||||||
v-model="slotMinTime"
|
>
|
||||||
id="slotMinTime"
|
<div class="col-sm-9 col-xs-12">
|
||||||
class="form-select"
|
<div class="input-group mb-3">
|
||||||
>
|
<label class="input-group-text" for="slotDuration"
|
||||||
<option value="00:00:00">0h</option>
|
>Durée des créneaux</label
|
||||||
<option value="01:00:00">1h</option>
|
>
|
||||||
<option value="02:00:00">2h</option>
|
<select v-model="slotDuration" id="slotDuration" class="form-select">
|
||||||
<option value="03:00:00">3h</option>
|
<option value="00:05:00">5 minutes</option>
|
||||||
<option value="04:00:00">4h</option>
|
<option value="00:10:00">10 minutes</option>
|
||||||
<option value="05:00:00">5h</option>
|
<option value="00:15:00">15 minutes</option>
|
||||||
<option value="06:00:00">6h</option>
|
<option value="00:30:00">30 minutes</option>
|
||||||
<option value="07:00:00">7h</option>
|
<option value="00:45:00">45 minutes</option>
|
||||||
<option value="08:00:00">8h</option>
|
<option value="00:60:00">60 minutes</option>
|
||||||
<option value="09:00:00">9h</option>
|
</select>
|
||||||
<option value="10:00:00">10h</option>
|
<label class="input-group-text" for="slotMinTime">De</label>
|
||||||
<option value="11:00:00">11h</option>
|
<select v-model="slotMinTime" id="slotMinTime" class="form-select">
|
||||||
<option value="12:00:00">12h</option>
|
<option value="00:00:00">0h</option>
|
||||||
</select>
|
<option value="01:00:00">1h</option>
|
||||||
<label class="input-group-text" for="slotMaxTime">À</label>
|
<option value="02:00:00">2h</option>
|
||||||
<select
|
<option value="03:00:00">3h</option>
|
||||||
v-model="slotMaxTime"
|
<option value="04:00:00">4h</option>
|
||||||
id="slotMaxTime"
|
<option value="05:00:00">5h</option>
|
||||||
class="form-select"
|
<option value="06:00:00">6h</option>
|
||||||
>
|
<option value="07:00:00">7h</option>
|
||||||
<option value="12:00:00">12h</option>
|
<option value="08:00:00">8h</option>
|
||||||
<option value="13:00:00">13h</option>
|
<option value="09:00:00">9h</option>
|
||||||
<option value="14:00:00">14h</option>
|
<option value="10:00:00">10h</option>
|
||||||
<option value="15:00:00">15h</option>
|
<option value="11:00:00">11h</option>
|
||||||
<option value="16:00:00">16h</option>
|
<option value="12:00:00">12h</option>
|
||||||
<option value="17:00:00">17h</option>
|
</select>
|
||||||
<option value="18:00:00">18h</option>
|
<label class="input-group-text" for="slotMaxTime">À</label>
|
||||||
<option value="19:00:00">19h</option>
|
<select v-model="slotMaxTime" id="slotMaxTime" class="form-select">
|
||||||
<option value="20:00:00">20h</option>
|
<option value="12:00:00">12h</option>
|
||||||
<option value="21:00:00">21h</option>
|
<option value="13:00:00">13h</option>
|
||||||
<option value="22:00:00">22h</option>
|
<option value="14:00:00">14h</option>
|
||||||
<option value="23:00:00">23h</option>
|
<option value="15:00:00">15h</option>
|
||||||
<option value="23:59:59">24h</option>
|
<option value="16:00:00">16h</option>
|
||||||
</select>
|
<option value="17:00:00">17h</option>
|
||||||
</div>
|
<option value="18:00:00">18h</option>
|
||||||
</div>
|
<option value="19:00:00">19h</option>
|
||||||
<div class="col-sm-3 col-xs-12">
|
<option value="20:00:00">20h</option>
|
||||||
<div class="float-end">
|
<option value="21:00:00">21h</option>
|
||||||
<div class="form-check input-group">
|
<option value="22:00:00">22h</option>
|
||||||
<span class="input-group-text">
|
<option value="23:00:00">23h</option>
|
||||||
<input
|
<option value="23:59:59">24h</option>
|
||||||
id="showHideWE"
|
</select>
|
||||||
class="mt-0"
|
|
||||||
type="checkbox"
|
|
||||||
v-model="hideWeekends"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<label
|
|
||||||
for="showHideWE"
|
|
||||||
class="form-check-label input-group-text"
|
|
||||||
>Week-ends</label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<FullCalendar ref="fullCalendar" :options="calendarOptions">
|
</div>
|
||||||
<template #eventContent="arg">
|
<div class="col-sm-3 col-xs-12">
|
||||||
<span>
|
<div class="float-end">
|
||||||
<b v-if="arg.event.extendedProps.is === 'remote'">{{
|
<div class="form-check input-group">
|
||||||
arg.event.title
|
<span class="input-group-text">
|
||||||
}}</b>
|
<input
|
||||||
<b v-else-if="arg.event.extendedProps.is === 'range'"
|
id="showHideWE"
|
||||||
>{{ arg.timeText }}
|
class="mt-0"
|
||||||
{{ arg.event.extendedProps.locationName }}
|
type="checkbox"
|
||||||
<small>{{
|
v-model="hideWeekends"
|
||||||
arg.event.extendedProps.userLabel
|
/>
|
||||||
}}</small></b
|
</span>
|
||||||
>
|
<label for="showHideWE" class="form-check-label input-group-text"
|
||||||
<b v-else-if="arg.event.extendedProps.is === 'current'"
|
>Week-ends</label
|
||||||
>{{ arg.timeText }} {{ $t("current_selected") }}
|
>
|
||||||
</b>
|
</div>
|
||||||
<b v-else-if="arg.event.extendedProps.is === 'local'">{{
|
</div>
|
||||||
arg.event.title
|
</div>
|
||||||
}}</b>
|
</div>
|
||||||
<b v-else
|
<FullCalendar ref="fullCalendar" :options="calendarOptions">
|
||||||
>{{ arg.timeText }} {{ $t("current_selected") }}
|
<template #eventContent="arg">
|
||||||
</b>
|
<span>
|
||||||
</span>
|
<b v-if="arg.event.extendedProps.is === 'remote'">{{
|
||||||
</template>
|
arg.event.title
|
||||||
</FullCalendar>
|
}}</b>
|
||||||
</teleport>
|
<b v-else-if="arg.event.extendedProps.is === 'range'"
|
||||||
|
>{{ arg.timeText }}
|
||||||
|
{{ arg.event.extendedProps.locationName }}
|
||||||
|
<small>{{ arg.event.extendedProps.userLabel }}</small></b
|
||||||
|
>
|
||||||
|
<b v-else-if="arg.event.extendedProps.is === 'current'"
|
||||||
|
>{{ arg.timeText }} {{ $t("current_selected") }}
|
||||||
|
</b>
|
||||||
|
<b v-else-if="arg.event.extendedProps.is === 'local'">{{
|
||||||
|
arg.event.title
|
||||||
|
}}</b>
|
||||||
|
<b v-else>{{ arg.timeText }} {{ $t("current_selected") }} </b>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</FullCalendar>
|
||||||
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -177,219 +159,210 @@ import PickEntity from "ChillMainAssets/vuejs/PickEntity/PickEntity.vue";
|
|||||||
import { mapGetters, mapState } from "vuex";
|
import { mapGetters, mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
ConcernedGroups,
|
ConcernedGroups,
|
||||||
Location,
|
Location,
|
||||||
FullCalendar,
|
FullCalendar,
|
||||||
CalendarActive,
|
CalendarActive,
|
||||||
PickEntity,
|
PickEntity,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
errorMsg: [],
|
||||||
|
showMyCalendar: false,
|
||||||
|
slotDuration: "00:05:00",
|
||||||
|
slotMinTime: "09:00:00",
|
||||||
|
slotMaxTime: "18:00:00",
|
||||||
|
hideWeekEnds: true,
|
||||||
|
previousUser: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(["getMainUser"]),
|
||||||
|
...mapState(["activity"]),
|
||||||
|
events() {
|
||||||
|
return this.$store.getters.getEventSources;
|
||||||
},
|
},
|
||||||
data() {
|
calendarOptions() {
|
||||||
return {
|
return {
|
||||||
errorMsg: [],
|
locale: frLocale,
|
||||||
showMyCalendar: false,
|
plugins: [
|
||||||
slotDuration: "00:05:00",
|
dayGridPlugin,
|
||||||
slotMinTime: "09:00:00",
|
interactionPlugin,
|
||||||
slotMaxTime: "18:00:00",
|
timeGridPlugin,
|
||||||
hideWeekEnds: true,
|
dayGridPlugin,
|
||||||
previousUser: [],
|
listPlugin,
|
||||||
};
|
],
|
||||||
|
initialView: "timeGridWeek",
|
||||||
|
initialDate: this.$store.getters.getInitialDate,
|
||||||
|
eventSources: this.events,
|
||||||
|
selectable: true,
|
||||||
|
slotMinTime: this.slotMinTime,
|
||||||
|
slotMaxTime: this.slotMaxTime,
|
||||||
|
scrollTimeReset: false,
|
||||||
|
datesSet: this.onDatesSet,
|
||||||
|
select: this.onDateSelect,
|
||||||
|
eventChange: this.onEventChange,
|
||||||
|
eventClick: this.onEventClick,
|
||||||
|
selectMirror: true,
|
||||||
|
editable: true,
|
||||||
|
weekends: !this.hideWeekEnds,
|
||||||
|
headerToolbar: {
|
||||||
|
left: "prev,next today",
|
||||||
|
center: "title",
|
||||||
|
right: "timeGridWeek,timeGridDay,listWeek",
|
||||||
|
},
|
||||||
|
views: {
|
||||||
|
timeGrid: {
|
||||||
|
slotEventOverlap: false,
|
||||||
|
slotDuration: this.slotDuration,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
getActiveUsers() {
|
||||||
...mapGetters(["getMainUser"]),
|
const users = [];
|
||||||
...mapState(["activity"]),
|
for (const id of this.$store.state.currentView.users.keys()) {
|
||||||
events() {
|
users.push(this.$store.getters.getUserDataById(id).user);
|
||||||
return this.$store.getters.getEventSources;
|
}
|
||||||
},
|
return users;
|
||||||
calendarOptions() {
|
|
||||||
return {
|
|
||||||
locale: frLocale,
|
|
||||||
plugins: [
|
|
||||||
dayGridPlugin,
|
|
||||||
interactionPlugin,
|
|
||||||
timeGridPlugin,
|
|
||||||
dayGridPlugin,
|
|
||||||
listPlugin,
|
|
||||||
],
|
|
||||||
initialView: "timeGridWeek",
|
|
||||||
initialDate: this.$store.getters.getInitialDate,
|
|
||||||
eventSources: this.events,
|
|
||||||
selectable: true,
|
|
||||||
slotMinTime: this.slotMinTime,
|
|
||||||
slotMaxTime: this.slotMaxTime,
|
|
||||||
scrollTimeReset: false,
|
|
||||||
datesSet: this.onDatesSet,
|
|
||||||
select: this.onDateSelect,
|
|
||||||
eventChange: this.onEventChange,
|
|
||||||
eventClick: this.onEventClick,
|
|
||||||
selectMirror: true,
|
|
||||||
editable: true,
|
|
||||||
weekends: !this.hideWeekEnds,
|
|
||||||
headerToolbar: {
|
|
||||||
left: "prev,next today",
|
|
||||||
center: "title",
|
|
||||||
right: "timeGridWeek,timeGridDay,listWeek",
|
|
||||||
},
|
|
||||||
views: {
|
|
||||||
timeGrid: {
|
|
||||||
slotEventOverlap: false,
|
|
||||||
slotDuration: this.slotDuration,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getActiveUsers() {
|
|
||||||
const users = [];
|
|
||||||
for (const id of this.$store.state.currentView.users.keys()) {
|
|
||||||
users.push(this.$store.getters.getUserDataById(id).user);
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
},
|
|
||||||
suggestedUsers() {
|
|
||||||
const suggested = [];
|
|
||||||
|
|
||||||
this.$data.previousUser.forEach((u) => {
|
|
||||||
if (u.id !== this.$store.getters.getMainUser.id) {
|
|
||||||
suggested.push(u);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return suggested;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
suggestedUsers() {
|
||||||
setMainUser({ entity }) {
|
const suggested = [];
|
||||||
const user = entity;
|
|
||||||
console.log("setMainUser APP", entity);
|
|
||||||
|
|
||||||
if (
|
this.$data.previousUser.forEach((u) => {
|
||||||
user.id !== this.$store.getters.getMainUser &&
|
if (u.id !== this.$store.getters.getMainUser.id) {
|
||||||
(this.$store.state.activity.calendarRange !== null ||
|
suggested.push(u);
|
||||||
this.$store.state.activity.startDate !== null ||
|
}
|
||||||
this.$store.state.activity.endDate !== null)
|
});
|
||||||
) {
|
|
||||||
if (
|
|
||||||
!window.confirm(
|
|
||||||
this.$t("change_main_user_will_reset_event_data"),
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the previous user, if any, in the previous user list (in use for suggestion)
|
return suggested;
|
||||||
if (null !== this.$store.getters.getMainUser) {
|
|
||||||
const suggestedUids = new Set(
|
|
||||||
this.$data.previousUser.map((u) => u.id),
|
|
||||||
);
|
|
||||||
if (!suggestedUids.has(this.$store.getters.getMainUser.id)) {
|
|
||||||
this.$data.previousUser.push(
|
|
||||||
this.$store.getters.getMainUser,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$store.dispatch("setMainUser", user);
|
|
||||||
this.$store.commit("showUserOnCalendar", {
|
|
||||||
user,
|
|
||||||
ranges: true,
|
|
||||||
remotes: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
removeMainUser(user) {
|
|
||||||
console.log("removeMainUser APP", user);
|
|
||||||
|
|
||||||
window.alert(this.$t("main_user_is_mandatory"));
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
onDatesSet(event) {
|
|
||||||
console.log("onDatesSet", event);
|
|
||||||
this.$store.dispatch("setCurrentDatesView", {
|
|
||||||
start: event.start,
|
|
||||||
end: event.end,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onDateSelect(payload) {
|
|
||||||
console.log("onDateSelect", payload);
|
|
||||||
|
|
||||||
// show an alert if changing mainUser
|
|
||||||
if (
|
|
||||||
(this.$store.getters.getMainUser !== null &&
|
|
||||||
this.$store.state.me.id !==
|
|
||||||
this.$store.getters.getMainUser.id) ||
|
|
||||||
this.$store.getters.getMainUser === null
|
|
||||||
) {
|
|
||||||
if (!window.confirm(this.$t("will_change_main_user_for_me"))) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.$store.commit("showUserOnCalendar", {
|
|
||||||
user: this.$store.state.me,
|
|
||||||
remotes: true,
|
|
||||||
ranges: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$store.dispatch("setEventTimes", {
|
|
||||||
start: payload.start,
|
|
||||||
end: payload.end,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onEventChange(payload) {
|
|
||||||
console.log("onEventChange", payload);
|
|
||||||
if (this.$store.state.activity.calendarRange !== null) {
|
|
||||||
throw new Error(
|
|
||||||
"not allowed to edit a calendar associated with a calendar range",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.$store.dispatch("setEventTimes", {
|
|
||||||
start: payload.event.start,
|
|
||||||
end: payload.event.end,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onEventClick(payload) {
|
|
||||||
if (payload.event.extendedProps.is !== "range") {
|
|
||||||
// do nothing when clicking on remote
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// show an alert if changing mainUser
|
|
||||||
if (
|
|
||||||
this.$store.getters.getMainUser !== null &&
|
|
||||||
payload.event.extendedProps.userId !==
|
|
||||||
this.$store.getters.getMainUser.id
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
!window.confirm(
|
|
||||||
this.$t("this_calendar_range_will_change_main_user"),
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$store.dispatch("associateCalendarToRange", {
|
|
||||||
range: payload.event,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setMainUser({ entity }) {
|
||||||
|
const user = entity;
|
||||||
|
console.log("setMainUser APP", entity);
|
||||||
|
|
||||||
|
if (
|
||||||
|
user.id !== this.$store.getters.getMainUser &&
|
||||||
|
(this.$store.state.activity.calendarRange !== null ||
|
||||||
|
this.$store.state.activity.startDate !== null ||
|
||||||
|
this.$store.state.activity.endDate !== null)
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!window.confirm(this.$t("change_main_user_will_reset_event_data"))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the previous user, if any, in the previous user list (in use for suggestion)
|
||||||
|
if (null !== this.$store.getters.getMainUser) {
|
||||||
|
const suggestedUids = new Set(this.$data.previousUser.map((u) => u.id));
|
||||||
|
if (!suggestedUids.has(this.$store.getters.getMainUser.id)) {
|
||||||
|
this.$data.previousUser.push(this.$store.getters.getMainUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$store.dispatch("setMainUser", user);
|
||||||
|
this.$store.commit("showUserOnCalendar", {
|
||||||
|
user,
|
||||||
|
ranges: true,
|
||||||
|
remotes: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeMainUser(user) {
|
||||||
|
console.log("removeMainUser APP", user);
|
||||||
|
|
||||||
|
window.alert(this.$t("main_user_is_mandatory"));
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
onDatesSet(event) {
|
||||||
|
console.log("onDatesSet", event);
|
||||||
|
this.$store.dispatch("setCurrentDatesView", {
|
||||||
|
start: event.start,
|
||||||
|
end: event.end,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onDateSelect(payload) {
|
||||||
|
console.log("onDateSelect", payload);
|
||||||
|
|
||||||
|
// show an alert if changing mainUser
|
||||||
|
if (
|
||||||
|
(this.$store.getters.getMainUser !== null &&
|
||||||
|
this.$store.state.me.id !== this.$store.getters.getMainUser.id) ||
|
||||||
|
this.$store.getters.getMainUser === null
|
||||||
|
) {
|
||||||
|
if (!window.confirm(this.$t("will_change_main_user_for_me"))) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.$store.commit("showUserOnCalendar", {
|
||||||
|
user: this.$store.state.me,
|
||||||
|
remotes: true,
|
||||||
|
ranges: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$store.dispatch("setEventTimes", {
|
||||||
|
start: payload.start,
|
||||||
|
end: payload.end,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onEventChange(payload) {
|
||||||
|
console.log("onEventChange", payload);
|
||||||
|
if (this.$store.state.activity.calendarRange !== null) {
|
||||||
|
throw new Error(
|
||||||
|
"not allowed to edit a calendar associated with a calendar range",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.$store.dispatch("setEventTimes", {
|
||||||
|
start: payload.event.start,
|
||||||
|
end: payload.event.end,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onEventClick(payload) {
|
||||||
|
if (payload.event.extendedProps.is !== "range") {
|
||||||
|
// do nothing when clicking on remote
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// show an alert if changing mainUser
|
||||||
|
if (
|
||||||
|
this.$store.getters.getMainUser !== null &&
|
||||||
|
payload.event.extendedProps.userId !==
|
||||||
|
this.$store.getters.getMainUser.id
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!window.confirm(this.$t("this_calendar_range_will_change_main_user"))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$store.dispatch("associateCalendarToRange", {
|
||||||
|
range: payload.event,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.calendar-actives {
|
.calendar-actives {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.display-options {
|
.display-options {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for events which are range */
|
/* for events which are range */
|
||||||
.fc-event.isrange {
|
.fc-event.isrange {
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,231 +1,185 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<label class="form-label">{{ $t("created_availabilities") }}</label>
|
<label class="form-label">{{ $t("created_availabilities") }}</label>
|
||||||
<vue-multiselect
|
<vue-multiselect
|
||||||
v-model="pickedLocation"
|
v-model="pickedLocation"
|
||||||
:options="locations"
|
:options="locations"
|
||||||
:label="'name'"
|
:label="'name'"
|
||||||
:track-by="'id'"
|
:track-by="'id'"
|
||||||
:selectLabel="'Presser \'Entrée\' pour choisir'"
|
:selectLabel="'Presser \'Entrée\' pour choisir'"
|
||||||
:selectedLabel="'Choisir'"
|
:selectedLabel="'Choisir'"
|
||||||
:deselectLabel="'Presser \'Entrée\' pour enlever'"
|
:deselectLabel="'Presser \'Entrée\' pour enlever'"
|
||||||
:placeholder="'Choisir'"
|
:placeholder="'Choisir'"
|
||||||
></vue-multiselect>
|
></vue-multiselect>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
</div>
|
||||||
class="display-options row justify-content-between"
|
<div
|
||||||
style="margin-top: 1rem"
|
class="display-options row justify-content-between"
|
||||||
>
|
style="margin-top: 1rem"
|
||||||
<div class="col-sm-9 col-xs-12">
|
>
|
||||||
<div class="input-group mb-3">
|
<div class="col-sm-9 col-xs-12">
|
||||||
<label class="input-group-text" for="slotDuration"
|
<div class="input-group mb-3">
|
||||||
>Durée des créneaux</label
|
<label class="input-group-text" for="slotDuration"
|
||||||
>
|
>Durée des créneaux</label
|
||||||
<select
|
>
|
||||||
v-model="slotDuration"
|
<select v-model="slotDuration" id="slotDuration" class="form-select">
|
||||||
id="slotDuration"
|
<option value="00:05:00">5 minutes</option>
|
||||||
class="form-select"
|
<option value="00:10:00">10 minutes</option>
|
||||||
>
|
<option value="00:15:00">15 minutes</option>
|
||||||
<option value="00:05:00">5 minutes</option>
|
<option value="00:30:00">30 minutes</option>
|
||||||
<option value="00:10:00">10 minutes</option>
|
<option value="00:45:00">45 minutes</option>
|
||||||
<option value="00:15:00">15 minutes</option>
|
<option value="00:60:00">60 minutes</option>
|
||||||
<option value="00:30:00">30 minutes</option>
|
</select>
|
||||||
<option value="00:45:00">45 minutes</option>
|
<label class="input-group-text" for="slotMinTime">De</label>
|
||||||
<option value="00:60:00">60 minutes</option>
|
<select v-model="slotMinTime" id="slotMinTime" class="form-select">
|
||||||
</select>
|
<option value="00:00:00">0h</option>
|
||||||
<label class="input-group-text" for="slotMinTime">De</label>
|
<option value="01:00:00">1h</option>
|
||||||
<select
|
<option value="02:00:00">2h</option>
|
||||||
v-model="slotMinTime"
|
<option value="03:00:00">3h</option>
|
||||||
id="slotMinTime"
|
<option value="04:00:00">4h</option>
|
||||||
class="form-select"
|
<option value="05:00:00">5h</option>
|
||||||
>
|
<option value="06:00:00">6h</option>
|
||||||
<option value="00:00:00">0h</option>
|
<option value="07:00:00">7h</option>
|
||||||
<option value="01:00:00">1h</option>
|
<option value="08:00:00">8h</option>
|
||||||
<option value="02:00:00">2h</option>
|
<option value="09:00:00">9h</option>
|
||||||
<option value="03:00:00">3h</option>
|
<option value="10:00:00">10h</option>
|
||||||
<option value="04:00:00">4h</option>
|
<option value="11:00:00">11h</option>
|
||||||
<option value="05:00:00">5h</option>
|
<option value="12:00:00">12h</option>
|
||||||
<option value="06:00:00">6h</option>
|
</select>
|
||||||
<option value="07:00:00">7h</option>
|
<label class="input-group-text" for="slotMaxTime">À</label>
|
||||||
<option value="08:00:00">8h</option>
|
<select v-model="slotMaxTime" id="slotMaxTime" class="form-select">
|
||||||
<option value="09:00:00">9h</option>
|
<option value="12:00:00">12h</option>
|
||||||
<option value="10:00:00">10h</option>
|
<option value="13:00:00">13h</option>
|
||||||
<option value="11:00:00">11h</option>
|
<option value="14:00:00">14h</option>
|
||||||
<option value="12:00:00">12h</option>
|
<option value="15:00:00">15h</option>
|
||||||
</select>
|
<option value="16:00:00">16h</option>
|
||||||
<label class="input-group-text" for="slotMaxTime">À</label>
|
<option value="17:00:00">17h</option>
|
||||||
<select
|
<option value="18:00:00">18h</option>
|
||||||
v-model="slotMaxTime"
|
<option value="19:00:00">19h</option>
|
||||||
id="slotMaxTime"
|
<option value="20:00:00">20h</option>
|
||||||
class="form-select"
|
<option value="21:00:00">21h</option>
|
||||||
>
|
<option value="22:00:00">22h</option>
|
||||||
<option value="12:00:00">12h</option>
|
<option value="23:00:00">23h</option>
|
||||||
<option value="13:00:00">13h</option>
|
<option value="23:59:59">24h</option>
|
||||||
<option value="14:00:00">14h</option>
|
</select>
|
||||||
<option value="15:00:00">15h</option>
|
</div>
|
||||||
<option value="16:00:00">16h</option>
|
|
||||||
<option value="17:00:00">17h</option>
|
|
||||||
<option value="18:00:00">18h</option>
|
|
||||||
<option value="19:00:00">19h</option>
|
|
||||||
<option value="20:00:00">20h</option>
|
|
||||||
<option value="21:00:00">21h</option>
|
|
||||||
<option value="22:00:00">22h</option>
|
|
||||||
<option value="23:00:00">23h</option>
|
|
||||||
<option value="23:59:59">24h</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-3">
|
|
||||||
<div class="float-end">
|
|
||||||
<div class="form-check input-group">
|
|
||||||
<span class="input-group-text">
|
|
||||||
<input
|
|
||||||
id="showHideWE"
|
|
||||||
class="mt-0"
|
|
||||||
type="checkbox"
|
|
||||||
v-model="showWeekends"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<label
|
|
||||||
for="showHideWE"
|
|
||||||
class="form-check-label input-group-text"
|
|
||||||
>Week-ends</label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
<div class="col-xs-12 col-sm-3">
|
||||||
<template v-slot:eventContent="{ event }: { event: EventApi }">
|
<div class="float-end">
|
||||||
<span :class="eventClasses">
|
<div class="form-check input-group">
|
||||||
<b v-if="event.extendedProps.is === 'remote'">{{
|
<span class="input-group-text">
|
||||||
event.title
|
<input
|
||||||
}}</b>
|
id="showHideWE"
|
||||||
<b v-else-if="event.extendedProps.is === 'range'"
|
class="mt-0"
|
||||||
>{{ formatDate(event.startStr, "time") }} -
|
type="checkbox"
|
||||||
{{ formatDate(event.endStr, "time") }}:
|
v-model="showWeekends"
|
||||||
{{ event.extendedProps.locationName }}</b
|
/>
|
||||||
>
|
</span>
|
||||||
<a
|
<label for="showHideWE" class="form-check-label input-group-text"
|
||||||
:href="calendarLink(event.id)"
|
>Week-ends</label
|
||||||
v-else-if="event.extendedProps.is === 'local'"
|
>
|
||||||
>
|
</div>
|
||||||
<b>{{ event.title }}</b>
|
</div>
|
||||||
</a>
|
</div>
|
||||||
<b v-else>no 'is'</b>
|
</div>
|
||||||
<a
|
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
||||||
v-if="event.extendedProps.is === 'range'"
|
<template v-slot:eventContent="{ event }: { event: EventApi }">
|
||||||
class="fa fa-fw fa-times delete"
|
<span :class="eventClasses">
|
||||||
@click.prevent="onClickDelete(event)"
|
<b v-if="event.extendedProps.is === 'remote'">{{ event.title }}</b>
|
||||||
>
|
<b v-else-if="event.extendedProps.is === 'range'"
|
||||||
</a>
|
>{{ formatDate(event.startStr, "time") }} -
|
||||||
</span>
|
{{ formatDate(event.endStr, "time") }}:
|
||||||
|
{{ event.extendedProps.locationName }}</b
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
:href="calendarLink(event.id)"
|
||||||
|
v-else-if="event.extendedProps.is === 'local'"
|
||||||
|
>
|
||||||
|
<b>{{ event.title }}</b>
|
||||||
|
</a>
|
||||||
|
<b v-else>no 'is'</b>
|
||||||
|
<a
|
||||||
|
v-if="event.extendedProps.is === 'range'"
|
||||||
|
class="fa fa-fw fa-times delete"
|
||||||
|
@click.prevent="onClickDelete(event)"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</FullCalendar>
|
||||||
|
|
||||||
|
<div id="copy-widget">
|
||||||
|
<div class="container mt-2 mb-2">
|
||||||
|
<div class="row justify-content-between align-items-center mb-4">
|
||||||
|
<div class="col-xs-12 col-sm-3 col-md-2">
|
||||||
|
<h6 class="chill-red">{{ $t("copy_range_from_to") }}</h6>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-9 col-md-2">
|
||||||
|
<select v-model="dayOrWeek" id="dayOrWeek" class="form-select">
|
||||||
|
<option value="day">{{ $t("from_day_to_day") }}</option>
|
||||||
|
<option value="week">
|
||||||
|
{{ $t("from_week_to_week") }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<template v-if="dayOrWeek === 'day'">
|
||||||
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
|
<input class="form-control" type="date" v-model="copyFrom" />
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-1 col-md-1 copy-chevron">
|
||||||
|
<i class="fa fa-angle-double-right"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
|
<input class="form-control" type="date" v-model="copyTo" />
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-5 col-md-1">
|
||||||
|
<button class="btn btn-action float-end" @click="copyDay">
|
||||||
|
{{ $t("copy_range") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</FullCalendar>
|
<template v-else>
|
||||||
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
<div id="copy-widget">
|
<select
|
||||||
<div class="container mt-2 mb-2">
|
v-model="copyFromWeek"
|
||||||
<div class="row justify-content-between align-items-center mb-4">
|
id="copyFromWeek"
|
||||||
<div class="col-xs-12 col-sm-3 col-md-2">
|
class="form-select"
|
||||||
<h6 class="chill-red">{{ $t("copy_range_from_to") }}</h6>
|
>
|
||||||
</div>
|
<option v-for="w in lastWeeks" :value="w.value" :key="w.value">
|
||||||
<div class="col-xs-12 col-sm-9 col-md-2">
|
{{ w.text }}
|
||||||
<select
|
</option>
|
||||||
v-model="dayOrWeek"
|
</select>
|
||||||
id="dayOrWeek"
|
</div>
|
||||||
class="form-select"
|
<div class="col-xs-12 col-sm-1 col-md-1 copy-chevron">
|
||||||
>
|
<i class="fa fa-angle-double-right"></i>
|
||||||
<option value="day">{{ $t("from_day_to_day") }}</option>
|
</div>
|
||||||
<option value="week">
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
{{ $t("from_week_to_week") }}
|
<select v-model="copyToWeek" id="copyToWeek" class="form-select">
|
||||||
</option>
|
<option v-for="w in nextWeeks" :value="w.value" :key="w.value">
|
||||||
</select>
|
{{ w.text }}
|
||||||
</div>
|
</option>
|
||||||
<template v-if="dayOrWeek === 'day'">
|
</select>
|
||||||
<div class="col-xs-12 col-sm-3 col-md-3">
|
</div>
|
||||||
<input
|
<div class="col-xs-12 col-sm-5 col-md-1">
|
||||||
class="form-control"
|
<button class="btn btn-action float-end" @click="copyWeek">
|
||||||
type="date"
|
{{ $t("copy_range") }}
|
||||||
v-model="copyFrom"
|
</button>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
<div class="col-xs-12 col-sm-1 col-md-1 copy-chevron">
|
</div>
|
||||||
<i class="fa fa-angle-double-right"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-3 col-md-3">
|
|
||||||
<input
|
|
||||||
class="form-control"
|
|
||||||
type="date"
|
|
||||||
v-model="copyTo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-5 col-md-1">
|
|
||||||
<button
|
|
||||||
class="btn btn-action float-end"
|
|
||||||
@click="copyDay"
|
|
||||||
>
|
|
||||||
{{ $t("copy_range") }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div class="col-xs-12 col-sm-3 col-md-3">
|
|
||||||
<select
|
|
||||||
v-model="copyFromWeek"
|
|
||||||
id="copyFromWeek"
|
|
||||||
class="form-select"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for="w in lastWeeks"
|
|
||||||
:value="w.value"
|
|
||||||
:key="w.value"
|
|
||||||
>
|
|
||||||
{{ w.text }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-1 col-md-1 copy-chevron">
|
|
||||||
<i class="fa fa-angle-double-right"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-3 col-md-3">
|
|
||||||
<select
|
|
||||||
v-model="copyToWeek"
|
|
||||||
id="copyToWeek"
|
|
||||||
class="form-select"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for="w in nextWeeks"
|
|
||||||
:value="w.value"
|
|
||||||
:key="w.value"
|
|
||||||
>
|
|
||||||
{{ w.text }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-5 col-md-1">
|
|
||||||
<button
|
|
||||||
class="btn btn-action float-end"
|
|
||||||
@click="copyWeek"
|
|
||||||
>
|
|
||||||
{{ $t("copy_range") }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- not directly seen, but include in a modal -->
|
<!-- not directly seen, but include in a modal -->
|
||||||
<edit-location ref="editLocation"></edit-location>
|
<edit-location ref="editLocation"></edit-location>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {
|
import type {
|
||||||
CalendarOptions,
|
CalendarOptions,
|
||||||
DatesSetArg,
|
DatesSetArg,
|
||||||
EventInput,
|
EventInput,
|
||||||
} from "@fullcalendar/core";
|
} from "@fullcalendar/core";
|
||||||
import { computed, ref, onMounted } from "vue";
|
import { computed, ref, onMounted } from "vue";
|
||||||
import { useStore } from "vuex";
|
import { useStore } from "vuex";
|
||||||
@@ -233,14 +187,14 @@ import { key } from "./store";
|
|||||||
import FullCalendar from "@fullcalendar/vue3";
|
import FullCalendar from "@fullcalendar/vue3";
|
||||||
import frLocale from "@fullcalendar/core/locales/fr";
|
import frLocale from "@fullcalendar/core/locales/fr";
|
||||||
import interactionPlugin, {
|
import interactionPlugin, {
|
||||||
EventResizeDoneArg,
|
EventResizeDoneArg,
|
||||||
} from "@fullcalendar/interaction";
|
} from "@fullcalendar/interaction";
|
||||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||||
import {
|
import {
|
||||||
EventApi,
|
EventApi,
|
||||||
DateSelectArg,
|
DateSelectArg,
|
||||||
EventDropArg,
|
EventDropArg,
|
||||||
EventClickArg,
|
EventClickArg,
|
||||||
} from "@fullcalendar/core";
|
} from "@fullcalendar/core";
|
||||||
import { dateToISO, ISOToDate } from "ChillMainAssets/chill/js/date";
|
import { dateToISO, ISOToDate } from "ChillMainAssets/chill/js/date";
|
||||||
import VueMultiselect from "vue-multiselect";
|
import VueMultiselect from "vue-multiselect";
|
||||||
@@ -261,113 +215,113 @@ const copyFromWeek = ref<string | null>(null);
|
|||||||
const copyToWeek = ref<string | null>(null);
|
const copyToWeek = ref<string | null>(null);
|
||||||
|
|
||||||
interface Weeks {
|
interface Weeks {
|
||||||
value: string | null;
|
value: string | null;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMonday = (week: number): Date => {
|
const getMonday = (week: number): Date => {
|
||||||
const lastMonday = new Date();
|
const lastMonday = new Date();
|
||||||
lastMonday.setDate(
|
lastMonday.setDate(
|
||||||
lastMonday.getDate() - ((lastMonday.getDay() + 6) % 7) + week * 7,
|
lastMonday.getDate() - ((lastMonday.getDay() + 6) % 7) + week * 7,
|
||||||
);
|
);
|
||||||
return lastMonday;
|
return lastMonday;
|
||||||
};
|
};
|
||||||
|
|
||||||
const dateOptions: Intl.DateTimeFormatOptions = {
|
const dateOptions: Intl.DateTimeFormatOptions = {
|
||||||
weekday: "long",
|
weekday: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
month: "long",
|
month: "long",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
};
|
};
|
||||||
|
|
||||||
const lastWeeks = computed((): Weeks[] =>
|
const lastWeeks = computed((): Weeks[] =>
|
||||||
Array.from(Array(30).keys()).map((w) => {
|
Array.from(Array(30).keys()).map((w) => {
|
||||||
const lastMonday = getMonday(15 - w);
|
const lastMonday = getMonday(15 - w);
|
||||||
return {
|
return {
|
||||||
value: dateToISO(lastMonday),
|
value: dateToISO(lastMonday),
|
||||||
text: `Semaine du ${lastMonday.toLocaleDateString("fr-FR", dateOptions)}`,
|
text: `Semaine du ${lastMonday.toLocaleDateString("fr-FR", dateOptions)}`,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const nextWeeks = computed((): Weeks[] =>
|
const nextWeeks = computed((): Weeks[] =>
|
||||||
Array.from(Array(52).keys()).map((w) => {
|
Array.from(Array(52).keys()).map((w) => {
|
||||||
const nextMonday = getMonday(w + 1);
|
const nextMonday = getMonday(w + 1);
|
||||||
return {
|
return {
|
||||||
value: dateToISO(nextMonday),
|
value: dateToISO(nextMonday),
|
||||||
text: `Semaine du ${nextMonday.toLocaleDateString("fr-FR", dateOptions)}`,
|
text: `Semaine du ${nextMonday.toLocaleDateString("fr-FR", dateOptions)}`,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const formatDate = (datetime: string, format: null | "time" = null) => {
|
const formatDate = (datetime: string, format: null | "time" = null) => {
|
||||||
const date = ISOToDate(datetime);
|
const date = ISOToDate(datetime);
|
||||||
if (!date) return "";
|
if (!date) return "";
|
||||||
|
|
||||||
if (format === "time") {
|
if (format === "time") {
|
||||||
return date.toLocaleTimeString("fr-FR", {
|
return date.toLocaleTimeString("fr-FR", {
|
||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// French date formatting
|
|
||||||
return date.toLocaleDateString("fr-FR", {
|
|
||||||
weekday: "short",
|
|
||||||
year: "numeric",
|
|
||||||
month: "short",
|
|
||||||
day: "numeric",
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// French date formatting
|
||||||
|
return date.toLocaleDateString("fr-FR", {
|
||||||
|
weekday: "short",
|
||||||
|
year: "numeric",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseOptions = ref<CalendarOptions>({
|
const baseOptions = ref<CalendarOptions>({
|
||||||
locale: frLocale,
|
locale: frLocale,
|
||||||
plugins: [interactionPlugin, timeGridPlugin],
|
plugins: [interactionPlugin, timeGridPlugin],
|
||||||
initialView: "timeGridWeek",
|
initialView: "timeGridWeek",
|
||||||
initialDate: new Date(),
|
initialDate: new Date(),
|
||||||
scrollTimeReset: false,
|
scrollTimeReset: false,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
// when the dates are changes in the fullcalendar view OR when new events are added
|
// when the dates are changes in the fullcalendar view OR when new events are added
|
||||||
datesSet: onDatesSet,
|
datesSet: onDatesSet,
|
||||||
// when a date is selected
|
// when a date is selected
|
||||||
select: onDateSelect,
|
select: onDateSelect,
|
||||||
// when a event is resized
|
// when a event is resized
|
||||||
eventResize: onEventDropOrResize,
|
eventResize: onEventDropOrResize,
|
||||||
// when an event is moved
|
// when an event is moved
|
||||||
eventDrop: onEventDropOrResize,
|
eventDrop: onEventDropOrResize,
|
||||||
// when an event si clicked
|
// when an event si clicked
|
||||||
eventClick: onEventClick,
|
eventClick: onEventClick,
|
||||||
selectMirror: false,
|
selectMirror: false,
|
||||||
editable: true,
|
editable: true,
|
||||||
headerToolbar: {
|
headerToolbar: {
|
||||||
left: "prev,next today",
|
left: "prev,next today",
|
||||||
center: "title",
|
center: "title",
|
||||||
right: "timeGridWeek,timeGridDay",
|
right: "timeGridWeek,timeGridDay",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const ranges = computed<EventInput[]>(() => {
|
const ranges = computed<EventInput[]>(() => {
|
||||||
return store.state.calendarRanges.ranges;
|
return store.state.calendarRanges.ranges;
|
||||||
});
|
});
|
||||||
|
|
||||||
const locations = computed<Location[]>(() => {
|
const locations = computed<Location[]>(() => {
|
||||||
return store.state.locations.locations;
|
return store.state.locations.locations;
|
||||||
});
|
});
|
||||||
|
|
||||||
const pickedLocation = computed<Location | null>({
|
const pickedLocation = computed<Location | null>({
|
||||||
get(): Location | null {
|
get(): Location | null {
|
||||||
return (
|
return (
|
||||||
store.state.locations.locationPicked ||
|
store.state.locations.locationPicked ||
|
||||||
store.state.locations.currentLocation
|
store.state.locations.currentLocation
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
set(newLocation: Location | null): void {
|
set(newLocation: Location | null): void {
|
||||||
store.commit("locations/setLocationPicked", newLocation, {
|
store.commit("locations/setLocationPicked", newLocation, {
|
||||||
root: true,
|
root: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -396,122 +350,122 @@ const sources = computed<EventSourceInput[]>(() => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const calendarOptions = computed((): CalendarOptions => {
|
const calendarOptions = computed((): CalendarOptions => {
|
||||||
return {
|
return {
|
||||||
...baseOptions.value,
|
...baseOptions.value,
|
||||||
weekends: showWeekends.value,
|
weekends: showWeekends.value,
|
||||||
slotDuration: slotDuration.value,
|
slotDuration: slotDuration.value,
|
||||||
events: ranges.value,
|
events: ranges.value,
|
||||||
slotMinTime: slotMinTime.value,
|
slotMinTime: slotMinTime.value,
|
||||||
slotMaxTime: slotMaxTime.value,
|
slotMaxTime: slotMaxTime.value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* launched when the calendar range date change
|
* launched when the calendar range date change
|
||||||
*/
|
*/
|
||||||
function onDatesSet(event: DatesSetArg): void {
|
function onDatesSet(event: DatesSetArg): void {
|
||||||
store.dispatch("fullCalendar/setCurrentDatesView", {
|
store.dispatch("fullCalendar/setCurrentDatesView", {
|
||||||
start: event.start,
|
start: event.start,
|
||||||
end: event.end,
|
end: event.end,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDateSelect(event: DateSelectArg): void {
|
function onDateSelect(event: DateSelectArg): void {
|
||||||
if (null === pickedLocation.value) {
|
if (null === pickedLocation.value) {
|
||||||
window.alert(
|
window.alert(
|
||||||
"Indiquez une localisation avant de créer une période de disponibilité.",
|
"Indiquez une localisation avant de créer une période de disponibilité.",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch("calendarRanges/createRange", {
|
store.dispatch("calendarRanges/createRange", {
|
||||||
start: event.start,
|
start: event.start,
|
||||||
end: event.end,
|
end: event.end,
|
||||||
location: pickedLocation.value,
|
location: pickedLocation.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a calendar range is deleted
|
* When a calendar range is deleted
|
||||||
*/
|
*/
|
||||||
function onClickDelete(event: EventApi): void {
|
function onClickDelete(event: EventApi): void {
|
||||||
if (event.extendedProps.is !== "range") {
|
if (event.extendedProps.is !== "range") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
"calendarRanges/deleteRange",
|
"calendarRanges/deleteRange",
|
||||||
event.extendedProps.calendarRangeId,
|
event.extendedProps.calendarRangeId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEventDropOrResize(payload: EventDropArg | EventResizeDoneArg) {
|
function onEventDropOrResize(payload: EventDropArg | EventResizeDoneArg) {
|
||||||
if (payload.event.extendedProps.is !== "range") {
|
if (payload.event.extendedProps.is !== "range") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch("calendarRanges/patchRangeTime", {
|
store.dispatch("calendarRanges/patchRangeTime", {
|
||||||
calendarRangeId: payload.event.extendedProps.calendarRangeId,
|
calendarRangeId: payload.event.extendedProps.calendarRangeId,
|
||||||
start: payload.event.start,
|
start: payload.event.start,
|
||||||
end: payload.event.end,
|
end: payload.event.end,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEventClick(payload: EventClickArg): void {
|
function onEventClick(payload: EventClickArg): void {
|
||||||
// @ts-ignore TS does not recognize the target. But it does exists.
|
// @ts-ignore TS does not recognize the target. But it does exists.
|
||||||
if (payload.jsEvent.target.classList.contains("delete")) {
|
if (payload.jsEvent.target.classList.contains("delete")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (payload.event.extendedProps.is !== "range") {
|
if (payload.event.extendedProps.is !== "range") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
editLocation.value?.startEdit(payload.event);
|
editLocation.value?.startEdit(payload.event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyDay() {
|
function copyDay() {
|
||||||
if (null === copyFrom.value || null === copyTo.value) {
|
if (null === copyFrom.value || null === copyTo.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
store.dispatch("calendarRanges/copyFromDayToAnotherDay", {
|
store.dispatch("calendarRanges/copyFromDayToAnotherDay", {
|
||||||
from: ISOToDate(copyFrom.value),
|
from: ISOToDate(copyFrom.value),
|
||||||
to: ISOToDate(copyTo.value),
|
to: ISOToDate(copyTo.value),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyWeek() {
|
function copyWeek() {
|
||||||
if (null === copyFromWeek.value || null === copyToWeek.value) {
|
if (null === copyFromWeek.value || null === copyToWeek.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
store.dispatch("calendarRanges/copyFromWeekToAnotherWeek", {
|
store.dispatch("calendarRanges/copyFromWeekToAnotherWeek", {
|
||||||
fromMonday: ISOToDate(copyFromWeek.value),
|
fromMonday: ISOToDate(copyFromWeek.value),
|
||||||
toMonday: ISOToDate(copyToWeek.value),
|
toMonday: ISOToDate(copyToWeek.value),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const calendarLink = (calendarId: string) => {
|
const calendarLink = (calendarId: string) => {
|
||||||
const idStr = calendarId.match(/_(\d+)$/)?.[1];
|
const idStr = calendarId.match(/_(\d+)$/)?.[1];
|
||||||
|
|
||||||
return `/fr/calendar/calendar/${idStr}/edit`;
|
return `/fr/calendar/calendar/${idStr}/edit`;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
copyFromWeek.value = dateToISO(getMonday(0));
|
copyFromWeek.value = dateToISO(getMonday(0));
|
||||||
copyToWeek.value = dateToISO(getMonday(1));
|
copyToWeek.value = dateToISO(getMonday(1));
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#copy-widget {
|
#copy-widget {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
z-index: 9999999999;
|
z-index: 9999999999;
|
||||||
padding: 0.25rem 0 0.25rem;
|
padding: 0.25rem 0 0.25rem;
|
||||||
}
|
}
|
||||||
div.copy-chevron {
|
div.copy-chevron {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
width: 2rem;
|
width: 2rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { DateTime } from "ChillMainAssets/types";
|
|||||||
import { StoredObject } from "ChillDocStoreAssets/types/index";
|
import { StoredObject } from "ChillDocStoreAssets/types/index";
|
||||||
|
|
||||||
export interface GenericDocMetadata {
|
export interface GenericDocMetadata {
|
||||||
isPresent: boolean;
|
isPresent: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,69 +15,69 @@ export interface EmptyMetadata extends GenericDocMetadata {}
|
|||||||
* Minimal Metadata for a GenericDoc with a normalizer
|
* Minimal Metadata for a GenericDoc with a normalizer
|
||||||
*/
|
*/
|
||||||
export interface BaseMetadata extends GenericDocMetadata {
|
export interface BaseMetadata extends GenericDocMetadata {
|
||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic doc is a document attached to a Person or an AccompanyingPeriod.
|
* A generic doc is a document attached to a Person or an AccompanyingPeriod.
|
||||||
*/
|
*/
|
||||||
export interface GenericDoc {
|
export interface GenericDoc {
|
||||||
type: "doc_store_generic_doc";
|
type: "doc_store_generic_doc";
|
||||||
uniqueKey: string;
|
uniqueKey: string;
|
||||||
key: string;
|
key: string;
|
||||||
identifiers: { id: number };
|
identifiers: { id: number };
|
||||||
context: "person" | "accompanying-period";
|
context: "person" | "accompanying-period";
|
||||||
doc_date: DateTime;
|
doc_date: DateTime;
|
||||||
metadata: GenericDocMetadata;
|
metadata: GenericDocMetadata;
|
||||||
storedObject: StoredObject | null;
|
storedObject: StoredObject | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericDocForAccompanyingPeriod extends GenericDoc {
|
export interface GenericDocForAccompanyingPeriod extends GenericDoc {
|
||||||
context: "accompanying-period";
|
context: "accompanying-period";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isGenericDocForAccompanyingPeriod(
|
export function isGenericDocForAccompanyingPeriod(
|
||||||
doc: GenericDoc,
|
doc: GenericDoc,
|
||||||
): doc is GenericDocForAccompanyingPeriod {
|
): doc is GenericDocForAccompanyingPeriod {
|
||||||
return doc.context === "accompanying-period";
|
return doc.context === "accompanying-period";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isGenericDocWithStoredObject(
|
export function isGenericDocWithStoredObject(
|
||||||
doc: GenericDoc,
|
doc: GenericDoc,
|
||||||
): doc is GenericDoc & { storedObject: StoredObject } {
|
): doc is GenericDoc & { storedObject: StoredObject } {
|
||||||
return doc.storedObject !== null;
|
return doc.storedObject !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BaseMetadataWithHtml extends BaseMetadata {
|
interface BaseMetadataWithHtml extends BaseMetadata {
|
||||||
html: string;
|
html: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericDocForAccompanyingCourseDocument extends GenericDocForAccompanyingPeriod {
|
export interface GenericDocForAccompanyingCourseDocument extends GenericDocForAccompanyingPeriod {
|
||||||
key: "accompanying_course_document";
|
key: "accompanying_course_document";
|
||||||
metadata: BaseMetadataWithHtml;
|
metadata: BaseMetadataWithHtml;
|
||||||
storedObject: StoredObject;
|
storedObject: StoredObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericDocForAccompanyingCourseActivityDocument extends GenericDocForAccompanyingPeriod {
|
export interface GenericDocForAccompanyingCourseActivityDocument extends GenericDocForAccompanyingPeriod {
|
||||||
key: "accompanying_course_activity_document";
|
key: "accompanying_course_activity_document";
|
||||||
metadata: BaseMetadataWithHtml;
|
metadata: BaseMetadataWithHtml;
|
||||||
storedObject: StoredObject;
|
storedObject: StoredObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericDocForAccompanyingCourseCalendarDocument extends GenericDocForAccompanyingPeriod {
|
export interface GenericDocForAccompanyingCourseCalendarDocument extends GenericDocForAccompanyingPeriod {
|
||||||
key: "accompanying_course_calendar_document";
|
key: "accompanying_course_calendar_document";
|
||||||
metadata: BaseMetadataWithHtml;
|
metadata: BaseMetadataWithHtml;
|
||||||
storedObject: StoredObject;
|
storedObject: StoredObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericDocForAccompanyingCoursePersonDocument extends GenericDocForAccompanyingPeriod {
|
export interface GenericDocForAccompanyingCoursePersonDocument extends GenericDocForAccompanyingPeriod {
|
||||||
key: "person_document";
|
key: "person_document";
|
||||||
metadata: BaseMetadataWithHtml;
|
metadata: BaseMetadataWithHtml;
|
||||||
storedObject: StoredObject;
|
storedObject: StoredObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericDocForAccompanyingCourseWorkEvaluationDocument extends GenericDocForAccompanyingPeriod {
|
export interface GenericDocForAccompanyingCourseWorkEvaluationDocument extends GenericDocForAccompanyingPeriod {
|
||||||
key: "accompanying_period_work_evaluation_document";
|
key: "accompanying_period_work_evaluation_document";
|
||||||
metadata: BaseMetadataWithHtml;
|
metadata: BaseMetadataWithHtml;
|
||||||
storedObject: StoredObject;
|
storedObject: StoredObject;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ export interface StoredObjectVersionCreated extends StoredObjectVersion {
|
|||||||
persisted: false;
|
persisted: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StoredObjectVersionPersisted
|
export interface StoredObjectVersionPersisted extends StoredObjectVersionCreated {
|
||||||
extends StoredObjectVersionCreated {
|
|
||||||
version: number;
|
version: number;
|
||||||
id: number;
|
id: number;
|
||||||
createdAt: DateTime | null;
|
createdAt: DateTime | null;
|
||||||
@@ -61,8 +60,7 @@ export interface StoredObjectStatusChange {
|
|||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StoredObjectVersionWithPointInTime
|
export interface StoredObjectVersionWithPointInTime extends StoredObjectVersionPersisted {
|
||||||
extends StoredObjectVersionPersisted {
|
|
||||||
"point-in-times": StoredObjectPointInTime[];
|
"point-in-times": StoredObjectPointInTime[];
|
||||||
"from-restored": StoredObjectVersionPersisted | null;
|
"from-restored": StoredObjectVersionPersisted | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,24 +7,24 @@ import { useToast } from "vue-toast-notification";
|
|||||||
import { DOCUMENT_ADD, trans } from "translator";
|
import { DOCUMENT_ADD, trans } from "translator";
|
||||||
|
|
||||||
interface DropFileConfig {
|
interface DropFileConfig {
|
||||||
allowRemove: boolean;
|
allowRemove: boolean;
|
||||||
existingDoc?: StoredObject;
|
existingDoc?: StoredObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<DropFileConfig>(), {
|
const props = withDefaults(defineProps<DropFileConfig>(), {
|
||||||
allowRemove: false,
|
allowRemove: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(
|
(
|
||||||
e: "addDocument",
|
e: "addDocument",
|
||||||
{
|
{
|
||||||
stored_object: StoredObject,
|
stored_object: StoredObject,
|
||||||
stored_object_version: StoredObjectVersion,
|
stored_object_version: StoredObjectVersion,
|
||||||
file_name: string,
|
file_name: string,
|
||||||
},
|
},
|
||||||
): void;
|
): void;
|
||||||
(e: "removeDocument"): void;
|
(e: "removeDocument"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const $toast = useToast();
|
const $toast = useToast();
|
||||||
@@ -34,65 +34,65 @@ const state = reactive({ showModal: false });
|
|||||||
const modalClasses = { "modal-dialog-centered": true, "modal-md": true };
|
const modalClasses = { "modal-dialog-centered": true, "modal-md": true };
|
||||||
|
|
||||||
const buttonState = computed<"add" | "replace">(() => {
|
const buttonState = computed<"add" | "replace">(() => {
|
||||||
if (props.existingDoc === undefined || props.existingDoc === null) {
|
if (props.existingDoc === undefined || props.existingDoc === null) {
|
||||||
return "add";
|
return "add";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "replace";
|
return "replace";
|
||||||
});
|
});
|
||||||
|
|
||||||
function onAddDocument({
|
function onAddDocument({
|
||||||
stored_object,
|
stored_object,
|
||||||
stored_object_version,
|
stored_object_version,
|
||||||
file_name,
|
file_name,
|
||||||
}: {
|
}: {
|
||||||
stored_object: StoredObject;
|
stored_object: StoredObject;
|
||||||
stored_object_version: StoredObjectVersion;
|
stored_object_version: StoredObjectVersion;
|
||||||
file_name: string;
|
file_name: string;
|
||||||
}): void {
|
}): void {
|
||||||
const message =
|
const message =
|
||||||
buttonState.value === "add" ? "Document ajouté" : "Document remplacé";
|
buttonState.value === "add" ? "Document ajouté" : "Document remplacé";
|
||||||
$toast.success(message);
|
$toast.success(message);
|
||||||
emit("addDocument", { stored_object_version, stored_object, file_name });
|
emit("addDocument", { stored_object_version, stored_object, file_name });
|
||||||
state.showModal = false;
|
state.showModal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRemoveDocument(): void {
|
function onRemoveDocument(): void {
|
||||||
emit("removeDocument");
|
emit("removeDocument");
|
||||||
}
|
}
|
||||||
|
|
||||||
function openModal(): void {
|
function openModal(): void {
|
||||||
state.showModal = true;
|
state.showModal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeModal(): void {
|
function closeModal(): void {
|
||||||
state.showModal = false;
|
state.showModal = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
v-if="buttonState === 'add'"
|
v-if="buttonState === 'add'"
|
||||||
@click="openModal"
|
@click="openModal"
|
||||||
class="btn btn-create"
|
class="btn btn-create"
|
||||||
>
|
>
|
||||||
{{ trans(DOCUMENT_ADD) }}
|
{{ trans(DOCUMENT_ADD) }}
|
||||||
</button>
|
</button>
|
||||||
<button v-else @click="openModal" class="btn btn-edit"></button>
|
<button v-else @click="openModal" class="btn btn-edit"></button>
|
||||||
<modal
|
<modal
|
||||||
v-if="state.showModal"
|
v-if="state.showModal"
|
||||||
:modal-dialog-class="modalClasses"
|
:modal-dialog-class="modalClasses"
|
||||||
@close="closeModal"
|
@close="closeModal"
|
||||||
>
|
>
|
||||||
<template v-slot:body>
|
<template v-slot:body>
|
||||||
<drop-file-widget
|
<drop-file-widget
|
||||||
:existing-doc="existingDoc"
|
:existing-doc="existingDoc"
|
||||||
:allow-remove="allowRemove"
|
:allow-remove="allowRemove"
|
||||||
@add-document="onAddDocument"
|
@add-document="onAddDocument"
|
||||||
@remove-document="onRemoveDocument"
|
@remove-document="onRemoveDocument"
|
||||||
></drop-file-widget>
|
></drop-file-widget>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
StoredObject,
|
StoredObject,
|
||||||
StoredObjectPointInTime,
|
StoredObjectPointInTime,
|
||||||
StoredObjectVersionWithPointInTime,
|
StoredObjectVersionWithPointInTime,
|
||||||
} from "ChillDocStoreAssets/types";
|
} from "ChillDocStoreAssets/types";
|
||||||
import UserRenderBoxBadge from "ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge.vue";
|
import UserRenderBoxBadge from "ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge.vue";
|
||||||
import { ISOToDatetime } from "ChillMainAssets/chill/js/date";
|
import { ISOToDatetime } from "ChillMainAssets/chill/js/date";
|
||||||
@@ -12,185 +12,173 @@ import DownloadButton from "ChillDocStoreAssets/vuejs/StoredObjectButton/Downloa
|
|||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
|
||||||
interface HistoryButtonListItemConfig {
|
interface HistoryButtonListItemConfig {
|
||||||
version: StoredObjectVersionWithPointInTime;
|
version: StoredObjectVersionWithPointInTime;
|
||||||
storedObject: StoredObject;
|
storedObject: StoredObject;
|
||||||
canEdit: boolean;
|
canEdit: boolean;
|
||||||
isCurrent: boolean;
|
isCurrent: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
restoreVersion: [newVersion: StoredObjectVersionWithPointInTime];
|
restoreVersion: [newVersion: StoredObjectVersionWithPointInTime];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps<HistoryButtonListItemConfig>();
|
const props = defineProps<HistoryButtonListItemConfig>();
|
||||||
|
|
||||||
const onRestore = ({
|
const onRestore = ({
|
||||||
newVersion,
|
newVersion,
|
||||||
}: {
|
}: {
|
||||||
newVersion: StoredObjectVersionWithPointInTime;
|
newVersion: StoredObjectVersionWithPointInTime;
|
||||||
}) => {
|
}) => {
|
||||||
emit("restoreVersion", { newVersion });
|
emit("restoreVersion", { newVersion });
|
||||||
};
|
};
|
||||||
|
|
||||||
const isKeptBeforeConversion = computed<boolean>(() => {
|
const isKeptBeforeConversion = computed<boolean>(() => {
|
||||||
if ("point-in-times" in props.version) {
|
if ("point-in-times" in props.version) {
|
||||||
return props.version["point-in-times"].reduce(
|
return props.version["point-in-times"].reduce(
|
||||||
(accumulator: boolean, pit: StoredObjectPointInTime) =>
|
(accumulator: boolean, pit: StoredObjectPointInTime) =>
|
||||||
accumulator || "keep-before-conversion" === pit.reason,
|
accumulator || "keep-before-conversion" === pit.reason,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const isRestored = computed<boolean>(
|
const isRestored = computed<boolean>(
|
||||||
() => props.version.version > 0 && null !== props.version["from-restored"],
|
() => props.version.version > 0 && null !== props.version["from-restored"],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isDuplicated = computed<boolean>(
|
const isDuplicated = computed<boolean>(
|
||||||
() =>
|
() => props.version.version === 0 && null !== props.version["from-restored"],
|
||||||
props.version.version === 0 && null !== props.version["from-restored"],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const classes = computed<{
|
const classes = computed<{
|
||||||
row: true;
|
row: true;
|
||||||
"row-hover": true;
|
"row-hover": true;
|
||||||
"blinking-1": boolean;
|
"blinking-1": boolean;
|
||||||
"blinking-2": boolean;
|
"blinking-2": boolean;
|
||||||
}>(() => ({
|
}>(() => ({
|
||||||
row: true,
|
row: true,
|
||||||
"row-hover": true,
|
"row-hover": true,
|
||||||
"blinking-1": props.isRestored && 0 === props.version.version % 2,
|
"blinking-1": props.isRestored && 0 === props.version.version % 2,
|
||||||
"blinking-2": props.isRestored && 1 === props.version.version % 2,
|
"blinking-2": props.isRestored && 1 === props.version.version % 2,
|
||||||
}));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="classes">
|
<div :class="classes">
|
||||||
<div
|
<div
|
||||||
class="col-12 tags"
|
class="col-12 tags"
|
||||||
v-if="
|
v-if="isCurrent || isKeptBeforeConversion || isRestored || isDuplicated"
|
||||||
isCurrent ||
|
>
|
||||||
isKeptBeforeConversion ||
|
<span class="badge bg-success" v-if="isCurrent">Version actuelle</span>
|
||||||
isRestored ||
|
<span class="badge bg-info" v-if="isKeptBeforeConversion"
|
||||||
isDuplicated
|
>Conservée avant conversion dans un autre format</span
|
||||||
"
|
>
|
||||||
>
|
<span class="badge bg-info" v-if="isRestored"
|
||||||
<span class="badge bg-success" v-if="isCurrent"
|
>Restaurée depuis la version
|
||||||
>Version actuelle</span
|
{{ version["from-restored"]?.version + 1 }}</span
|
||||||
>
|
>
|
||||||
<span class="badge bg-info" v-if="isKeptBeforeConversion"
|
<span class="badge bg-info" v-if="isDuplicated"
|
||||||
>Conservée avant conversion dans un autre format</span
|
>Dupliqué depuis un autre document</span
|
||||||
>
|
>
|
||||||
<span class="badge bg-info" v-if="isRestored"
|
|
||||||
>Restaurée depuis la version
|
|
||||||
{{ version["from-restored"]?.version + 1 }}</span
|
|
||||||
>
|
|
||||||
<span class="badge bg-info" v-if="isDuplicated"
|
|
||||||
>Dupliqué depuis un autre document</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<file-icon :type="version.type"></file-icon>
|
|
||||||
<span
|
|
||||||
><strong> #{{ version.version + 1 }} </strong></span
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-if="version.createdBy !== null && version.createdAt !== null"
|
|
||||||
><strong v-if="version.version == 0">créé par</strong
|
|
||||||
><strong v-else>modifié par</strong>
|
|
||||||
<span class="badge-user"
|
|
||||||
><UserRenderBoxBadge
|
|
||||||
:user="version.createdBy"
|
|
||||||
></UserRenderBoxBadge
|
|
||||||
></span>
|
|
||||||
<strong>à</strong>
|
|
||||||
{{
|
|
||||||
$d(ISOToDatetime(version.createdAt.datetime8601), "long")
|
|
||||||
}}</template
|
|
||||||
><template
|
|
||||||
v-if="version.createdBy === null && version.createdAt !== null"
|
|
||||||
><strong v-if="version.version == 0">Créé le</strong
|
|
||||||
><strong v-else>modifié le</strong>
|
|
||||||
{{
|
|
||||||
$d(ISOToDatetime(version.createdAt.datetime8601), "long")
|
|
||||||
}}</template
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<ul class="record_actions small slim on-version-actions">
|
|
||||||
<li v-if="canEdit && !isCurrent">
|
|
||||||
<restore-version-button
|
|
||||||
:stored-object-version="props.version"
|
|
||||||
@restore-version="onRestore"
|
|
||||||
></restore-version-button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<download-button
|
|
||||||
:stored-object="storedObject"
|
|
||||||
:at-version="version"
|
|
||||||
:classes="{
|
|
||||||
btn: true,
|
|
||||||
'btn-outline-primary': true,
|
|
||||||
'btn-sm': true,
|
|
||||||
}"
|
|
||||||
:display-action-string-in-button="false"
|
|
||||||
></download-button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<file-icon :type="version.type"></file-icon>
|
||||||
|
<span
|
||||||
|
><strong> #{{ version.version + 1 }} </strong></span
|
||||||
|
>
|
||||||
|
<template v-if="version.createdBy !== null && version.createdAt !== null"
|
||||||
|
><strong v-if="version.version == 0">créé par</strong
|
||||||
|
><strong v-else>modifié par</strong>
|
||||||
|
<span class="badge-user"
|
||||||
|
><UserRenderBoxBadge :user="version.createdBy"></UserRenderBoxBadge
|
||||||
|
></span>
|
||||||
|
<strong>à</strong>
|
||||||
|
{{
|
||||||
|
$d(ISOToDatetime(version.createdAt.datetime8601), "long")
|
||||||
|
}}</template
|
||||||
|
><template v-if="version.createdBy === null && version.createdAt !== null"
|
||||||
|
><strong v-if="version.version == 0">Créé le</strong
|
||||||
|
><strong v-else>modifié le</strong>
|
||||||
|
{{
|
||||||
|
$d(ISOToDatetime(version.createdAt.datetime8601), "long")
|
||||||
|
}}</template
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<ul class="record_actions small slim on-version-actions">
|
||||||
|
<li v-if="canEdit && !isCurrent">
|
||||||
|
<restore-version-button
|
||||||
|
:stored-object-version="props.version"
|
||||||
|
@restore-version="onRestore"
|
||||||
|
></restore-version-button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<download-button
|
||||||
|
:stored-object="storedObject"
|
||||||
|
:at-version="version"
|
||||||
|
:classes="{
|
||||||
|
btn: true,
|
||||||
|
'btn-outline-primary': true,
|
||||||
|
'btn-sm': true,
|
||||||
|
}"
|
||||||
|
:display-action-string-in-button="false"
|
||||||
|
></download-button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
div.tags {
|
div.tags {
|
||||||
span.badge:not(:last-child) {
|
span.badge:not(:last-child) {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// to make the animation restart, we have the same animation twice,
|
// to make the animation restart, we have the same animation twice,
|
||||||
// and alternate between both
|
// and alternate between both
|
||||||
.blinking-1 {
|
.blinking-1 {
|
||||||
animation-name: backgroundColorPalette-1;
|
animation-name: backgroundColorPalette-1;
|
||||||
animation-duration: 8s;
|
animation-duration: 8s;
|
||||||
animation-iteration-count: 1;
|
animation-iteration-count: 1;
|
||||||
animation-direction: normal;
|
animation-direction: normal;
|
||||||
animation-timing-function: linear;
|
animation-timing-function: linear;
|
||||||
}
|
}
|
||||||
@keyframes backgroundColorPalette-1 {
|
@keyframes backgroundColorPalette-1 {
|
||||||
0% {
|
0% {
|
||||||
background: var(--bs-chill-green-dark);
|
background: var(--bs-chill-green-dark);
|
||||||
}
|
}
|
||||||
25% {
|
25% {
|
||||||
background: var(--bs-chill-green);
|
background: var(--bs-chill-green);
|
||||||
}
|
}
|
||||||
65% {
|
65% {
|
||||||
background: var(--bs-chill-beige);
|
background: var(--bs-chill-beige);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
background: unset;
|
background: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.blinking-2 {
|
.blinking-2 {
|
||||||
animation-name: backgroundColorPalette-2;
|
animation-name: backgroundColorPalette-2;
|
||||||
animation-duration: 8s;
|
animation-duration: 8s;
|
||||||
animation-iteration-count: 1;
|
animation-iteration-count: 1;
|
||||||
animation-direction: normal;
|
animation-direction: normal;
|
||||||
animation-timing-function: linear;
|
animation-timing-function: linear;
|
||||||
}
|
}
|
||||||
@keyframes backgroundColorPalette-2 {
|
@keyframes backgroundColorPalette-2 {
|
||||||
0% {
|
0% {
|
||||||
background: var(--bs-chill-green-dark);
|
background: var(--bs-chill-green-dark);
|
||||||
}
|
}
|
||||||
25% {
|
25% {
|
||||||
background: var(--bs-chill-green);
|
background: var(--bs-chill-green);
|
||||||
}
|
}
|
||||||
65% {
|
65% {
|
||||||
background: var(--bs-chill-beige);
|
background: var(--bs-chill-beige);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
background: unset;
|
background: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -13,15 +13,15 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const dateToISO = (date: Date | null): string | null => {
|
export const dateToISO = (date: Date | null): string | null => {
|
||||||
if (null === date) {
|
if (null === date) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
date.getFullYear(),
|
date.getFullYear(),
|
||||||
(date.getMonth() + 1).toString().padStart(2, "0"),
|
(date.getMonth() + 1).toString().padStart(2, "0"),
|
||||||
date.getDate().toString().padStart(2, "0"),
|
date.getDate().toString().padStart(2, "0"),
|
||||||
].join("-");
|
].join("-");
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,21 +30,21 @@ export const dateToISO = (date: Date | null): string | null => {
|
|||||||
* **Experimental**
|
* **Experimental**
|
||||||
*/
|
*/
|
||||||
export const ISOToDate = (str: string | null): Date | null => {
|
export const ISOToDate = (str: string | null): Date | null => {
|
||||||
if (null === str) {
|
if (null === str) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ("" === str.trim()) {
|
if ("" === str.trim()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the string already contains time info, use it directly
|
// If the string already contains time info, use it directly
|
||||||
if (str.includes("T") || str.includes(" ")) {
|
if (str.includes("T") || str.includes(" ")) {
|
||||||
return new Date(str);
|
return new Date(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, parse date only
|
// Otherwise, parse date only
|
||||||
const [year, month, day] = str.split("-").map((p) => parseInt(p));
|
const [year, month, day] = str.split("-").map((p) => parseInt(p));
|
||||||
return new Date(year, month - 1, day, 0, 0, 0, 0);
|
return new Date(year, month - 1, day, 0, 0, 0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,21 +52,19 @@ export const ISOToDate = (str: string | null): Date | null => {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const ISOToDatetime = (str: string | null): Date | null => {
|
export const ISOToDatetime = (str: string | null): Date | null => {
|
||||||
if (null === str) {
|
if (null === str) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [cal, times] = str.split("T"),
|
const [cal, times] = str.split("T"),
|
||||||
[year, month, date] = cal.split("-").map((s) => parseInt(s)),
|
[year, month, date] = cal.split("-").map((s) => parseInt(s)),
|
||||||
[time, timezone] = times.split(times.charAt(8)),
|
[time, timezone] = times.split(times.charAt(8)),
|
||||||
[hours, minutes, seconds] = time.split(":").map((s) => parseInt(s));
|
[hours, minutes, seconds] = time.split(":").map((s) => parseInt(s));
|
||||||
if ("0000" === timezone) {
|
if ("0000" === timezone) {
|
||||||
return new Date(
|
return new Date(Date.UTC(year, month - 1, date, hours, minutes, seconds));
|
||||||
Date.UTC(year, month - 1, date, hours, minutes, seconds),
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Date(year, month - 1, date, hours, minutes, seconds);
|
return new Date(year, month - 1, date, hours, minutes, seconds);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,102 +72,100 @@ export const ISOToDatetime = (str: string | null): Date | null => {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const datetimeToISO = (date: Date): string => {
|
export const datetimeToISO = (date: Date): string => {
|
||||||
const cal = [
|
const cal = [
|
||||||
date.getFullYear(),
|
date.getFullYear(),
|
||||||
(date.getMonth() + 1).toString().padStart(2, "0"),
|
(date.getMonth() + 1).toString().padStart(2, "0"),
|
||||||
date.getDate().toString().padStart(2, "0"),
|
date.getDate().toString().padStart(2, "0"),
|
||||||
].join("-");
|
].join("-");
|
||||||
|
|
||||||
const time = [
|
const time = [
|
||||||
date.getHours().toString().padStart(2, "0"),
|
date.getHours().toString().padStart(2, "0"),
|
||||||
date.getMinutes().toString().padStart(2, "0"),
|
date.getMinutes().toString().padStart(2, "0"),
|
||||||
date.getSeconds().toString().padStart(2, "0"),
|
date.getSeconds().toString().padStart(2, "0"),
|
||||||
].join(":");
|
].join(":");
|
||||||
|
|
||||||
const offset = [
|
const offset = [
|
||||||
date.getTimezoneOffset() <= 0 ? "+" : "-",
|
date.getTimezoneOffset() <= 0 ? "+" : "-",
|
||||||
Math.abs(Math.floor(date.getTimezoneOffset() / 60))
|
Math.abs(Math.floor(date.getTimezoneOffset() / 60))
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(2, "0"),
|
.padStart(2, "0"),
|
||||||
":",
|
":",
|
||||||
Math.abs(date.getTimezoneOffset() % 60)
|
Math.abs(date.getTimezoneOffset() % 60)
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(2, "0"),
|
.padStart(2, "0"),
|
||||||
].join("");
|
].join("");
|
||||||
|
|
||||||
const x = cal + "T" + time + offset;
|
const x = cal + "T" + time + offset;
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const intervalDaysToISO = (days: number | string | null): string => {
|
export const intervalDaysToISO = (days: number | string | null): string => {
|
||||||
if (null === days) {
|
if (null === days) {
|
||||||
return "P0D";
|
return "P0D";
|
||||||
}
|
}
|
||||||
|
|
||||||
return `P${days}D`;
|
return `P${days}D`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const intervalISOToDays = (str: string | null): number | null => {
|
export const intervalISOToDays = (str: string | null): number | null => {
|
||||||
if (null === str) {
|
if (null === str) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("" === str.trim()) {
|
if ("" === str.trim()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let days = 0;
|
let days = 0;
|
||||||
let isDate = true;
|
let isDate = true;
|
||||||
let vstring = "";
|
let vstring = "";
|
||||||
for (let i = 0; i < str.length; i = i + 1) {
|
for (let i = 0; i < str.length; i = i + 1) {
|
||||||
if (!isDate) {
|
if (!isDate) {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
switch (str.charAt(i)) {
|
|
||||||
case "P":
|
|
||||||
isDate = true;
|
|
||||||
break;
|
|
||||||
case "T":
|
|
||||||
isDate = false;
|
|
||||||
break;
|
|
||||||
case "0":
|
|
||||||
case "1":
|
|
||||||
case "2":
|
|
||||||
case "3":
|
|
||||||
case "4":
|
|
||||||
case "5":
|
|
||||||
case "6":
|
|
||||||
case "7":
|
|
||||||
case "8":
|
|
||||||
case "9":
|
|
||||||
vstring = vstring + str.charAt(i);
|
|
||||||
break;
|
|
||||||
case "Y":
|
|
||||||
days = days + Number.parseInt(vstring) * 365;
|
|
||||||
vstring = "";
|
|
||||||
break;
|
|
||||||
case "M":
|
|
||||||
days = days + Number.parseInt(vstring) * 30;
|
|
||||||
vstring = "";
|
|
||||||
break;
|
|
||||||
case "D":
|
|
||||||
days = days + Number.parseInt(vstring);
|
|
||||||
vstring = "";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw Error(
|
|
||||||
"this character should not appears: " + str.charAt(i),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
switch (str.charAt(i)) {
|
||||||
|
case "P":
|
||||||
|
isDate = true;
|
||||||
|
break;
|
||||||
|
case "T":
|
||||||
|
isDate = false;
|
||||||
|
break;
|
||||||
|
case "0":
|
||||||
|
case "1":
|
||||||
|
case "2":
|
||||||
|
case "3":
|
||||||
|
case "4":
|
||||||
|
case "5":
|
||||||
|
case "6":
|
||||||
|
case "7":
|
||||||
|
case "8":
|
||||||
|
case "9":
|
||||||
|
vstring = vstring + str.charAt(i);
|
||||||
|
break;
|
||||||
|
case "Y":
|
||||||
|
days = days + Number.parseInt(vstring) * 365;
|
||||||
|
vstring = "";
|
||||||
|
break;
|
||||||
|
case "M":
|
||||||
|
days = days + Number.parseInt(vstring) * 30;
|
||||||
|
vstring = "";
|
||||||
|
break;
|
||||||
|
case "D":
|
||||||
|
days = days + Number.parseInt(vstring);
|
||||||
|
vstring = "";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw Error("this character should not appears: " + str.charAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return days;
|
return days;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getTimezoneOffsetString(date: Date, timeZone: string): string {
|
export function getTimezoneOffsetString(date: Date, timeZone: string): string {
|
||||||
const utcDate = new Date(date.toLocaleString("en-US", { timeZone: "UTC" }));
|
const utcDate = new Date(date.toLocaleString("en-US", { timeZone: "UTC" }));
|
||||||
const tzDate = new Date(date.toLocaleString("en-US", { timeZone }));
|
const tzDate = new Date(date.toLocaleString("en-US", { timeZone }));
|
||||||
const offsetMinutes = (utcDate.getTime() - tzDate.getTime()) / (60 * 1000);
|
const offsetMinutes = (utcDate.getTime() - tzDate.getTime()) / (60 * 1000);
|
||||||
|
|
||||||
// Inverser le signe pour avoir la convention ±HH:MM
|
// Inverser le signe pour avoir la convention ±HH:MM
|
||||||
@@ -180,4 +176,3 @@ export function getTimezoneOffsetString(date: Date, timeZone: string): string {
|
|||||||
|
|
||||||
return `${sign}${hours}:${minutes}`;
|
return `${sign}${hours}:${minutes}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
Scope,
|
Scope,
|
||||||
ValidationExceptionInterface,
|
ValidationExceptionInterface,
|
||||||
ValidationProblemFromMap,
|
ValidationProblemFromMap,
|
||||||
ViolationFromMap
|
ViolationFromMap,
|
||||||
} from "../../types";
|
} from "../../types";
|
||||||
|
|
||||||
export type body = Record<string, boolean | string | number | null>;
|
export type body = Record<string, boolean | string | number | null>;
|
||||||
@@ -32,11 +32,11 @@ export interface TransportExceptionInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ValidationException<
|
export class ValidationException<
|
||||||
M extends Record<string, Record<string, string|number>> = Record<
|
M extends Record<string, Record<string, string | number>> = Record<
|
||||||
string,
|
string,
|
||||||
Record<string, string|number>
|
Record<string, string | number>
|
||||||
>,
|
>,
|
||||||
>
|
>
|
||||||
extends Error
|
extends Error
|
||||||
implements ValidationExceptionInterface<M>
|
implements ValidationExceptionInterface<M>
|
||||||
{
|
{
|
||||||
@@ -68,7 +68,10 @@ export class ValidationException<
|
|||||||
|
|
||||||
this.byProperty = problem.violations.reduce(
|
this.byProperty = problem.violations.reduce(
|
||||||
(acc, v) => {
|
(acc, v) => {
|
||||||
const key = v.propertyPath.replace('/\[\d+\]$/', "") as Extract<keyof M, string>;
|
const key = v.propertyPath.replace("/\[\d+\]$/", "") as Extract<
|
||||||
|
keyof M,
|
||||||
|
string
|
||||||
|
>;
|
||||||
(acc[key] ||= []).push(v.title);
|
(acc[key] ||= []).push(v.title);
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
@@ -80,28 +83,27 @@ export class ValidationException<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
violationsByNormalizedProperty(property: Extract<keyof M, string>): ViolationFromMap<M>[] {
|
violationsByNormalizedProperty(
|
||||||
return this.violationsList.filter((v) => v.propertyPath.replace(/\[\d+\]$/, "") === property);
|
property: Extract<keyof M, string>,
|
||||||
|
): ViolationFromMap<M>[] {
|
||||||
|
return this.violationsList.filter(
|
||||||
|
(v) => v.propertyPath.replace(/\[\d+\]$/, "") === property,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
violationsByNormalizedPropertyAndParams<
|
violationsByNormalizedPropertyAndParams<
|
||||||
P extends Extract<keyof M, string>,
|
P extends Extract<keyof M, string>,
|
||||||
K extends Extract<keyof M[P], string>
|
K extends Extract<keyof M[P], string>,
|
||||||
>(
|
>(property: P, param: K, param_value: M[P][K]): ViolationFromMap<M>[] {
|
||||||
property: P,
|
|
||||||
param: K,
|
|
||||||
param_value: M[P][K]
|
|
||||||
): ViolationFromMap<M>[]
|
|
||||||
{
|
|
||||||
const list = this.violationsByNormalizedProperty(property);
|
const list = this.violationsByNormalizedProperty(property);
|
||||||
|
|
||||||
return list.filter(
|
return list.filter(
|
||||||
(v): boolean =>
|
(v): boolean =>
|
||||||
!!v.parameters &&
|
!!v.parameters &&
|
||||||
// `with_parameter in v.parameters` check indexing
|
// `with_parameter in v.parameters` check indexing
|
||||||
param in v.parameters &&
|
param in v.parameters &&
|
||||||
// the cast is safe, because we have overloading that bind the types
|
// the cast is safe, because we have overloading that bind the types
|
||||||
(v.parameters as M[P])[param] === param_value
|
(v.parameters as M[P])[param] === param_value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,9 +112,9 @@ export class ValidationException<
|
|||||||
* Check that the exception is a ValidationExceptionInterface
|
* Check that the exception is a ValidationExceptionInterface
|
||||||
* @param x
|
* @param x
|
||||||
*/
|
*/
|
||||||
export function isValidationException<M extends Record<string, Record<string, string|number>>>(
|
export function isValidationException<
|
||||||
x: unknown,
|
M extends Record<string, Record<string, string | number>>,
|
||||||
): x is ValidationExceptionInterface<M> {
|
>(x: unknown): x is ValidationExceptionInterface<M> {
|
||||||
return (
|
return (
|
||||||
x instanceof ValidationException ||
|
x instanceof ValidationException ||
|
||||||
(typeof x === "object" &&
|
(typeof x === "object" &&
|
||||||
@@ -147,8 +149,7 @@ export interface AccessExceptionInterface extends TransportExceptionInterface {
|
|||||||
violations: string[];
|
violations: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NotFoundExceptionInterface
|
export interface NotFoundExceptionInterface extends TransportExceptionInterface {
|
||||||
extends TransportExceptionInterface {
|
|
||||||
name: "NotFoundException";
|
name: "NotFoundException";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,8 +160,7 @@ export interface ServerExceptionInterface extends TransportExceptionInterface {
|
|||||||
body: string;
|
body: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConflictHttpExceptionInterface
|
export interface ConflictHttpExceptionInterface extends TransportExceptionInterface {
|
||||||
extends TransportExceptionInterface {
|
|
||||||
name: "ConflictHttpException";
|
name: "ConflictHttpException";
|
||||||
violations: string[];
|
violations: string[];
|
||||||
}
|
}
|
||||||
@@ -306,9 +306,9 @@ export interface ConflictHttpExceptionInterface
|
|||||||
export const makeFetch = async <
|
export const makeFetch = async <
|
||||||
Input,
|
Input,
|
||||||
Output,
|
Output,
|
||||||
M extends Record<string, Record<string, string|number>> = Record<
|
M extends Record<string, Record<string, string | number>> = Record<
|
||||||
string,
|
string,
|
||||||
Record<string, string|number>
|
Record<string, string | number>
|
||||||
>,
|
>,
|
||||||
>(
|
>(
|
||||||
method: "POST" | "GET" | "PUT" | "PATCH" | "DELETE",
|
method: "POST" | "GET" | "PUT" | "PATCH" | "DELETE",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Gender, GenderTranslation} from "ChillMainAssets/types";
|
import { Gender, GenderTranslation } from "ChillMainAssets/types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates a given gender object into its corresponding gender translation string.
|
* Translates a given gender object into its corresponding gender translation string.
|
||||||
@@ -7,8 +7,7 @@ import {Gender, GenderTranslation} from "ChillMainAssets/types";
|
|||||||
* @return {GenderTranslation} Returns the gender translation string corresponding to the provided gender,
|
* @return {GenderTranslation} Returns the gender translation string corresponding to the provided gender,
|
||||||
* or "unknown" if the gender is null.
|
* or "unknown" if the gender is null.
|
||||||
*/
|
*/
|
||||||
export function toGenderTranslation(gender: Gender|null): GenderTranslation
|
export function toGenderTranslation(gender: Gender | null): GenderTranslation {
|
||||||
{
|
|
||||||
if (null === gender) {
|
if (null === gender) {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
* @return {string} The "returnPath" from the query string, or the fallback path if "returnPath" is not present.
|
* @return {string} The "returnPath" from the query string, or the fallback path if "returnPath" is not present.
|
||||||
*/
|
*/
|
||||||
export function returnPathOr(fallbackPath: string): string {
|
export function returnPathOr(fallbackPath: string): string {
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
const returnPath = urlParams.get("returnPath");
|
const returnPath = urlParams.get("returnPath");
|
||||||
|
|
||||||
return returnPath ?? fallbackPath;
|
return returnPath ?? fallbackPath;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ import { EntityWorkflow } from "ChillMainAssets/types";
|
|||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
|
||||||
export const fetchWorkflow = async (
|
export const fetchWorkflow = async (
|
||||||
workflowId: number,
|
workflowId: number,
|
||||||
): Promise<EntityWorkflow> => {
|
): Promise<EntityWorkflow> => {
|
||||||
try {
|
try {
|
||||||
return await makeFetch<null, EntityWorkflow>(
|
return await makeFetch<null, EntityWorkflow>(
|
||||||
"GET",
|
"GET",
|
||||||
`/api/1.0/main/workflow/${workflowId}.json`,
|
`/api/1.0/main/workflow/${workflowId}.json`,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to fetch workflow ${workflowId}:`, error);
|
console.error(`Failed to fetch workflow ${workflowId}:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
GenericDoc,
|
GenericDoc,
|
||||||
isGenericDocWithStoredObject,
|
isGenericDocWithStoredObject,
|
||||||
} from "ChillDocStoreAssets/types/generic_doc";
|
} from "ChillDocStoreAssets/types/generic_doc";
|
||||||
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
|
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
|
||||||
import { CreatableEntityType } from "ChillPersonAssets/types";
|
import { CreatableEntityType } from "ChillPersonAssets/types";
|
||||||
import {ThirdpartyCompany} from "../../../ChillThirdPartyBundle/Resources/public/types";
|
import { ThirdpartyCompany } from "../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
import { Person } from "../../../ChillPersonBundle/Resources/public/types";
|
import { Person } from "../../../ChillPersonBundle/Resources/public/types";
|
||||||
|
|
||||||
export interface DateTime {
|
export interface DateTime {
|
||||||
@@ -38,7 +38,6 @@ export interface SetCivility {
|
|||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gender translation.
|
* Gender translation.
|
||||||
*
|
*
|
||||||
@@ -282,74 +281,74 @@ export interface WorkflowAttachment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type AttachmentWithDocAndStored = WorkflowAttachment & {
|
export type AttachmentWithDocAndStored = WorkflowAttachment & {
|
||||||
genericDoc: GenericDoc & { storedObject: StoredObject };
|
genericDoc: GenericDoc & { storedObject: StoredObject };
|
||||||
};
|
};
|
||||||
|
|
||||||
export function isAttachmentWithDocAndStored(
|
export function isAttachmentWithDocAndStored(
|
||||||
a: WorkflowAttachment,
|
a: WorkflowAttachment,
|
||||||
): a is AttachmentWithDocAndStored {
|
): a is AttachmentWithDocAndStored {
|
||||||
return (
|
return (
|
||||||
isWorkflowAttachmentWithGenericDoc(a) &&
|
isWorkflowAttachmentWithGenericDoc(a) &&
|
||||||
isGenericDocWithStoredObject(a.genericDoc)
|
isGenericDocWithStoredObject(a.genericDoc)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isWorkflowAttachmentWithGenericDoc(
|
export function isWorkflowAttachmentWithGenericDoc(
|
||||||
attachment: WorkflowAttachment,
|
attachment: WorkflowAttachment,
|
||||||
): attachment is WorkflowAttachment & { genericDoc: GenericDoc } {
|
): attachment is WorkflowAttachment & { genericDoc: GenericDoc } {
|
||||||
return attachment.genericDoc !== null;
|
return attachment.genericDoc !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Workflow {
|
export interface Workflow {
|
||||||
name: string;
|
name: string;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityWorkflowStep {
|
export interface EntityWorkflowStep {
|
||||||
type: "entity_workflow_step";
|
type: "entity_workflow_step";
|
||||||
id: number;
|
id: number;
|
||||||
comment: string;
|
comment: string;
|
||||||
currentStep: StepDefinition;
|
currentStep: StepDefinition;
|
||||||
isFinal: boolean;
|
isFinal: boolean;
|
||||||
isFreezed: boolean;
|
isFreezed: boolean;
|
||||||
isFinalized: boolean;
|
isFinalized: boolean;
|
||||||
transitionPrevious: Transition | null;
|
transitionPrevious: Transition | null;
|
||||||
transitionAfter: Transition | null;
|
transitionAfter: Transition | null;
|
||||||
previousId: number | null;
|
previousId: number | null;
|
||||||
nextId: number | null;
|
nextId: number | null;
|
||||||
transitionPreviousBy: User | null;
|
transitionPreviousBy: User | null;
|
||||||
transitionPreviousAt: DateTime | null;
|
transitionPreviousAt: DateTime | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Transition {
|
export interface Transition {
|
||||||
name: string;
|
name: string;
|
||||||
text: string;
|
text: string;
|
||||||
isForward: boolean;
|
isForward: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StepDefinition {
|
export interface StepDefinition {
|
||||||
name: string;
|
name: string;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityWorkflow {
|
export interface EntityWorkflow {
|
||||||
type: "entity_workflow";
|
type: "entity_workflow";
|
||||||
id: number;
|
id: number;
|
||||||
relatedEntityClass: string;
|
relatedEntityClass: string;
|
||||||
relatedEntityId: number;
|
relatedEntityId: number;
|
||||||
workflow: Workflow;
|
workflow: Workflow;
|
||||||
currentStep: EntityWorkflowStep;
|
currentStep: EntityWorkflowStep;
|
||||||
steps: EntityWorkflowStep[];
|
steps: EntityWorkflowStep[];
|
||||||
datas: WorkflowData;
|
datas: WorkflowData;
|
||||||
title: string;
|
title: string;
|
||||||
isOnHoldAtCurrentStep: boolean;
|
isOnHoldAtCurrentStep: boolean;
|
||||||
_permissions: {
|
_permissions: {
|
||||||
CHILL_MAIN_WORKFLOW_ATTACHMENT_EDIT: boolean;
|
CHILL_MAIN_WORKFLOW_ATTACHMENT_EDIT: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkflowData {
|
export interface WorkflowData {
|
||||||
persons: Person[];
|
persons: Person[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExportGeneration {
|
export interface ExportGeneration {
|
||||||
@@ -380,17 +379,20 @@ export type DynamicKeys<M extends Record<string, Record<string, unknown>>> =
|
|||||||
|
|
||||||
type NormalizeKey<K extends string> = K extends `${infer B}[${number}]` ? B : K;
|
type NormalizeKey<K extends string> = K extends `${infer B}[${number}]` ? B : K;
|
||||||
|
|
||||||
export type ViolationFromMap<M extends Record<string, Record<string, unknown>>> = {
|
export type ViolationFromMap<
|
||||||
[K in DynamicKeys<M> & string]: { // <- note le "& string" ici
|
M extends Record<string, Record<string, unknown>>,
|
||||||
|
> = {
|
||||||
|
[K in DynamicKeys<M> & string]: {
|
||||||
|
// <- note le "& string" ici
|
||||||
propertyPath: K;
|
propertyPath: K;
|
||||||
title: string;
|
title: string;
|
||||||
parameters?: M[NormalizeKey<K>];
|
parameters?: M[NormalizeKey<K>];
|
||||||
type?: string;
|
type?: string;
|
||||||
}
|
};
|
||||||
}[DynamicKeys<M> & string];
|
}[DynamicKeys<M> & string];
|
||||||
|
|
||||||
export type ValidationProblemFromMap<
|
export type ValidationProblemFromMap<
|
||||||
M extends Record<string, Record<string, string|number>>,
|
M extends Record<string, Record<string, string | number>>,
|
||||||
> = {
|
> = {
|
||||||
type: string;
|
type: string;
|
||||||
title: string;
|
title: string;
|
||||||
@@ -399,9 +401,9 @@ export type ValidationProblemFromMap<
|
|||||||
} & Record<string, unknown>;
|
} & Record<string, unknown>;
|
||||||
|
|
||||||
export interface ValidationExceptionInterface<
|
export interface ValidationExceptionInterface<
|
||||||
M extends Record<string, Record<string, string|number>> = Record<
|
M extends Record<string, Record<string, string | number>> = Record<
|
||||||
string,
|
string,
|
||||||
Record<string, string|number>
|
Record<string, string | number>
|
||||||
>,
|
>,
|
||||||
> extends Error {
|
> extends Error {
|
||||||
name: "ValidationException";
|
name: "ValidationException";
|
||||||
@@ -418,15 +420,17 @@ export interface ValidationExceptionInterface<
|
|||||||
/** Indexing by property (useful for display by field) */
|
/** Indexing by property (useful for display by field) */
|
||||||
byProperty: Record<Extract<keyof M, string>, string[]>;
|
byProperty: Record<Extract<keyof M, string>, string[]>;
|
||||||
|
|
||||||
violationsByNormalizedProperty(property: Extract<keyof M, string>): ViolationFromMap<M>[];
|
violationsByNormalizedProperty(
|
||||||
|
property: Extract<keyof M, string>,
|
||||||
|
): ViolationFromMap<M>[];
|
||||||
|
|
||||||
violationsByNormalizedPropertyAndParams<
|
violationsByNormalizedPropertyAndParams<
|
||||||
P extends Extract<keyof M, string>,
|
P extends Extract<keyof M, string>,
|
||||||
K extends Extract<keyof M[P], string>
|
K extends Extract<keyof M[P], string>,
|
||||||
>(
|
>(
|
||||||
property: P,
|
property: P,
|
||||||
param: K,
|
param: K,
|
||||||
param_value: M[P][K]
|
param_value: M[P][K],
|
||||||
): ViolationFromMap<M>[];
|
): ViolationFromMap<M>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,8 +439,7 @@ export interface AccessExceptionInterface extends TransportExceptionInterface {
|
|||||||
violations: string[];
|
violations: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NotFoundExceptionInterface
|
export interface NotFoundExceptionInterface extends TransportExceptionInterface {
|
||||||
extends TransportExceptionInterface {
|
|
||||||
name: "NotFoundException";
|
name: "NotFoundException";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,8 +450,7 @@ export interface ServerExceptionInterface extends TransportExceptionInterface {
|
|||||||
body: string;
|
body: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConflictHttpExceptionInterface
|
export interface ConflictHttpExceptionInterface extends TransportExceptionInterface {
|
||||||
extends TransportExceptionInterface {
|
|
||||||
name: "ConflictHttpException";
|
name: "ConflictHttpException";
|
||||||
violations: string[];
|
violations: string[];
|
||||||
}
|
}
|
||||||
@@ -496,16 +498,16 @@ export interface TabDefinition {
|
|||||||
counter: () => number;
|
counter: () => number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateComponentConfigGeneral = {
|
export interface CreateComponentConfigGeneral {
|
||||||
action: 'create';
|
action: "create";
|
||||||
allowedTypes: CreatableEntityType[];
|
allowedTypes: CreatableEntityType[];
|
||||||
query: string;
|
query: string;
|
||||||
parent: null;
|
parent: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateComponentThirdPartyAddContact = {
|
export interface CreateComponentThirdPartyAddContact {
|
||||||
action: 'addContact';
|
action: "addContact";
|
||||||
allowedTypes: readonly ['thirdparty'];
|
allowedTypes: readonly ["thirdparty"];
|
||||||
query: string;
|
query: string;
|
||||||
parent: ThirdpartyCompany;
|
parent: ThirdpartyCompany;
|
||||||
}
|
}
|
||||||
@@ -513,8 +515,9 @@ export type CreateComponentThirdPartyAddContact = {
|
|||||||
/**
|
/**
|
||||||
* Configuration for the CreateModal and Create component
|
* Configuration for the CreateModal and Create component
|
||||||
*/
|
*/
|
||||||
export type CreateComponentConfig = CreateComponentConfigGeneral | CreateComponentThirdPartyAddContact;
|
export type CreateComponentConfig =
|
||||||
|
| CreateComponentConfigGeneral
|
||||||
|
| CreateComponentThirdPartyAddContact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Possible states for the WaitingScreen Component.
|
* Possible states for the WaitingScreen Component.
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
trans,
|
trans,
|
||||||
EXPORT_GENERATION_EXPORT_GENERATION_IS_PENDING,
|
EXPORT_GENERATION_EXPORT_GENERATION_IS_PENDING,
|
||||||
EXPORT_GENERATION_TOO_MANY_RETRIES,
|
EXPORT_GENERATION_TOO_MANY_RETRIES,
|
||||||
EXPORT_GENERATION_ERROR_WHILE_GENERATING_EXPORT,
|
EXPORT_GENERATION_ERROR_WHILE_GENERATING_EXPORT,
|
||||||
EXPORT_GENERATION_EXPORT_READY,
|
EXPORT_GENERATION_EXPORT_READY,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
|
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
|
||||||
@@ -14,9 +14,9 @@ import WaitingScreen from "../_components/WaitingScreen.vue";
|
|||||||
import { ExportGeneration, WaitingScreenState } from "ChillMainAssets/types";
|
import { ExportGeneration, WaitingScreenState } from "ChillMainAssets/types";
|
||||||
|
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
exportGenerationId: string;
|
exportGenerationId: string;
|
||||||
title: string;
|
title: string;
|
||||||
createdDate: string;
|
createdDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<AppProps>();
|
const props = defineProps<AppProps>();
|
||||||
@@ -24,25 +24,25 @@ const props = defineProps<AppProps>();
|
|||||||
const exportGeneration = ref<ExportGeneration | null>(null);
|
const exportGeneration = ref<ExportGeneration | null>(null);
|
||||||
|
|
||||||
const status = computed<StoredObjectStatus>(
|
const status = computed<StoredObjectStatus>(
|
||||||
() => exportGeneration.value?.status ?? "pending",
|
() => exportGeneration.value?.status ?? "pending",
|
||||||
);
|
);
|
||||||
const storedObject = computed<null | StoredObject>(() => {
|
const storedObject = computed<null | StoredObject>(() => {
|
||||||
if (exportGeneration.value === null) {
|
if (exportGeneration.value === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return exportGeneration.value?.storedObject;
|
return exportGeneration.value?.storedObject;
|
||||||
});
|
});
|
||||||
|
|
||||||
const isPending = computed<boolean>(() => status.value === "pending");
|
const isPending = computed<boolean>(() => status.value === "pending");
|
||||||
const filename = computed<string>(() => `${props.title}-${props.createdDate}`);
|
const filename = computed<string>(() => `${props.title}-${props.createdDate}`);
|
||||||
|
|
||||||
const state = computed<WaitingScreenState>((): WaitingScreenState => {
|
const state = computed<WaitingScreenState>((): WaitingScreenState => {
|
||||||
if (status.value === "empty") {
|
if (status.value === "empty") {
|
||||||
return "pending";
|
return "pending";
|
||||||
}
|
}
|
||||||
|
|
||||||
return status.value;
|
return status.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,69 +56,69 @@ let tryiesForReady = ref<number>(0);
|
|||||||
const maxTryiesForReady = 120;
|
const maxTryiesForReady = 120;
|
||||||
|
|
||||||
const checkForReady = function (): void {
|
const checkForReady = function (): void {
|
||||||
if (
|
if (
|
||||||
"ready" === status.value ||
|
"ready" === status.value ||
|
||||||
"empty" === status.value ||
|
"empty" === status.value ||
|
||||||
"failure" === status.value ||
|
"failure" === status.value ||
|
||||||
// stop reloading if the page stays opened for a long time
|
// stop reloading if the page stays opened for a long time
|
||||||
tryiesForReady.value > maxTryiesForReady
|
tryiesForReady.value > maxTryiesForReady
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tryiesForReady.value = tryiesForReady.value + 1;
|
tryiesForReady.value = tryiesForReady.value + 1;
|
||||||
setTimeout(onObjectNewStatusCallback, 5000);
|
setTimeout(onObjectNewStatusCallback, 5000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onObjectNewStatusCallback = async function (): Promise<void> {
|
const onObjectNewStatusCallback = async function (): Promise<void> {
|
||||||
exportGeneration.value = await fetchExportGenerationStatus(
|
exportGeneration.value = await fetchExportGenerationStatus(
|
||||||
props.exportGenerationId,
|
props.exportGenerationId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isPending.value) {
|
|
||||||
checkForReady();
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (isPending.value) {
|
||||||
|
checkForReady();
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
onObjectNewStatusCallback();
|
onObjectNewStatusCallback();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<WaitingScreen :state="state">
|
<WaitingScreen :state="state">
|
||||||
<template v-slot:pending>
|
<template v-slot:pending>
|
||||||
<p>
|
<p>
|
||||||
{{ trans(EXPORT_GENERATION_EXPORT_GENERATION_IS_PENDING) }}
|
{{ trans(EXPORT_GENERATION_EXPORT_GENERATION_IS_PENDING) }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:stopped>
|
<template v-slot:stopped>
|
||||||
<p>
|
<p>
|
||||||
{{ trans(EXPORT_GENERATION_TOO_MANY_RETRIES) }}
|
{{ trans(EXPORT_GENERATION_TOO_MANY_RETRIES) }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:failure>
|
<template v-slot:failure>
|
||||||
<p>
|
<p>
|
||||||
{{ trans(EXPORT_GENERATION_ERROR_WHILE_GENERATING_EXPORT) }}
|
{{ trans(EXPORT_GENERATION_ERROR_WHILE_GENERATING_EXPORT) }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:ready>
|
<template v-slot:ready>
|
||||||
<p>
|
<p>
|
||||||
{{ trans(EXPORT_GENERATION_EXPORT_READY) }}
|
{{ trans(EXPORT_GENERATION_EXPORT_READY) }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p v-if="storedObject !== null">
|
<p v-if="storedObject !== null">
|
||||||
<document-action-buttons-group
|
<document-action-buttons-group
|
||||||
:stored-object="storedObject"
|
:stored-object="storedObject"
|
||||||
:filename="filename"
|
:filename="filename"
|
||||||
></document-action-buttons-group>
|
></document-action-buttons-group>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</WaitingScreen>
|
</WaitingScreen>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ import { CreatableEntityType, Person } from "ChillPersonAssets/types";
|
|||||||
import { CreateComponentConfig } from "ChillMainAssets/types";
|
import { CreateComponentConfig } from "ChillMainAssets/types";
|
||||||
import PersonEdit from "ChillPersonAssets/vuejs/_components/OnTheFly/PersonEdit.vue";
|
import PersonEdit from "ChillPersonAssets/vuejs/_components/OnTheFly/PersonEdit.vue";
|
||||||
import ThirdPartyEdit from "ChillThirdPartyAssets/vuejs/_components/OnTheFly/ThirdPartyEdit.vue";
|
import ThirdPartyEdit from "ChillThirdPartyAssets/vuejs/_components/OnTheFly/ThirdPartyEdit.vue";
|
||||||
import {Thirdparty} from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
import { Thirdparty } from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
|
|
||||||
const props = withDefaults(defineProps<CreateComponentConfig>(), {
|
const props = withDefaults(defineProps<CreateComponentConfig>(), {
|
||||||
action: "create",
|
action: "create",
|
||||||
@@ -69,11 +69,10 @@ const props = withDefaults(defineProps<CreateComponentConfig>(), {
|
|||||||
parent: null,
|
parent: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit =
|
const emit = defineEmits<{
|
||||||
defineEmits<{
|
(e: "onPersonCreated", payload: { person: Person }): void;
|
||||||
(e: "onPersonCreated", payload: { person: Person }): void,
|
(e: "onThirdPartyCreated", payload: { thirdParty: Thirdparty }): void;
|
||||||
(e: "onThirdPartyCreated", payload: { thirdParty: Thirdparty }): void,
|
}>();
|
||||||
}>();
|
|
||||||
|
|
||||||
const type = ref<CreatableEntityType | null>(null);
|
const type = ref<CreatableEntityType | null>(null);
|
||||||
|
|
||||||
@@ -88,8 +87,8 @@ const radioType = computed<CreatableEntityType | null>({
|
|||||||
type PersonEditComponent = InstanceType<typeof PersonEdit>;
|
type PersonEditComponent = InstanceType<typeof PersonEdit>;
|
||||||
type ThirdPartyEditComponent = InstanceType<typeof ThirdPartyEdit>;
|
type ThirdPartyEditComponent = InstanceType<typeof ThirdPartyEdit>;
|
||||||
|
|
||||||
const castPerson = ref<PersonEditComponent|null>(null);
|
const castPerson = ref<PersonEditComponent | null>(null);
|
||||||
const castThirdparty = ref<ThirdPartyEditComponent|null>(null);
|
const castThirdparty = ref<ThirdPartyEditComponent | null>(null);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
type.value =
|
type.value =
|
||||||
@@ -106,7 +105,7 @@ const containsThirdParty = computed<boolean>(() =>
|
|||||||
props.allowedTypes.includes("thirdparty"),
|
props.allowedTypes.includes("thirdparty"),
|
||||||
);
|
);
|
||||||
const containsPerson = computed<boolean>(() => {
|
const containsPerson = computed<boolean>(() => {
|
||||||
if (props.action === 'addContact') {
|
if (props.action === "addContact") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return props.allowedTypes.includes("person");
|
return props.allowedTypes.includes("person");
|
||||||
@@ -115,7 +114,10 @@ const containsPerson = computed<boolean>(() => {
|
|||||||
function save(): void {
|
function save(): void {
|
||||||
if (radioType.value === "person" && castPerson.value !== null) {
|
if (radioType.value === "person" && castPerson.value !== null) {
|
||||||
castPerson.value.postPerson();
|
castPerson.value.postPerson();
|
||||||
} else if (radioType.value === "thirdparty" && castThirdparty.value !== null) {
|
} else if (
|
||||||
|
radioType.value === "thirdparty" &&
|
||||||
|
castThirdparty.value !== null
|
||||||
|
) {
|
||||||
castThirdparty.value.postThirdParty();
|
castThirdparty.value.postThirdParty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CreateComponentConfig } from "ChillMainAssets/types";
|
|||||||
import { trans, SAVE } from "translator";
|
import { trans, SAVE } from "translator";
|
||||||
import { useTemplateRef } from "vue";
|
import { useTemplateRef } from "vue";
|
||||||
import { Person } from "ChillPersonAssets/types";
|
import { Person } from "ChillPersonAssets/types";
|
||||||
import {Thirdparty} from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
import { Thirdparty } from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "onPersonCreated", payload: { person: Person }): void;
|
(e: "onPersonCreated", payload: { person: Person }): void;
|
||||||
@@ -13,20 +13,24 @@ const emit = defineEmits<{
|
|||||||
(e: "close"): void;
|
(e: "close"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps<CreateComponentConfig & {modalTitle: string}>();
|
const props = defineProps<CreateComponentConfig & { modalTitle: string }>();
|
||||||
const modalDialogClass = { "modal-xl": true, "modal-scrollable": true };
|
const modalDialogClass = { "modal-xl": true, "modal-scrollable": true };
|
||||||
|
|
||||||
type CreateComponentType = InstanceType<typeof Create>;
|
type CreateComponentType = InstanceType<typeof Create>;
|
||||||
|
|
||||||
const create = useTemplateRef<CreateComponentType>("create");
|
const create = useTemplateRef<CreateComponentType>("create");
|
||||||
|
|
||||||
const onPersonCreated = ({person}: {person: Person}): void => {
|
const onPersonCreated = ({ person }: { person: Person }): void => {
|
||||||
emit("onPersonCreated", {person});
|
emit("onPersonCreated", { person });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onThirdPartyCreated = ({thirdParty}: {thirdParty: Thirdparty}): void => {
|
const onThirdPartyCreated = ({
|
||||||
emit("onThirdPartyCreated", {thirdParty: thirdParty});
|
thirdParty,
|
||||||
}
|
}: {
|
||||||
|
thirdParty: Thirdparty;
|
||||||
|
}): void => {
|
||||||
|
emit("onThirdPartyCreated", { thirdParty: thirdParty });
|
||||||
|
};
|
||||||
|
|
||||||
function save(): void {
|
function save(): void {
|
||||||
console.log("save from CreateModal");
|
console.log("save from CreateModal");
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, defineEmits, defineProps, useTemplateRef} from "vue";
|
import { ref, computed, defineEmits, defineProps, useTemplateRef } from "vue";
|
||||||
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
||||||
import OnTheFlyCreate from "./Create.vue";
|
import OnTheFlyCreate from "./Create.vue";
|
||||||
import OnTheFlyPerson from "ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue";
|
import OnTheFlyPerson from "ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue";
|
||||||
@@ -177,14 +177,19 @@ const props = withDefaults(defineProps<OnTheFlyComponentProps>(), {
|
|||||||
query: "",
|
query: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit =
|
||||||
(e: "saveFormOnTheFly", payload: { type: string | undefined; data: any }): void;
|
defineEmits<
|
||||||
}>();
|
(
|
||||||
|
e: "saveFormOnTheFly",
|
||||||
|
payload: { type: string | undefined; data: any },
|
||||||
|
) => void
|
||||||
|
>();
|
||||||
|
|
||||||
type castEditPersonType = InstanceType<typeof PersonEdit>;
|
type castEditPersonType = InstanceType<typeof PersonEdit>;
|
||||||
type castEditThirdPartyType = InstanceType<typeof ThirdPartyEdit>;
|
type castEditThirdPartyType = InstanceType<typeof ThirdPartyEdit>;
|
||||||
const castEditPerson = useTemplateRef<castEditPersonType>('castEditPerson')
|
const castEditPerson = useTemplateRef<castEditPersonType>("castEditPerson");
|
||||||
const castEditThirdParty = useTemplateRef<castEditThirdPartyType>('castEditThirdParty');
|
const castEditThirdParty =
|
||||||
|
useTemplateRef<castEditThirdPartyType>("castEditThirdParty");
|
||||||
|
|
||||||
const modal = ref<{ showModal: boolean; modalDialogClass: string }>({
|
const modal = ref<{ showModal: boolean; modalDialogClass: string }>({
|
||||||
showModal: false,
|
showModal: false,
|
||||||
@@ -234,35 +239,35 @@ const titleAction = computed<string>(() => {
|
|||||||
|
|
||||||
const titleCreate = computed<string>(() => {
|
const titleCreate = computed<string>(() => {
|
||||||
if (typeof props.allowedTypes === "undefined") {
|
if (typeof props.allowedTypes === "undefined") {
|
||||||
return trans(ONTHEFLY_CREATE_TITLE_DEFAULT)
|
return trans(ONTHEFLY_CREATE_TITLE_DEFAULT);
|
||||||
}
|
}
|
||||||
return props.allowedTypes.every((t: EntityType) => t === "person")
|
return props.allowedTypes.every((t: EntityType) => t === "person")
|
||||||
? (trans(ONTHEFLY_CREATE_TITLE_PERSON))
|
? trans(ONTHEFLY_CREATE_TITLE_PERSON)
|
||||||
: props.allowedTypes.every((t: EntityType) => t === "thirdparty")
|
: props.allowedTypes.every((t: EntityType) => t === "thirdparty")
|
||||||
? (trans(ONTHEFLY_CREATE_TITLE_THIRDPARTY))
|
? trans(ONTHEFLY_CREATE_TITLE_THIRDPARTY)
|
||||||
: (trans(ONTHEFLY_CREATE_TITLE_DEFAULT));
|
: trans(ONTHEFLY_CREATE_TITLE_DEFAULT);
|
||||||
});
|
});
|
||||||
|
|
||||||
const titleModal = computed<string>(() => {
|
const titleModal = computed<string>(() => {
|
||||||
switch (props.action) {
|
switch (props.action) {
|
||||||
case "show":
|
case "show":
|
||||||
if (props.type == "person") {
|
if (props.type == "person") {
|
||||||
return trans(ONTHEFLY_SHOW_PERSON)
|
return trans(ONTHEFLY_SHOW_PERSON);
|
||||||
} else if (props.type == "thirdparty") {
|
} else if (props.type == "thirdparty") {
|
||||||
return trans(ONTHEFLY_SHOW_THIRDPARTY)
|
return trans(ONTHEFLY_SHOW_THIRDPARTY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "edit":
|
case "edit":
|
||||||
if (props.type == "person") {
|
if (props.type == "person") {
|
||||||
return trans(ONTHEFLY_EDIT_PERSON)
|
return trans(ONTHEFLY_EDIT_PERSON);
|
||||||
} else if (props.type == "thirdparty") {
|
} else if (props.type == "thirdparty") {
|
||||||
return trans(ONTHEFLY_EDIT_THIRDPARTY)
|
return trans(ONTHEFLY_EDIT_THIRDPARTY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "create":
|
case "create":
|
||||||
return titleCreate.value;
|
return titleCreate.value;
|
||||||
case "addContact":
|
case "addContact":
|
||||||
return trans(THIRDPARTY_ADDCONTACT_TITLE)
|
return trans(THIRDPARTY_ADDCONTACT_TITLE);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -311,7 +316,10 @@ function openModal(): void {
|
|||||||
modal.value.showModal = true;
|
modal.value.showModal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildLocation(id: string | number | undefined, type: EntityType | undefined): string | undefined {
|
function buildLocation(
|
||||||
|
id: string | number | undefined,
|
||||||
|
type: EntityType | undefined,
|
||||||
|
): string | undefined {
|
||||||
if (type === "person") {
|
if (type === "person") {
|
||||||
return encodeURI(`/fr/person/${id}/general${getReturnPath.value}`);
|
return encodeURI(`/fr/person/${id}/general${getReturnPath.value}`);
|
||||||
} else if (type === "thirdparty") {
|
} else if (type === "thirdparty") {
|
||||||
@@ -324,17 +332,16 @@ async function saveAction() {
|
|||||||
if (props.type === "person") {
|
if (props.type === "person") {
|
||||||
const person = await castEditPerson.value?.postPerson();
|
const person = await castEditPerson.value?.postPerson();
|
||||||
if (null !== person) {
|
if (null !== person) {
|
||||||
emit("saveFormOnTheFly", {type: props.type, data: person})
|
emit("saveFormOnTheFly", { type: props.type, data: person });
|
||||||
}
|
}
|
||||||
} else if (props.type === 'thirdparty') {
|
} else if (props.type === "thirdparty") {
|
||||||
const thirdParty = await castEditThirdParty.value?.postThirdParty();
|
const thirdParty = await castEditThirdParty.value?.postThirdParty();
|
||||||
if (null !== thirdParty) {
|
if (null !== thirdParty) {
|
||||||
emit("saveFormOnTheFly", {type: props.type, data: thirdParty })
|
emit("saveFormOnTheFly", { type: props.type, data: thirdParty });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
openModal,
|
openModal,
|
||||||
closeModal,
|
closeModal,
|
||||||
|
|||||||
@@ -19,10 +19,11 @@
|
|||||||
>
|
>
|
||||||
{{ p.text }}
|
{{ p.text }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else
|
<span
|
||||||
:class="getBadgeClass(p)"
|
v-else
|
||||||
class="chill_denomination"
|
:class="getBadgeClass(p)"
|
||||||
:style="getBadgeStyle(p)"
|
class="chill_denomination"
|
||||||
|
:style="getBadgeStyle(p)"
|
||||||
>
|
>
|
||||||
Ménage n°{{ p.id }}
|
Ménage n°{{ p.id }}
|
||||||
</span>
|
</span>
|
||||||
@@ -61,12 +62,14 @@
|
|||||||
@click="addNewSuggested(s)"
|
@click="addNewSuggested(s)"
|
||||||
style="margin: 0"
|
style="margin: 0"
|
||||||
>
|
>
|
||||||
<span v-if="!isEntityHousehold(s)" :class="getBadgeClass(s)" :style="getBadgeStyle(s)">
|
<span
|
||||||
|
v-if="!isEntityHousehold(s)"
|
||||||
|
:class="getBadgeClass(s)"
|
||||||
|
:style="getBadgeStyle(s)"
|
||||||
|
>
|
||||||
{{ s.text }}
|
{{ s.text }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else> Ménage n°{{ s.id }} </span>
|
||||||
Ménage n°{{ s.id }}
|
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -85,7 +88,8 @@ import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
|||||||
import {
|
import {
|
||||||
Entities,
|
Entities,
|
||||||
EntitiesOrMe,
|
EntitiesOrMe,
|
||||||
EntityType, isEntityHousehold,
|
EntityType,
|
||||||
|
isEntityHousehold,
|
||||||
SearchOptions,
|
SearchOptions,
|
||||||
Suggestion,
|
Suggestion,
|
||||||
} from "ChillPersonAssets/types";
|
} from "ChillPersonAssets/types";
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ import { ref } from "vue";
|
|||||||
import WaitingScreen from "ChillMainAssets/vuejs/_components/WaitingScreen.vue";
|
import WaitingScreen from "ChillMainAssets/vuejs/_components/WaitingScreen.vue";
|
||||||
import { WaitingScreenState } from "ChillMainAssets/types";
|
import { WaitingScreenState } from "ChillMainAssets/types";
|
||||||
import {
|
import {
|
||||||
trans,
|
trans,
|
||||||
WORKFLOW_WAIT_TITLE,
|
WORKFLOW_WAIT_TITLE,
|
||||||
WORKFLOW_WAIT_ERROR_WHILE_WAITING,
|
WORKFLOW_WAIT_ERROR_WHILE_WAITING,
|
||||||
WORKFLOW_WAIT_SUCCESS,
|
WORKFLOW_WAIT_SUCCESS,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
|
|
||||||
interface WaitPostProcessWorkflowComponentProps {
|
interface WaitPostProcessWorkflowComponentProps {
|
||||||
workflowId: number;
|
workflowId: number;
|
||||||
expectedStep: string;
|
expectedStep: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<WaitPostProcessWorkflowComponentProps>();
|
const props = defineProps<WaitPostProcessWorkflowComponentProps>();
|
||||||
@@ -24,52 +24,52 @@ const MAX_TRYIES = 50;
|
|||||||
const state = ref<WaitingScreenState>("pending");
|
const state = ref<WaitingScreenState>("pending");
|
||||||
|
|
||||||
const { pause, resume } = useIntervalFn(
|
const { pause, resume } = useIntervalFn(
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
const workflow = await fetchWorkflow(props.workflowId);
|
const workflow = await fetchWorkflow(props.workflowId);
|
||||||
counter.value++;
|
counter.value++;
|
||||||
if (workflow.currentStep.currentStep.name === props.expectedStep) {
|
if (workflow.currentStep.currentStep.name === props.expectedStep) {
|
||||||
window.location.assign(
|
window.location.assign(
|
||||||
returnPathOr("/fr/main/workflow" + workflow.id + "/show"),
|
returnPathOr("/fr/main/workflow" + workflow.id + "/show"),
|
||||||
);
|
);
|
||||||
resume();
|
resume();
|
||||||
state.value = "ready";
|
state.value = "ready";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter.value > MAX_TRYIES) {
|
if (counter.value > MAX_TRYIES) {
|
||||||
pause();
|
pause();
|
||||||
state.value = "failure";
|
state.value = "failure";
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
pause();
|
pause();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
2000,
|
2000,
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<WaitingScreen :state="state">
|
<WaitingScreen :state="state">
|
||||||
<template v-slot:pending>
|
<template v-slot:pending>
|
||||||
<p>
|
<p>
|
||||||
{{ trans(WORKFLOW_WAIT_TITLE) }}
|
{{ trans(WORKFLOW_WAIT_TITLE) }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:failure>
|
<template v-slot:failure>
|
||||||
<p>
|
<p>
|
||||||
{{ trans(WORKFLOW_WAIT_ERROR_WHILE_WAITING) }}
|
{{ trans(WORKFLOW_WAIT_ERROR_WHILE_WAITING) }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:ready>
|
<template v-slot:ready>
|
||||||
<p>
|
<p>
|
||||||
{{ trans(WORKFLOW_WAIT_SUCCESS) }}
|
{{ trans(WORKFLOW_WAIT_SUCCESS) }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</WaitingScreen>
|
</WaitingScreen>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -2,50 +2,50 @@ import { createApp } from "vue";
|
|||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
|
|
||||||
function mountApp(): void {
|
function mountApp(): void {
|
||||||
const el = document.querySelector<HTMLDivElement>(".screen-wait");
|
const el = document.querySelector<HTMLDivElement>(".screen-wait");
|
||||||
if (!el) {
|
if (!el) {
|
||||||
console.error(
|
console.error(
|
||||||
"WaitPostProcessWorkflow: mount element .screen-wait not found",
|
"WaitPostProcessWorkflow: mount element .screen-wait not found",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflowIdAttr = el.getAttribute("data-workflow-id");
|
const workflowIdAttr = el.getAttribute("data-workflow-id");
|
||||||
const expectedStep = el.getAttribute("data-expected-step") || "";
|
const expectedStep = el.getAttribute("data-expected-step") || "";
|
||||||
|
|
||||||
if (!workflowIdAttr) {
|
if (!workflowIdAttr) {
|
||||||
console.error(
|
console.error(
|
||||||
"WaitPostProcessWorkflow: data-workflow-id attribute missing on mount element",
|
"WaitPostProcessWorkflow: data-workflow-id attribute missing on mount element",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expectedStep) {
|
if (!expectedStep) {
|
||||||
console.error(
|
console.error(
|
||||||
"WaitPostProcessWorkflow: data-expected-step attribute missing on mount element",
|
"WaitPostProcessWorkflow: data-expected-step attribute missing on mount element",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflowId = Number(workflowIdAttr);
|
const workflowId = Number(workflowIdAttr);
|
||||||
if (Number.isNaN(workflowId)) {
|
if (Number.isNaN(workflowId)) {
|
||||||
console.error(
|
console.error(
|
||||||
"WaitPostProcessWorkflow: data-workflow-id is not a valid number:",
|
"WaitPostProcessWorkflow: data-workflow-id is not a valid number:",
|
||||||
workflowIdAttr,
|
workflowIdAttr,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = createApp(App, {
|
const app = createApp(App, {
|
||||||
workflowId,
|
workflowId,
|
||||||
expectedStep,
|
expectedStep,
|
||||||
});
|
});
|
||||||
|
|
||||||
app.mount(el);
|
app.mount(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.readyState === "loading") {
|
if (document.readyState === "loading") {
|
||||||
document.addEventListener("DOMContentLoaded", mountApp);
|
document.addEventListener("DOMContentLoaded", mountApp);
|
||||||
} else {
|
} else {
|
||||||
mountApp();
|
mountApp();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,17 +9,17 @@ import { fetchWorkflow } from "ChillMainAssets/lib/workflow/api";
|
|||||||
import { trans, WORKFLOW_ATTACHMENTS_ADD_AN_ATTACHMENT } from "translator";
|
import { trans, WORKFLOW_ATTACHMENTS_ADD_AN_ATTACHMENT } from "translator";
|
||||||
|
|
||||||
interface AppConfig {
|
interface AppConfig {
|
||||||
workflowId: number;
|
workflowId: number;
|
||||||
accompanyingPeriodId: number;
|
accompanyingPeriodId: number;
|
||||||
attachments: WorkflowAttachment[];
|
attachments: WorkflowAttachment[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(
|
(
|
||||||
e: "pickGenericDoc",
|
e: "pickGenericDoc",
|
||||||
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
||||||
): void;
|
): void;
|
||||||
(e: "removeAttachment", payload: { attachment: WorkflowAttachment }): void;
|
(e: "removeAttachment", payload: { attachment: WorkflowAttachment }): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
type PickGenericModalType = InstanceType<typeof PickGenericDocModal>;
|
type PickGenericModalType = InstanceType<typeof PickGenericDocModal>;
|
||||||
@@ -28,66 +28,66 @@ const pickDocModal = useTemplateRef<PickGenericModalType>("pickDocModal");
|
|||||||
const props = defineProps<AppConfig>();
|
const props = defineProps<AppConfig>();
|
||||||
|
|
||||||
const attachedGenericDoc = computed<GenericDocForAccompanyingPeriod[]>(
|
const attachedGenericDoc = computed<GenericDocForAccompanyingPeriod[]>(
|
||||||
() =>
|
() =>
|
||||||
props.attachments
|
props.attachments
|
||||||
.map((a: WorkflowAttachment) => a.genericDoc)
|
.map((a: WorkflowAttachment) => a.genericDoc)
|
||||||
.filter(
|
.filter(
|
||||||
(g: GenericDoc | null) => g !== null,
|
(g: GenericDoc | null) => g !== null,
|
||||||
) as GenericDocForAccompanyingPeriod[],
|
) as GenericDocForAccompanyingPeriod[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const workflow = ref<EntityWorkflow | null>(null);
|
const workflow = ref<EntityWorkflow | null>(null);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
workflow.value = await fetchWorkflow(Number(props.workflowId));
|
workflow.value = await fetchWorkflow(Number(props.workflowId));
|
||||||
console.log("workflow", workflow.value);
|
console.log("workflow", workflow.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
const openModal = function () {
|
const openModal = function () {
|
||||||
pickDocModal.value?.openModal();
|
pickDocModal.value?.openModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPickGenericDoc = ({
|
const onPickGenericDoc = ({
|
||||||
genericDoc,
|
genericDoc,
|
||||||
}: {
|
}: {
|
||||||
genericDoc: GenericDocForAccompanyingPeriod;
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
}) => {
|
}) => {
|
||||||
emit("pickGenericDoc", { genericDoc });
|
emit("pickGenericDoc", { genericDoc });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRemoveAttachment = (payload: { attachment: WorkflowAttachment }) => {
|
const onRemoveAttachment = (payload: { attachment: WorkflowAttachment }) => {
|
||||||
emit("removeAttachment", payload);
|
emit("removeAttachment", payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
const canEditAttachement = computed<boolean>(() => {
|
const canEditAttachement = computed<boolean>(() => {
|
||||||
if (null === workflow.value) {
|
if (null === workflow.value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return workflow.value._permissions.CHILL_MAIN_WORKFLOW_ATTACHMENT_EDIT;
|
return workflow.value._permissions.CHILL_MAIN_WORKFLOW_ATTACHMENT_EDIT;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<pick-generic-doc-modal
|
<pick-generic-doc-modal
|
||||||
:workflow="workflow"
|
:workflow="workflow"
|
||||||
:accompanying-period-id="props.accompanyingPeriodId"
|
:accompanying-period-id="props.accompanyingPeriodId"
|
||||||
:to-remove="attachedGenericDoc"
|
:to-remove="attachedGenericDoc"
|
||||||
ref="pickDocModal"
|
ref="pickDocModal"
|
||||||
@pickGenericDoc="onPickGenericDoc"
|
@pickGenericDoc="onPickGenericDoc"
|
||||||
></pick-generic-doc-modal>
|
></pick-generic-doc-modal>
|
||||||
<attachment-list
|
<attachment-list
|
||||||
:workflow="workflow"
|
:workflow="workflow"
|
||||||
:attachments="props.attachments"
|
:attachments="props.attachments"
|
||||||
@removeAttachment="onRemoveAttachment"
|
@removeAttachment="onRemoveAttachment"
|
||||||
></attachment-list>
|
></attachment-list>
|
||||||
<ul v-if="canEditAttachement" class="record_actions">
|
<ul v-if="canEditAttachement" class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
<button type="button" class="btn btn-create" @click="openModal">
|
<button type="button" class="btn btn-create" @click="openModal">
|
||||||
{{ trans(WORKFLOW_ATTACHMENTS_ADD_AN_ATTACHMENT) }}
|
{{ trans(WORKFLOW_ATTACHMENTS_ADD_AN_ATTACHMENT) }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
AttachmentWithDocAndStored,
|
AttachmentWithDocAndStored,
|
||||||
EntityWorkflow,
|
EntityWorkflow,
|
||||||
isAttachmentWithDocAndStored,
|
isAttachmentWithDocAndStored,
|
||||||
WorkflowAttachment,
|
WorkflowAttachment,
|
||||||
} from "ChillMainAssets/types";
|
} from "ChillMainAssets/types";
|
||||||
import GenericDocItemBox from "ChillMainAssets/vuejs/WorkflowAttachment/Component/GenericDocItemBox.vue";
|
import GenericDocItemBox from "ChillMainAssets/vuejs/WorkflowAttachment/Component/GenericDocItemBox.vue";
|
||||||
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
|
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
|
||||||
@@ -11,63 +11,61 @@ import { computed } from "vue";
|
|||||||
import { trans, WORKFLOW_ATTACHMENTS_NO_ATTACHMENT } from "translator";
|
import { trans, WORKFLOW_ATTACHMENTS_NO_ATTACHMENT } from "translator";
|
||||||
|
|
||||||
interface AttachmentListProps {
|
interface AttachmentListProps {
|
||||||
attachments: WorkflowAttachment[];
|
attachments: WorkflowAttachment[];
|
||||||
workflow: EntityWorkflow | null;
|
workflow: EntityWorkflow | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-function-type
|
// eslint-disable-next-line @typescript-eslint/prefer-function-type
|
||||||
(e: "removeAttachment", payload: { attachment: WorkflowAttachment }): void;
|
(e: "removeAttachment", payload: { attachment: WorkflowAttachment }): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps<AttachmentListProps>();
|
const props = defineProps<AttachmentListProps>();
|
||||||
|
|
||||||
const notNullAttachments = computed<AttachmentWithDocAndStored[]>(() =>
|
const notNullAttachments = computed<AttachmentWithDocAndStored[]>(() =>
|
||||||
props.attachments.filter(
|
props.attachments.filter(
|
||||||
(a: WorkflowAttachment): a is AttachmentWithDocAndStored =>
|
(a: WorkflowAttachment): a is AttachmentWithDocAndStored =>
|
||||||
isAttachmentWithDocAndStored(a),
|
isAttachmentWithDocAndStored(a),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const canRemove = computed<boolean>((): boolean => {
|
const canRemove = computed<boolean>((): boolean => {
|
||||||
if (null === props.workflow) {
|
if (null === props.workflow) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return props.workflow._permissions.CHILL_MAIN_WORKFLOW_ATTACHMENT_EDIT;
|
return props.workflow._permissions.CHILL_MAIN_WORKFLOW_ATTACHMENT_EDIT;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<p
|
<p
|
||||||
v-if="notNullAttachments.length === 0"
|
v-if="notNullAttachments.length === 0"
|
||||||
class="chill-no-data-statement text-center"
|
class="chill-no-data-statement text-center"
|
||||||
>
|
>
|
||||||
{{ trans(WORKFLOW_ATTACHMENTS_NO_ATTACHMENT) }}
|
{{ trans(WORKFLOW_ATTACHMENTS_NO_ATTACHMENT) }}
|
||||||
</p>
|
</p>
|
||||||
<div v-else class="flex-table">
|
<div v-else class="flex-table">
|
||||||
<div v-for="a in notNullAttachments" :key="a.id" class="item-bloc">
|
<div v-for="a in notNullAttachments" :key="a.id" class="item-bloc">
|
||||||
<generic-doc-item-box
|
<generic-doc-item-box :generic-doc="a.genericDoc"></generic-doc-item-box>
|
||||||
:generic-doc="a.genericDoc"
|
<div class="item-row separator">
|
||||||
></generic-doc-item-box>
|
<ul class="record_actions">
|
||||||
<div class="item-row separator">
|
<li>
|
||||||
<ul class="record_actions">
|
<document-action-buttons-group
|
||||||
<li>
|
:stored-object="a.genericDoc.storedObject"
|
||||||
<document-action-buttons-group
|
></document-action-buttons-group>
|
||||||
:stored-object="a.genericDoc.storedObject"
|
</li>
|
||||||
></document-action-buttons-group>
|
<li v-if="canRemove">
|
||||||
</li>
|
<button
|
||||||
<li v-if="canRemove">
|
type="button"
|
||||||
<button
|
class="btn btn-delete"
|
||||||
type="button"
|
@click="emit('removeAttachment', { attachment: a })"
|
||||||
class="btn btn-delete"
|
></button>
|
||||||
@click="emit('removeAttachment', { attachment: a })"
|
</li>
|
||||||
></button>
|
</ul>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
import { GenericDoc } from "ChillDocStoreAssets/types/generic_doc";
|
import { GenericDoc } from "ChillDocStoreAssets/types/generic_doc";
|
||||||
|
|
||||||
interface GenericDocItemBoxProps {
|
interface GenericDocItemBoxProps {
|
||||||
genericDoc: GenericDoc;
|
genericDoc: GenericDoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<GenericDocItemBoxProps>();
|
const props = defineProps<GenericDocItemBoxProps>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="'html' in props.genericDoc.metadata"
|
v-if="'html' in props.genericDoc.metadata"
|
||||||
v-html="props.genericDoc.metadata.html"
|
v-html="props.genericDoc.metadata.html"
|
||||||
></div>
|
></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
GenericDoc,
|
GenericDoc,
|
||||||
GenericDocForAccompanyingPeriod,
|
GenericDocForAccompanyingPeriod,
|
||||||
} from "ChillDocStoreAssets/types/generic_doc";
|
} from "ChillDocStoreAssets/types/generic_doc";
|
||||||
import PickGenericDocItem from "ChillMainAssets/vuejs/WorkflowAttachment/Component/PickGenericDocItem.vue";
|
import PickGenericDocItem from "ChillMainAssets/vuejs/WorkflowAttachment/Component/PickGenericDocItem.vue";
|
||||||
import { fetch_generic_docs_by_accompanying_period } from "ChillDocStoreAssets/js/generic-doc-api";
|
import { fetch_generic_docs_by_accompanying_period } from "ChillDocStoreAssets/js/generic-doc-api";
|
||||||
@@ -9,51 +9,50 @@ import { computed, onMounted, ref } from "vue";
|
|||||||
import { EntityWorkflow } from "ChillMainAssets/types";
|
import { EntityWorkflow } from "ChillMainAssets/types";
|
||||||
|
|
||||||
interface PickGenericDocProps {
|
interface PickGenericDocProps {
|
||||||
workflow: EntityWorkflow | null;
|
workflow: EntityWorkflow | null;
|
||||||
accompanyingPeriodId: number;
|
accompanyingPeriodId: number;
|
||||||
pickedList: GenericDocForAccompanyingPeriod[];
|
pickedList: GenericDocForAccompanyingPeriod[];
|
||||||
toRemove: GenericDocForAccompanyingPeriod[];
|
toRemove: GenericDocForAccompanyingPeriod[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<PickGenericDocProps>();
|
const props = defineProps<PickGenericDocProps>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(
|
(
|
||||||
e: "pickGenericDoc",
|
e: "pickGenericDoc",
|
||||||
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
(
|
(
|
||||||
e: "removeGenericDoc",
|
e: "removeGenericDoc",
|
||||||
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
||||||
): void;
|
): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const genericDocs = ref<GenericDocForAccompanyingPeriod[]>([]);
|
const genericDocs = ref<GenericDocForAccompanyingPeriod[]>([]);
|
||||||
const loaded = ref(false);
|
const loaded = ref(false);
|
||||||
|
|
||||||
const isPicked = (genericDoc: GenericDocForAccompanyingPeriod): boolean =>
|
const isPicked = (genericDoc: GenericDocForAccompanyingPeriod): boolean =>
|
||||||
props.pickedList.findIndex(
|
props.pickedList.findIndex(
|
||||||
(element: GenericDocForAccompanyingPeriod) =>
|
(element: GenericDocForAccompanyingPeriod) =>
|
||||||
element.uniqueKey === genericDoc.uniqueKey,
|
element.uniqueKey === genericDoc.uniqueKey,
|
||||||
) !== -1;
|
) !== -1;
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const fetchedGenericDocs = await fetch_generic_docs_by_accompanying_period(
|
const fetchedGenericDocs = await fetch_generic_docs_by_accompanying_period(
|
||||||
props.accompanyingPeriodId,
|
props.accompanyingPeriodId,
|
||||||
);
|
);
|
||||||
const documentClasses = [
|
const documentClasses = [
|
||||||
"Chill\\DocStoreBundle\\Entity\\AccompanyingCourseDocument",
|
"Chill\\DocStoreBundle\\Entity\\AccompanyingCourseDocument",
|
||||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
||||||
"Chill\\DocStoreBundle\\Entity\\PersonDocument",
|
"Chill\\DocStoreBundle\\Entity\\PersonDocument",
|
||||||
];
|
];
|
||||||
|
|
||||||
genericDocs.value = fetchedGenericDocs.filter(
|
genericDocs.value = fetchedGenericDocs.filter(
|
||||||
(doc) =>
|
(doc) =>
|
||||||
!documentClasses.includes(
|
!documentClasses.includes(props.workflow?.relatedEntityClass || "") ||
|
||||||
props.workflow?.relatedEntityClass || "",
|
props.workflow?.relatedEntityId !== doc.identifiers.id,
|
||||||
) || props.workflow?.relatedEntityId !== doc.identifiers.id,
|
);
|
||||||
);
|
loaded.value = true;
|
||||||
loaded.value = true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const textFilter = ref<string>("");
|
const textFilter = ref<string>("");
|
||||||
@@ -62,229 +61,213 @@ const dateToFilter = ref<string | null>(null);
|
|||||||
const placesFilter = ref<string[]>([]);
|
const placesFilter = ref<string[]>([]);
|
||||||
|
|
||||||
const availablePlaces = computed<string[]>(() => {
|
const availablePlaces = computed<string[]>(() => {
|
||||||
const places = new Set<string>(
|
const places = new Set<string>(
|
||||||
genericDocs.value.map((genericDoc: GenericDoc) => genericDoc.key),
|
genericDocs.value.map((genericDoc: GenericDoc) => genericDoc.key),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Array.from(places).sort((a, b) => (a < b ? -1 : a === b ? 0 : 1));
|
return Array.from(places).sort((a, b) => (a < b ? -1 : a === b ? 0 : 1));
|
||||||
});
|
});
|
||||||
|
|
||||||
const placeTrans = (str: string): string => {
|
const placeTrans = (str: string): string => {
|
||||||
switch (str) {
|
switch (str) {
|
||||||
case "accompanying_course_document":
|
case "accompanying_course_document":
|
||||||
return "Documents du parcours";
|
return "Documents du parcours";
|
||||||
case "person_document":
|
case "person_document":
|
||||||
return "Documents de l'usager";
|
return "Documents de l'usager";
|
||||||
case "accompanying_period_calendar_document":
|
case "accompanying_period_calendar_document":
|
||||||
return "Document des rendez-vous des parcours";
|
return "Document des rendez-vous des parcours";
|
||||||
case "accompanying_period_activity_document":
|
case "accompanying_period_activity_document":
|
||||||
return "Document des échanges des parcours";
|
return "Document des échanges des parcours";
|
||||||
case "accompanying_period_work_evaluation_document":
|
case "accompanying_period_work_evaluation_document":
|
||||||
return "Document des actions d'accompagnement";
|
return "Document des actions d'accompagnement";
|
||||||
default:
|
default:
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPickDocument = (payload: {
|
const onPickDocument = (payload: {
|
||||||
genericDoc: GenericDocForAccompanyingPeriod;
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
}) => emit("pickGenericDoc", payload);
|
}) => emit("pickGenericDoc", payload);
|
||||||
|
|
||||||
const onRemoveGenericDoc = (payload: {
|
const onRemoveGenericDoc = (payload: {
|
||||||
genericDoc: GenericDocForAccompanyingPeriod;
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
}) => emit("removeGenericDoc", payload);
|
}) => emit("removeGenericDoc", payload);
|
||||||
|
|
||||||
const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => {
|
const filteredDocuments = computed<GenericDocForAccompanyingPeriod[]>(() => {
|
||||||
if (false === loaded.value) {
|
if (false === loaded.value) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return genericDocs.value
|
return genericDocs.value
|
||||||
.filter(
|
.filter(
|
||||||
(genericDoc: GenericDocForAccompanyingPeriod) =>
|
(genericDoc: GenericDocForAccompanyingPeriod) =>
|
||||||
!props.toRemove
|
!props.toRemove
|
||||||
.map((g: GenericDocForAccompanyingPeriod) => g.uniqueKey)
|
.map((g: GenericDocForAccompanyingPeriod) => g.uniqueKey)
|
||||||
.includes(genericDoc.uniqueKey),
|
.includes(genericDoc.uniqueKey),
|
||||||
)
|
)
|
||||||
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
||||||
if (textFilter.value === "") {
|
if (textFilter.value === "") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const needles = textFilter.value
|
const needles = textFilter.value
|
||||||
.trim()
|
.trim()
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.map((str: string) => str.trim().toLowerCase())
|
.map((str: string) => str.trim().toLowerCase())
|
||||||
.filter((str: string) => str.length > 0);
|
.filter((str: string) => str.length > 0);
|
||||||
const title: string =
|
const title: string =
|
||||||
"title" in genericDoc.metadata
|
"title" in genericDoc.metadata
|
||||||
? (genericDoc.metadata.title as string)
|
? (genericDoc.metadata.title as string)
|
||||||
: "";
|
: "";
|
||||||
if (title === "") {
|
if (title === "") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return needles.every((n: string) =>
|
return needles.every((n: string) => title.toLowerCase().includes(n));
|
||||||
title.toLowerCase().includes(n),
|
})
|
||||||
);
|
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
||||||
})
|
if (placesFilter.value.length === 0) {
|
||||||
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
return true;
|
||||||
if (placesFilter.value.length === 0) {
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return placesFilter.value.includes(genericDoc.key);
|
return placesFilter.value.includes(genericDoc.key);
|
||||||
})
|
})
|
||||||
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
||||||
if (dateToFilter.value === null) {
|
if (dateToFilter.value === null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return genericDoc.doc_date.datetime8601 < dateToFilter.value;
|
return genericDoc.doc_date.datetime8601 < dateToFilter.value;
|
||||||
})
|
})
|
||||||
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
.filter((genericDoc: GenericDocForAccompanyingPeriod) => {
|
||||||
if (dateFromFilter.value === null) {
|
if (dateFromFilter.value === null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return genericDoc.doc_date.datetime8601 > dateFromFilter.value;
|
return genericDoc.doc_date.datetime8601 > dateFromFilter.value;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="loaded">
|
<div v-if="loaded">
|
||||||
<div>
|
<div>
|
||||||
<form name="f" method="get">
|
<form name="f" method="get">
|
||||||
<div class="accordion my-3" id="filterOrderAccordion">
|
<div class="accordion my-3" id="filterOrderAccordion">
|
||||||
<h2 class="accordion-header" id="filterOrderHeading">
|
<h2 class="accordion-header" id="filterOrderHeading">
|
||||||
<button
|
<button
|
||||||
class="accordion-button"
|
class="accordion-button"
|
||||||
type="button"
|
type="button"
|
||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
data-bs-target="#filterOrderCollapse"
|
data-bs-target="#filterOrderCollapse"
|
||||||
aria-expanded="true"
|
aria-expanded="true"
|
||||||
aria-controls="filterOrderCollapse"
|
aria-controls="filterOrderCollapse"
|
||||||
>
|
>
|
||||||
<strong
|
<strong
|
||||||
><i class="fa fa-fw fa-filter"></i>Filtrer la
|
><i class="fa fa-fw fa-filter"></i>Filtrer la liste</strong
|
||||||
liste</strong
|
>
|
||||||
>
|
</button>
|
||||||
</button>
|
</h2>
|
||||||
</h2>
|
<div
|
||||||
<div
|
class="accordion-collapse collapse"
|
||||||
class="accordion-collapse collapse"
|
id="filterOrderCollapse"
|
||||||
id="filterOrderCollapse"
|
aria-labelledby="filterOrderHeading"
|
||||||
aria-labelledby="filterOrderHeading"
|
data-bs-parent="#filterOrderAccordion"
|
||||||
data-bs-parent="#filterOrderAccordion"
|
style=""
|
||||||
style=""
|
>
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="accordion-body chill_filter_order container-xxl p-5 py-2"
|
|
||||||
>
|
|
||||||
<div class="row my-2">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div class="input-group">
|
|
||||||
<input
|
|
||||||
v-model="textFilter"
|
|
||||||
type="search"
|
|
||||||
id="f_q"
|
|
||||||
name="f[q]"
|
|
||||||
placeholder="Chercher dans la liste"
|
|
||||||
class="form-control"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="btn btn-misc"
|
|
||||||
>
|
|
||||||
<i class="fa fa-search"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row my-2">
|
|
||||||
<legend
|
|
||||||
class="col-form-label col-sm-4 required"
|
|
||||||
>
|
|
||||||
Date du document
|
|
||||||
</legend>
|
|
||||||
<div class="col-sm-8 pt-1">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text">Du</span>
|
|
||||||
<input
|
|
||||||
v-model="dateFromFilter"
|
|
||||||
type="date"
|
|
||||||
id="f_dateRanges_dateRange_from"
|
|
||||||
name="f[dateRanges][dateRange][from]"
|
|
||||||
class="form-control"
|
|
||||||
/>
|
|
||||||
<span class="input-group-text">Au</span>
|
|
||||||
<input
|
|
||||||
v-model="dateToFilter"
|
|
||||||
type="date"
|
|
||||||
id="f_dateRanges_dateRange_to"
|
|
||||||
name="f[dateRanges][dateRange][to]"
|
|
||||||
class="form-control"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row my-2">
|
|
||||||
<div class="col-sm-4 col-form-label">
|
|
||||||
Filtrer par
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-8 pt-2">
|
|
||||||
<div
|
|
||||||
class="form-check"
|
|
||||||
v-for="p in availablePlaces"
|
|
||||||
:key="p"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
v-model="placesFilter"
|
|
||||||
name="f[checkboxes][places][]"
|
|
||||||
class="form-check-input"
|
|
||||||
:value="p"
|
|
||||||
/>
|
|
||||||
<label class="form-check-label">{{
|
|
||||||
placeTrans(p)
|
|
||||||
}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="genericDocs.length > 0" class="flex-table chill-task-list">
|
|
||||||
<pick-generic-doc-item
|
|
||||||
v-for="g in filteredDocuments"
|
|
||||||
:key="g.uniqueKey"
|
|
||||||
:accompanying-period-id="accompanyingPeriodId"
|
|
||||||
:genericDoc="g"
|
|
||||||
:is-picked="isPicked(g)"
|
|
||||||
@pickGenericDoc="onPickDocument"
|
|
||||||
@removeGenericDoc="onRemoveGenericDoc"
|
|
||||||
></pick-generic-doc-item>
|
|
||||||
</div>
|
|
||||||
<div v-else class="text-center chill-no-data-statement">
|
|
||||||
Aucun document dans ce parcours
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<strong>Chargement…</strong>
|
|
||||||
<div
|
<div
|
||||||
class="spinner-border ms-auto"
|
class="accordion-body chill_filter_order container-xxl p-5 py-2"
|
||||||
role="status"
|
>
|
||||||
aria-hidden="true"
|
<div class="row my-2">
|
||||||
></div>
|
<div class="col-sm-12">
|
||||||
|
<div class="input-group">
|
||||||
|
<input
|
||||||
|
v-model="textFilter"
|
||||||
|
type="search"
|
||||||
|
id="f_q"
|
||||||
|
name="f[q]"
|
||||||
|
placeholder="Chercher dans la liste"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
<button type="submit" class="btn btn-misc">
|
||||||
|
<i class="fa fa-search"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row my-2">
|
||||||
|
<legend class="col-form-label col-sm-4 required">
|
||||||
|
Date du document
|
||||||
|
</legend>
|
||||||
|
<div class="col-sm-8 pt-1">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">Du</span>
|
||||||
|
<input
|
||||||
|
v-model="dateFromFilter"
|
||||||
|
type="date"
|
||||||
|
id="f_dateRanges_dateRange_from"
|
||||||
|
name="f[dateRanges][dateRange][from]"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
<span class="input-group-text">Au</span>
|
||||||
|
<input
|
||||||
|
v-model="dateToFilter"
|
||||||
|
type="date"
|
||||||
|
id="f_dateRanges_dateRange_to"
|
||||||
|
name="f[dateRanges][dateRange][to]"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row my-2">
|
||||||
|
<div class="col-sm-4 col-form-label">Filtrer par</div>
|
||||||
|
<div class="col-sm-8 pt-2">
|
||||||
|
<div class="form-check" v-for="p in availablePlaces" :key="p">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
v-model="placesFilter"
|
||||||
|
name="f[checkboxes][places][]"
|
||||||
|
class="form-check-input"
|
||||||
|
:value="p"
|
||||||
|
/>
|
||||||
|
<label class="form-check-label">{{ placeTrans(p) }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="genericDocs.length > 0" class="flex-table chill-task-list">
|
||||||
|
<pick-generic-doc-item
|
||||||
|
v-for="g in filteredDocuments"
|
||||||
|
:key="g.uniqueKey"
|
||||||
|
:accompanying-period-id="accompanyingPeriodId"
|
||||||
|
:genericDoc="g"
|
||||||
|
:is-picked="isPicked(g)"
|
||||||
|
@pickGenericDoc="onPickDocument"
|
||||||
|
@removeGenericDoc="onRemoveGenericDoc"
|
||||||
|
></pick-generic-doc-item>
|
||||||
|
</div>
|
||||||
|
<div v-else class="text-center chill-no-data-statement">
|
||||||
|
Aucun document dans ce parcours
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<strong>Chargement…</strong>
|
||||||
|
<div
|
||||||
|
class="spinner-border ms-auto"
|
||||||
|
role="status"
|
||||||
|
aria-hidden="true"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -6,20 +6,20 @@ import { GenericDocForAccompanyingPeriod } from "ChillDocStoreAssets/types/gener
|
|||||||
import { EntityWorkflow } from "ChillMainAssets/types";
|
import { EntityWorkflow } from "ChillMainAssets/types";
|
||||||
|
|
||||||
interface PickGenericDocModalProps {
|
interface PickGenericDocModalProps {
|
||||||
workflow: EntityWorkflow | null;
|
workflow: EntityWorkflow | null;
|
||||||
accompanyingPeriodId: number;
|
accompanyingPeriodId: number;
|
||||||
toRemove: GenericDocForAccompanyingPeriod[];
|
toRemove: GenericDocForAccompanyingPeriod[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type PickGenericDocType = InstanceType<typeof PickGenericDoc>;
|
type PickGenericDocType = InstanceType<typeof PickGenericDoc>;
|
||||||
|
|
||||||
const props = defineProps<PickGenericDocModalProps>();
|
const props = defineProps<PickGenericDocModalProps>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-function-type
|
// eslint-disable-next-line @typescript-eslint/prefer-function-type
|
||||||
(
|
(
|
||||||
e: "pickGenericDoc",
|
e: "pickGenericDoc",
|
||||||
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
payload: { genericDoc: GenericDocForAccompanyingPeriod },
|
||||||
): void;
|
): void;
|
||||||
}>();
|
}>();
|
||||||
const picker = useTemplateRef<PickGenericDocType>("picker");
|
const picker = useTemplateRef<PickGenericDocType>("picker");
|
||||||
const modalOpened = ref<boolean>(false);
|
const modalOpened = ref<boolean>(false);
|
||||||
@@ -29,88 +29,88 @@ const modalClasses = { "modal-xl": true, "modal-dialog-scrollable": true };
|
|||||||
const numberOfPicked = computed<number>(() => pickeds.value.length);
|
const numberOfPicked = computed<number>(() => pickeds.value.length);
|
||||||
|
|
||||||
const onPicked = ({
|
const onPicked = ({
|
||||||
genericDoc,
|
genericDoc,
|
||||||
}: {
|
}: {
|
||||||
genericDoc: GenericDocForAccompanyingPeriod;
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
}) => {
|
}) => {
|
||||||
pickeds.value.push(genericDoc);
|
pickeds.value.push(genericDoc);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRemove = ({
|
const onRemove = ({
|
||||||
genericDoc,
|
genericDoc,
|
||||||
}: {
|
}: {
|
||||||
genericDoc: GenericDocForAccompanyingPeriod;
|
genericDoc: GenericDocForAccompanyingPeriod;
|
||||||
}) => {
|
}) => {
|
||||||
const index = pickeds.value.findIndex(
|
const index = pickeds.value.findIndex(
|
||||||
(item) => item.uniqueKey === genericDoc.uniqueKey,
|
(item) => item.uniqueKey === genericDoc.uniqueKey,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
throw new Error("Remove generic doc that doesn't exist");
|
throw new Error("Remove generic doc that doesn't exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
pickeds.value.splice(index, 1);
|
pickeds.value.splice(index, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
for (let genericDoc of pickeds.value) {
|
for (let genericDoc of pickeds.value) {
|
||||||
emit("pickGenericDoc", { genericDoc });
|
emit("pickGenericDoc", { genericDoc });
|
||||||
}
|
}
|
||||||
pickeds.value = [];
|
pickeds.value = [];
|
||||||
closeModal();
|
closeModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeModal = function () {
|
const closeModal = function () {
|
||||||
modalOpened.value = false;
|
modalOpened.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const openModal = function () {
|
const openModal = function () {
|
||||||
modalOpened.value = true;
|
modalOpened.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ openModal, closeModal });
|
defineExpose({ openModal, closeModal });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<modal
|
<modal
|
||||||
v-if="modalOpened"
|
v-if="modalOpened"
|
||||||
@close="closeModal"
|
@close="closeModal"
|
||||||
:modal-dialog-class="modalClasses"
|
:modal-dialog-class="modalClasses"
|
||||||
>
|
>
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<h2 class="modal-title">Ajouter une pièce jointe</h2>
|
<h2 class="modal-title">Ajouter une pièce jointe</h2>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:body>
|
<template v-slot:body>
|
||||||
<pick-generic-doc
|
<pick-generic-doc
|
||||||
:workflow="props.workflow"
|
:workflow="props.workflow"
|
||||||
:accompanying-period-id="props.accompanyingPeriodId"
|
:accompanying-period-id="props.accompanyingPeriodId"
|
||||||
:to-remove="props.toRemove"
|
:to-remove="props.toRemove"
|
||||||
:picked-list="pickeds"
|
:picked-list="pickeds"
|
||||||
ref="picker"
|
ref="picker"
|
||||||
@pickGenericDoc="onPicked"
|
@pickGenericDoc="onPicked"
|
||||||
@removeGenericDoc="onRemove"
|
@removeGenericDoc="onRemove"
|
||||||
></pick-generic-doc>
|
></pick-generic-doc>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<ul v-if="numberOfPicked > 0" class="record_actions">
|
<ul v-if="numberOfPicked > 0" class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-chill-green text-white"
|
class="btn btn-chill-green text-white"
|
||||||
@click="onConfirm"
|
@click="onConfirm"
|
||||||
>
|
>
|
||||||
<template v-if="numberOfPicked > 1">
|
<template v-if="numberOfPicked > 1">
|
||||||
<i class="fa fa-plus"></i> Ajouter
|
<i class="fa fa-plus"></i> Ajouter {{ numberOfPicked }} pièces
|
||||||
{{ numberOfPicked }} pièces jointes
|
jointes
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<i class="fa fa-plus"></i> Ajouter une pièce jointe
|
<i class="fa fa-plus"></i> Ajouter une pièce jointe
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import type { Gender } from "ChillMainAssets/types";
|
import type { Gender } from "ChillMainAssets/types";
|
||||||
import {toGenderTranslation} from "ChillMainAssets/lib/api/genderHelper";
|
import { toGenderTranslation } from "ChillMainAssets/lib/api/genderHelper";
|
||||||
|
|
||||||
interface GenderIconRenderBoxProps {
|
interface GenderIconRenderBoxProps {
|
||||||
gender: Gender;
|
gender: Gender;
|
||||||
|
|||||||
@@ -1,79 +1,71 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="d-grid gap-2 my-3">
|
<div class="d-grid gap-2 my-3">
|
||||||
<button
|
<button
|
||||||
class="btn btn-outline-primary text-start d-flex align-items-center"
|
class="btn btn-outline-primary text-start d-flex align-items-center"
|
||||||
:class="{ active: subscriberFinal }"
|
:class="{ active: subscriberFinal }"
|
||||||
type="button"
|
type="button"
|
||||||
@click="
|
@click="
|
||||||
subscribeTo(
|
subscribeTo(subscriberFinal ? 'unsubscribe' : 'subscribe', 'final')
|
||||||
subscriberFinal ? 'unsubscribe' : 'subscribe',
|
"
|
||||||
'final',
|
>
|
||||||
)
|
<i
|
||||||
"
|
class="fa fa-fw me-2"
|
||||||
>
|
:class="subscriberFinal ? 'fa-check-square-o' : 'fa-square-o'"
|
||||||
<i
|
></i>
|
||||||
class="fa fa-fw me-2"
|
<span>{{ trans(WORKFLOW_SUBSCRIBE_FINAL) }}</span>
|
||||||
:class="subscriberFinal ? 'fa-check-square-o' : 'fa-square-o'"
|
</button>
|
||||||
></i>
|
<button
|
||||||
<span>{{ trans(WORKFLOW_SUBSCRIBE_FINAL) }}</span>
|
class="btn btn-outline-primary text-start d-flex align-items-center"
|
||||||
</button>
|
:class="{ active: subscriberStep }"
|
||||||
<button
|
type="button"
|
||||||
class="btn btn-outline-primary text-start d-flex align-items-center"
|
@click="subscribeTo(subscriberStep ? 'unsubscribe' : 'subscribe', 'step')"
|
||||||
:class="{ active: subscriberStep }"
|
>
|
||||||
type="button"
|
<i
|
||||||
@click="
|
class="fa fa-fw me-2"
|
||||||
subscribeTo(
|
:class="subscriberStep ? 'fa-check-square-o' : 'fa-square-o'"
|
||||||
subscriberStep ? 'unsubscribe' : 'subscribe',
|
></i>
|
||||||
'step',
|
<span>{{ trans(WORKFLOW_SUBSCRIBE_ALL_STEPS) }}</span>
|
||||||
)
|
</button>
|
||||||
"
|
</div>
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="fa fa-fw me-2"
|
|
||||||
:class="subscriberStep ? 'fa-check-square-o' : 'fa-square-o'"
|
|
||||||
></i>
|
|
||||||
<span>{{ trans(WORKFLOW_SUBSCRIBE_ALL_STEPS) }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
|
||||||
import { defineProps, defineEmits } from "vue";
|
import { defineProps, defineEmits } from "vue";
|
||||||
import {
|
import {
|
||||||
trans,
|
trans,
|
||||||
WORKFLOW_SUBSCRIBE_FINAL,
|
WORKFLOW_SUBSCRIBE_FINAL,
|
||||||
WORKFLOW_SUBSCRIBE_ALL_STEPS,
|
WORKFLOW_SUBSCRIBE_ALL_STEPS,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
|
|
||||||
// props
|
// props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
entityWorkflowId: {
|
entityWorkflowId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
subscriberStep: {
|
subscriberStep: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
subscriberFinal: {
|
subscriberFinal: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//methods
|
//methods
|
||||||
const subscribeTo = (step, to) => {
|
const subscribeTo = (step, to) => {
|
||||||
let params = new URLSearchParams();
|
let params = new URLSearchParams();
|
||||||
params.set("subscribe", to);
|
params.set("subscribe", to);
|
||||||
|
|
||||||
const url =
|
const url =
|
||||||
`/api/1.0/main/workflow/${props.entityWorkflowId}/${step}?` +
|
`/api/1.0/main/workflow/${props.entityWorkflowId}/${step}?` +
|
||||||
params.toString();
|
params.toString();
|
||||||
|
|
||||||
makeFetch("POST", url).then((response) => {
|
makeFetch("POST", url).then((response) => {
|
||||||
emit("subscriptionUpdated", response);
|
emit("subscriptionUpdated", response);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// emit
|
// emit
|
||||||
|
|||||||
@@ -1,42 +1,39 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="modal">
|
<transition name="modal">
|
||||||
<div class="modal-mask">
|
<div class="modal-mask">
|
||||||
<!-- :: styles bootstrap :: -->
|
<!-- :: styles bootstrap :: -->
|
||||||
<div
|
<div
|
||||||
class="modal fade show"
|
class="modal fade show"
|
||||||
style="display: block"
|
style="display: block"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
>
|
>
|
||||||
<div class="modal-dialog" :class="props.modalDialogClass || {}">
|
<div class="modal-dialog" :class="props.modalDialogClass || {}">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
<button class="close btn" @click="emits('close')">
|
<button class="close btn" @click="emits('close')">
|
||||||
<i class="fa fa-times" aria-hidden="true"></i>
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="body-head">
|
|
||||||
<slot name="body-head"></slot>
|
|
||||||
</div>
|
|
||||||
<slot name="body"></slot>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer" v-if="!hideFooter">
|
|
||||||
<button
|
|
||||||
class="btn btn-cancel"
|
|
||||||
@click="emits('close')"
|
|
||||||
>
|
|
||||||
{{ trans(MODAL_ACTION_CLOSE) }}
|
|
||||||
</button>
|
|
||||||
<slot name="footer"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- :: end styles bootstrap :: -->
|
<div class="modal-body">
|
||||||
|
<div class="body-head">
|
||||||
|
<slot name="body-head"></slot>
|
||||||
|
</div>
|
||||||
|
<slot name="body"></slot>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer" v-if="!hideFooter">
|
||||||
|
<button class="btn btn-cancel" @click="emits('close')">
|
||||||
|
{{ trans(MODAL_ACTION_CLOSE) }}
|
||||||
|
</button>
|
||||||
|
<slot name="footer"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</div>
|
||||||
|
<!-- :: end styles bootstrap :: -->
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -53,10 +50,10 @@ import { trans, MODAL_ACTION_CLOSE } from "translator";
|
|||||||
import { defineProps } from "vue";
|
import { defineProps } from "vue";
|
||||||
|
|
||||||
defineSlots<{
|
defineSlots<{
|
||||||
header?: () => any,
|
header?: () => any;
|
||||||
body?: () => any,
|
body?: () => any;
|
||||||
footer?: () => any,
|
footer?: () => any;
|
||||||
"body-head"?: () => any,
|
"body-head"?: () => any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
export interface ModalProps {
|
export interface ModalProps {
|
||||||
@@ -72,7 +69,7 @@ const props = withDefaults(defineProps<ModalProps>(), {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
close: [];
|
close: [];
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -81,19 +78,19 @@ const emits = defineEmits<{
|
|||||||
* This is a mask behind the modal.
|
* This is a mask behind the modal.
|
||||||
*/
|
*/
|
||||||
.modal-mask {
|
.modal-mask {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 9998;
|
z-index: 9998;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0, 0, 0, 0.75);
|
background-color: rgba(0, 0, 0, 0.75);
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
}
|
}
|
||||||
.modal-header .close {
|
.modal-header .close {
|
||||||
border-top-right-radius: 0.3rem;
|
border-top-right-radius: 0.3rem;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* The following styles are auto-applied to elements with
|
* The following styles are auto-applied to elements with
|
||||||
@@ -104,23 +101,23 @@ const emits = defineEmits<{
|
|||||||
* these styles.
|
* these styles.
|
||||||
*/
|
*/
|
||||||
.modal-enter {
|
.modal-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
.modal-leave-active {
|
.modal-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
.modal-enter .modal-container,
|
.modal-enter .modal-container,
|
||||||
.modal-leave-active .modal-container {
|
.modal-leave-active .modal-container {
|
||||||
-webkit-transform: scale(1.1);
|
-webkit-transform: scale(1.1);
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
h3.modal-title {
|
h3.modal-title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
div.modal-footer {
|
div.modal-footer {
|
||||||
button:first-child {
|
button:first-child {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,61 +2,61 @@
|
|||||||
import { WaitingScreenState } from "ChillMainAssets/types";
|
import { WaitingScreenState } from "ChillMainAssets/types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
state: WaitingScreenState;
|
state: WaitingScreenState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="waiting-screen">
|
<div id="waiting-screen">
|
||||||
<div
|
<div
|
||||||
v-if="props.state === 'pending' && !!$slots.pending"
|
v-if="props.state === 'pending' && !!$slots.pending"
|
||||||
class="alert alert-danger text-center"
|
class="alert alert-danger text-center"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<slot name="pending"></slot>
|
<slot name="pending"></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<i class="fa fa-cog fa-spin fa-3x fa-fw"></i>
|
<i class="fa fa-cog fa-spin fa-3x fa-fw"></i>
|
||||||
<span class="sr-only">Loading...</span>
|
<span class="sr-only">Loading...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="props.state === 'stopped' && !!$slots.stopped"
|
|
||||||
class="alert alert-info"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<slot name="stopped"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="props.state === 'failure' && !!$slots.failure"
|
|
||||||
class="alert alert-danger text-center"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<slot name="failure"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="props.state === 'ready' && !!$slots.ready"
|
|
||||||
class="alert alert-success text-center"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<slot name="ready"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="props.state === 'stopped' && !!$slots.stopped"
|
||||||
|
class="alert alert-info"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<slot name="stopped"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="props.state === 'failure' && !!$slots.failure"
|
||||||
|
class="alert alert-danger text-center"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<slot name="failure"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="props.state === 'ready' && !!$slots.ready"
|
||||||
|
class="alert alert-success text-center"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<slot name="ready"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
#waiting-screen {
|
#waiting-screen {
|
||||||
> .alert {
|
> .alert {
|
||||||
min-height: 350px;
|
min-height: 350px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
import {ref} from "vue";
|
import { ref } from "vue";
|
||||||
import {ValidationExceptionInterface} from "ChillMainAssets/types";
|
import { ValidationExceptionInterface } from "ChillMainAssets/types";
|
||||||
|
|
||||||
export function useViolationList<T extends Record<string, Record<string, string>>>() {
|
export function useViolationList<
|
||||||
|
T extends Record<string, Record<string, string>>,
|
||||||
|
>() {
|
||||||
type ViolationKey = Extract<keyof T, string>;
|
type ViolationKey = Extract<keyof T, string>;
|
||||||
const violationsList = ref<ValidationExceptionInterface<T>|null>(null);
|
const violationsList = ref<ValidationExceptionInterface<T> | null>(null);
|
||||||
|
|
||||||
function violationTitles<P extends ViolationKey>(property: P): string[] {
|
function violationTitles<P extends ViolationKey>(property: P): string[] {
|
||||||
if (null === violationsList.value) {
|
if (null === violationsList.value) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const r = violationsList.value.violationsByNormalizedProperty(property).map((v) => v.title);
|
const r = violationsList.value
|
||||||
|
.violationsByNormalizedProperty(property)
|
||||||
|
.map((v) => v.title);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
}
|
}
|
||||||
function violationTitlesWithParameter<
|
function violationTitlesWithParameter<
|
||||||
P extends ViolationKey,
|
P extends ViolationKey,
|
||||||
Param extends Extract<keyof T[P], string>
|
Param extends Extract<keyof T[P], string>,
|
||||||
>(
|
>(
|
||||||
property: P,
|
property: P,
|
||||||
with_parameter: Param,
|
with_parameter: Param,
|
||||||
@@ -26,26 +28,38 @@ export function useViolationList<T extends Record<string, Record<string, string>
|
|||||||
if (violationsList.value === null) {
|
if (violationsList.value === null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return violationsList.value.violationsByNormalizedPropertyAndParams(property, with_parameter, with_parameter_value)
|
return violationsList.value
|
||||||
|
.violationsByNormalizedPropertyAndParams(
|
||||||
|
property,
|
||||||
|
with_parameter,
|
||||||
|
with_parameter_value,
|
||||||
|
)
|
||||||
.map((v) => v.title);
|
.map((v) => v.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function hasViolation<P extends ViolationKey>(property: P): boolean {
|
function hasViolation<P extends ViolationKey>(property: P): boolean {
|
||||||
return violationTitles(property).length > 0;
|
return violationTitles(property).length > 0;
|
||||||
}
|
}
|
||||||
function hasViolationWithParameter<
|
function hasViolationWithParameter<
|
||||||
P extends ViolationKey,
|
P extends ViolationKey,
|
||||||
Param extends Extract<keyof T[P], string>
|
Param extends Extract<keyof T[P], string>,
|
||||||
>(
|
>(
|
||||||
property: P,
|
property: P,
|
||||||
with_parameter: Param,
|
with_parameter: Param,
|
||||||
with_parameter_value: T[P][Param],
|
with_parameter_value: T[P][Param],
|
||||||
): boolean {
|
): boolean {
|
||||||
return violationTitlesWithParameter(property, with_parameter, with_parameter_value).length > 0;
|
return (
|
||||||
|
violationTitlesWithParameter(
|
||||||
|
property,
|
||||||
|
with_parameter,
|
||||||
|
with_parameter_value,
|
||||||
|
).length > 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setValidationException<V extends ValidationExceptionInterface<T>>(validationException: V): void {
|
function setValidationException<V extends ValidationExceptionInterface<T>>(
|
||||||
|
validationException: V,
|
||||||
|
): void {
|
||||||
violationsList.value = validationException;
|
violationsList.value = validationException;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,5 +67,12 @@ export function useViolationList<T extends Record<string, Record<string, string>
|
|||||||
violationsList.value = null;
|
violationsList.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {violationTitles, violationTitlesWithParameter, setValidationException, cleanException, hasViolationWithParameter, hasViolation};
|
return {
|
||||||
|
violationTitles,
|
||||||
|
violationTitlesWithParameter,
|
||||||
|
setValidationException,
|
||||||
|
cleanException,
|
||||||
|
hasViolationWithParameter,
|
||||||
|
hasViolation,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
DateTimeWrite,
|
DateTimeWrite,
|
||||||
SetGender,
|
SetGender,
|
||||||
SetCenter,
|
SetCenter,
|
||||||
SetCivility, Gender,
|
SetCivility,
|
||||||
|
Gender,
|
||||||
} from "ChillMainAssets/types";
|
} from "ChillMainAssets/types";
|
||||||
import { StoredObject } from "ChillDocStoreAssets/types";
|
import { StoredObject } from "ChillDocStoreAssets/types";
|
||||||
import { Thirdparty } from "../../../ChillThirdPartyBundle/Resources/public/types";
|
import { Thirdparty } from "../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
@@ -157,16 +158,16 @@ export interface AccompanyingPeriod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodWorkEvaluationDocument {
|
export interface AccompanyingPeriodWorkEvaluationDocument {
|
||||||
id: number;
|
id: number;
|
||||||
type: "accompanying_period_work_evaluation_document";
|
type: "accompanying_period_work_evaluation_document";
|
||||||
storedObject: StoredObject;
|
storedObject: StoredObject;
|
||||||
title: string;
|
title: string;
|
||||||
createdAt: DateTime | null;
|
createdAt: DateTime | null;
|
||||||
createdBy: User | null;
|
createdBy: User | null;
|
||||||
updatedAt: DateTime | null;
|
updatedAt: DateTime | null;
|
||||||
updatedBy: User | null;
|
updatedBy: User | null;
|
||||||
workflows_availables: WorkflowAvailable[];
|
workflows_availables: WorkflowAvailable[];
|
||||||
workflows: object[];
|
workflows: object[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodWork {
|
export interface AccompanyingPeriodWork {
|
||||||
@@ -195,139 +196,139 @@ export interface AccompanyingPeriodWork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface SocialAction {
|
interface SocialAction {
|
||||||
id: number;
|
id: number;
|
||||||
parent?: SocialAction | null;
|
parent?: SocialAction | null;
|
||||||
children: SocialAction[];
|
children: SocialAction[];
|
||||||
issue?: SocialIssue | null;
|
issue?: SocialIssue | null;
|
||||||
ordering: number;
|
ordering: number;
|
||||||
title: {
|
title: {
|
||||||
fr: string;
|
fr: string;
|
||||||
};
|
};
|
||||||
text: string;
|
text: string;
|
||||||
defaultNotificationDelay?: string | null;
|
defaultNotificationDelay?: string | null;
|
||||||
desactivationDate?: string | null;
|
desactivationDate?: string | null;
|
||||||
evaluations: Evaluation[];
|
evaluations: Evaluation[];
|
||||||
goals: Goal[];
|
goals: Goal[];
|
||||||
results: Result[];
|
results: Result[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodResource {
|
export interface AccompanyingPeriodResource {
|
||||||
id: number;
|
id: number;
|
||||||
accompanyingPeriod: AccompanyingPeriod;
|
accompanyingPeriod: AccompanyingPeriod;
|
||||||
comment?: string | null;
|
comment?: string | null;
|
||||||
person?: Person | null;
|
person?: Person | null;
|
||||||
thirdParty?: Thirdparty | null;
|
thirdParty?: Thirdparty | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Origin {
|
export interface Origin {
|
||||||
id: number;
|
id: number;
|
||||||
label: {
|
label: {
|
||||||
fr: string;
|
fr: string;
|
||||||
};
|
};
|
||||||
noActiveAfter: DateTime;
|
noActiveAfter: DateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClosingMotive {
|
export interface ClosingMotive {
|
||||||
id: number;
|
id: number;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
name: {
|
name: {
|
||||||
fr: string;
|
fr: string;
|
||||||
};
|
};
|
||||||
ordering: number;
|
ordering: number;
|
||||||
isCanceledAccompanyingPeriod: boolean;
|
isCanceledAccompanyingPeriod: boolean;
|
||||||
parent?: ClosingMotive | null;
|
parent?: ClosingMotive | null;
|
||||||
children: ClosingMotive[];
|
children: ClosingMotive[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodParticipation {
|
export interface AccompanyingPeriodParticipation {
|
||||||
id: number;
|
id: number;
|
||||||
startDate: DateTime;
|
startDate: DateTime;
|
||||||
endDate?: DateTime | null;
|
endDate?: DateTime | null;
|
||||||
accompanyingPeriod: AccompanyingPeriod;
|
accompanyingPeriod: AccompanyingPeriod;
|
||||||
person: Person;
|
person: Person;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodLocationHistory {
|
export interface AccompanyingPeriodLocationHistory {
|
||||||
id: number;
|
id: number;
|
||||||
startDate: DateTime;
|
startDate: DateTime;
|
||||||
endDate?: DateTime | null;
|
endDate?: DateTime | null;
|
||||||
addressLocation?: Address | null;
|
addressLocation?: Address | null;
|
||||||
period: AccompanyingPeriod;
|
period: AccompanyingPeriod;
|
||||||
personLocation?: Person | null;
|
personLocation?: Person | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SocialIssue {
|
export interface SocialIssue {
|
||||||
id: number;
|
id: number;
|
||||||
text: string;
|
text: string;
|
||||||
parent?: SocialIssue | null;
|
parent?: SocialIssue | null;
|
||||||
children: SocialIssue[];
|
children: SocialIssue[];
|
||||||
socialActions?: SocialAction[] | null;
|
socialActions?: SocialAction[] | null;
|
||||||
ordering: number;
|
ordering: number;
|
||||||
title: {
|
title: {
|
||||||
fr: string;
|
fr: string;
|
||||||
};
|
};
|
||||||
desactivationDate?: string | null;
|
desactivationDate?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Goal {
|
export interface Goal {
|
||||||
id: number;
|
id: number;
|
||||||
results: Result[];
|
results: Result[];
|
||||||
socialActions?: SocialAction[] | null;
|
socialActions?: SocialAction[] | null;
|
||||||
title: {
|
title: {
|
||||||
fr: string;
|
fr: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Result {
|
export interface Result {
|
||||||
id: number;
|
id: number;
|
||||||
accompanyingPeriodWorks: AccompanyingPeriodWork[];
|
accompanyingPeriodWorks: AccompanyingPeriodWork[];
|
||||||
accompanyingPeriodWorkGoals: AccompanyingPeriodWorkGoal[];
|
accompanyingPeriodWorkGoals: AccompanyingPeriodWorkGoal[];
|
||||||
goals: Goal[];
|
goals: Goal[];
|
||||||
socialActions: SocialAction[];
|
socialActions: SocialAction[];
|
||||||
title: {
|
title: {
|
||||||
fr: string;
|
fr: string;
|
||||||
};
|
};
|
||||||
desactivationDate?: string | null;
|
desactivationDate?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodWorkGoal {
|
export interface AccompanyingPeriodWorkGoal {
|
||||||
id: number;
|
id: number;
|
||||||
accompanyingPeriodWork: AccompanyingPeriodWork;
|
accompanyingPeriodWork: AccompanyingPeriodWork;
|
||||||
goal: Goal;
|
goal: Goal;
|
||||||
note: string;
|
note: string;
|
||||||
results: Result[];
|
results: Result[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodWorkEvaluation {
|
export interface AccompanyingPeriodWorkEvaluation {
|
||||||
type: 'accompanying_period_work_evaluation';
|
type: "accompanying_period_work_evaluation";
|
||||||
accompanyingPeriodWork: AccompanyingPeriodWork | null;
|
accompanyingPeriodWork: AccompanyingPeriodWork | null;
|
||||||
comment: string;
|
comment: string;
|
||||||
createdAt: DateTime | null;
|
createdAt: DateTime | null;
|
||||||
createdBy: User | null;
|
createdBy: User | null;
|
||||||
documents: AccompanyingPeriodWorkEvaluationDocument[];
|
documents: AccompanyingPeriodWorkEvaluationDocument[];
|
||||||
endDate: DateTime | null;
|
endDate: DateTime | null;
|
||||||
evaluation: Evaluation | null;
|
evaluation: Evaluation | null;
|
||||||
id: number | null;
|
id: number | null;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
key: any;
|
key: any;
|
||||||
maxDate: DateTime | null;
|
maxDate: DateTime | null;
|
||||||
startDate: DateTime | null;
|
startDate: DateTime | null;
|
||||||
updatedAt: DateTime | null;
|
updatedAt: DateTime | null;
|
||||||
updatedBy: User | null;
|
updatedBy: User | null;
|
||||||
warningInterval: string | null;
|
warningInterval: string | null;
|
||||||
timeSpent: number | null;
|
timeSpent: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Evaluation {
|
export interface Evaluation {
|
||||||
id: number;
|
id: number;
|
||||||
url: string;
|
url: string;
|
||||||
socialActions: SocialAction[];
|
socialActions: SocialAction[];
|
||||||
title: {
|
title: {
|
||||||
fr: string;
|
fr: string;
|
||||||
};
|
};
|
||||||
active: boolean;
|
active: boolean;
|
||||||
delay: string;
|
delay: string;
|
||||||
notificationDelay: string;
|
notificationDelay: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Step {
|
export interface Step {
|
||||||
@@ -394,15 +395,15 @@ export interface AccompanyingCourse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodWorkReferrerHistory {
|
export interface AccompanyingPeriodWorkReferrerHistory {
|
||||||
id: number;
|
id: number;
|
||||||
accompanyingPeriodWork: AccompanyingPeriodWork;
|
accompanyingPeriodWork: AccompanyingPeriodWork;
|
||||||
user: User;
|
user: User;
|
||||||
startDate: DateTime;
|
startDate: DateTime;
|
||||||
endDate: DateTime | null;
|
endDate: DateTime | null;
|
||||||
createdAt: DateTime;
|
createdAt: DateTime;
|
||||||
updatedAt: DateTime | null;
|
updatedAt: DateTime | null;
|
||||||
createdBy: User;
|
createdBy: User;
|
||||||
updatedBy: User | null;
|
updatedBy: User | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodWorkEvaluationDocument {
|
export interface AccompanyingPeriodWorkEvaluationDocument {
|
||||||
@@ -432,7 +433,7 @@ export type EntityType =
|
|||||||
| "user"
|
| "user"
|
||||||
| "household";
|
| "household";
|
||||||
|
|
||||||
export type Entities = (UserGroup | User | Person | Thirdparty | Household);
|
export type Entities = UserGroup | User | Person | Thirdparty | Household;
|
||||||
|
|
||||||
export function isEntityHousehold(e: Entities): e is Household {
|
export function isEntityHousehold(e: Entities): e is Household {
|
||||||
return e.type === "household";
|
return e.type === "household";
|
||||||
@@ -440,25 +441,34 @@ export function isEntityHousehold(e: Entities): e is Household {
|
|||||||
|
|
||||||
export type EntitiesOrMe = "me" | Entities;
|
export type EntitiesOrMe = "me" | Entities;
|
||||||
|
|
||||||
|
|
||||||
// Type guards to discriminate Suggestions by their result kind
|
// Type guards to discriminate Suggestions by their result kind
|
||||||
export function isSuggestionForUserGroup(s: Suggestion): s is Suggestion & { result: UserGroup } {
|
export function isSuggestionForUserGroup(
|
||||||
|
s: Suggestion,
|
||||||
|
): s is Suggestion & { result: UserGroup } {
|
||||||
return (s as any)?.result?.type === "user_group";
|
return (s as any)?.result?.type === "user_group";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSuggestionForUser(s: Suggestion): s is Suggestion & { result: User } {
|
export function isSuggestionForUser(
|
||||||
|
s: Suggestion,
|
||||||
|
): s is Suggestion & { result: User } {
|
||||||
return (s as any)?.result?.type === "user";
|
return (s as any)?.result?.type === "user";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSuggestionForPerson(s: Suggestion): s is Suggestion & { result: Person } {
|
export function isSuggestionForPerson(
|
||||||
|
s: Suggestion,
|
||||||
|
): s is Suggestion & { result: Person } {
|
||||||
return (s as any)?.result?.type === "person";
|
return (s as any)?.result?.type === "person";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSuggestionForThirdParty(s: Suggestion): s is Suggestion & { result: Thirdparty } {
|
export function isSuggestionForThirdParty(
|
||||||
|
s: Suggestion,
|
||||||
|
): s is Suggestion & { result: Thirdparty } {
|
||||||
return (s as any)?.result?.type === "thirdparty";
|
return (s as any)?.result?.type === "thirdparty";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSuggestionForHousehold(s: Suggestion): s is Suggestion & { result: Household } {
|
export function isSuggestionForHousehold(
|
||||||
|
s: Suggestion,
|
||||||
|
): s is Suggestion & { result: Household } {
|
||||||
return (s as any)?.result?.type === "household";
|
return (s as any)?.result?.type === "household";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +492,7 @@ export interface SearchPagination {
|
|||||||
export interface Search {
|
export interface Search {
|
||||||
count: number;
|
count: number;
|
||||||
pagination: SearchPagination;
|
pagination: SearchPagination;
|
||||||
results: {relevance: number, result: Entities}[];
|
results: { relevance: number; result: Entities }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchOptions {
|
export interface SearchOptions {
|
||||||
@@ -498,7 +508,11 @@ export interface SearchOptions {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type PersonIdentifierPresence = 'NOT_EDITABLE' | 'ON_EDIT' | 'ON_CREATION' | 'REQUIRED';
|
type PersonIdentifierPresence =
|
||||||
|
| "NOT_EDITABLE"
|
||||||
|
| "ON_EDIT"
|
||||||
|
| "ON_CREATION"
|
||||||
|
| "REQUIRED";
|
||||||
|
|
||||||
export interface PersonIdentifierWorker {
|
export interface PersonIdentifierWorker {
|
||||||
type: "person_identifier_worker";
|
type: "person_identifier_worker";
|
||||||
|
|||||||
@@ -42,9 +42,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button class="btn btn-save" @click="modal.showModal = true">
|
||||||
class="btn btn-save"
|
|
||||||
@click="modal.showModal = true">
|
|
||||||
{{ $t("confirm.ok") }}
|
{{ $t("confirm.ok") }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -84,8 +84,12 @@
|
|||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li class="add-persons">
|
<li class="add-persons">
|
||||||
<add-persons
|
<add-persons
|
||||||
:button-title="trans(ACCOMPANYING_COURSE_PERSONS_ASSOCIATED_ADD_PERSON)"
|
:button-title="
|
||||||
:modal-title="trans(ACCOMPANYING_COURSE_PERSONS_ASSOCIATED_ADD_PERSON)"
|
trans(ACCOMPANYING_COURSE_PERSONS_ASSOCIATED_ADD_PERSON)
|
||||||
|
"
|
||||||
|
:modal-title="
|
||||||
|
trans(ACCOMPANYING_COURSE_PERSONS_ASSOCIATED_ADD_PERSON)
|
||||||
|
"
|
||||||
:key="addPersons.key"
|
:key="addPersons.key"
|
||||||
:options="addPersons.options"
|
:options="addPersons.options"
|
||||||
@add-new-persons="addNewPersons"
|
@add-new-persons="addNewPersons"
|
||||||
@@ -108,7 +112,10 @@ import { mapGetters, mapState } from "vuex";
|
|||||||
import ParticipationItem from "./PersonsAssociated/ParticipationItem.vue";
|
import ParticipationItem from "./PersonsAssociated/ParticipationItem.vue";
|
||||||
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
||||||
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
||||||
import {ACCOMPANYING_COURSE_PERSONS_ASSOCIATED_ADD_PERSON, trans} from "translator";
|
import {
|
||||||
|
ACCOMPANYING_COURSE_PERSONS_ASSOCIATED_ADD_PERSON,
|
||||||
|
trans,
|
||||||
|
} from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PersonsAssociated",
|
name: "PersonsAssociated",
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
|
|||||||
import { mapState } from "vuex";
|
import { mapState } from "vuex";
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
||||||
import {ACCOMPANYING_COURSE_REQUESTOR_ADD, trans} from "translator";
|
import { ACCOMPANYING_COURSE_REQUESTOR_ADD, trans } from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Requestor",
|
name: "Requestor",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import { mapState } from "vuex";
|
|||||||
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
|
||||||
import ResourceItem from "./Resources/ResourceItem.vue";
|
import ResourceItem from "./Resources/ResourceItem.vue";
|
||||||
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
||||||
import {ACCOMPANYING_COURSE_RESOURCES_ADD_RESOURCES, trans} from "translator";
|
import { ACCOMPANYING_COURSE_RESOURCES_ADD_RESOURCES, trans } from "translator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Resources",
|
name: "Resources",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label class="col-sm-4 col-form-label visually-hidden">{{
|
<label class="col-sm-4 col-form-label visually-hidden">{{
|
||||||
trans(EVALUATION_PUBLIC_COMMENT)
|
trans(EVALUATION_PUBLIC_COMMENT)
|
||||||
}}</label>
|
}}</label>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<ckeditor
|
<ckeditor
|
||||||
:editor="ClassicEditor"
|
:editor="ClassicEditor"
|
||||||
:config="classicEditorConfig"
|
:config="classicEditorConfig"
|
||||||
:placeholder="trans(EVALUATION_COMMENT_PLACEHOLDER)"
|
:placeholder="trans(EVALUATION_COMMENT_PLACEHOLDER)"
|
||||||
:value="comment"
|
:value="comment"
|
||||||
@input="$emit('update:comment', $event)"
|
@input="$emit('update:comment', $event)"
|
||||||
tag-name="textarea"
|
tag-name="textarea"
|
||||||
></ckeditor>
|
></ckeditor>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -21,9 +21,9 @@ import { Ckeditor } from "@ckeditor/ckeditor5-vue";
|
|||||||
import { ClassicEditor } from "ckeditor5";
|
import { ClassicEditor } from "ckeditor5";
|
||||||
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
|
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
|
||||||
import {
|
import {
|
||||||
EVALUATION_PUBLIC_COMMENT,
|
EVALUATION_PUBLIC_COMMENT,
|
||||||
EVALUATION_COMMENT_PLACEHOLDER,
|
EVALUATION_COMMENT_PLACEHOLDER,
|
||||||
trans,
|
trans,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
|
|
||||||
defineProps(["comment"]);
|
defineProps(["comment"]);
|
||||||
|
|||||||
@@ -1,71 +1,71 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
||||||
{{ trans(EVALUATION_STARTDATE) }}
|
{{ trans(EVALUATION_STARTDATE) }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
||||||
<input
|
<input
|
||||||
class="form-control form-control-sm"
|
class="form-control form-control-sm"
|
||||||
type="date"
|
type="date"
|
||||||
:value="startDate"
|
:value="startDate"
|
||||||
@input="$emit('update:startDate', $event.target.value)"
|
@input="$emit('update:startDate', $event.target.value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
|
||||||
{{ trans(EVALUATION_ENDDATE) }}
|
|
||||||
</label>
|
|
||||||
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
|
||||||
<input
|
|
||||||
class="form-control form-control-sm"
|
|
||||||
type="date"
|
|
||||||
:value="endDate"
|
|
||||||
@input="$emit('update:endDate', $event.target.value)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
||||||
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
{{ trans(EVALUATION_ENDDATE) }}
|
||||||
{{ trans(EVALUATION_MAXDATE) }}
|
</label>
|
||||||
</label>
|
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
||||||
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
<input
|
||||||
<input
|
class="form-control form-control-sm"
|
||||||
class="form-control form-control-sm"
|
type="date"
|
||||||
type="date"
|
:value="endDate"
|
||||||
:value="maxDate"
|
@input="$emit('update:endDate', $event.target.value)"
|
||||||
@input="$emit('update:maxDate', $event.target.value)"
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
|
||||||
{{ trans(EVALUATION_WARNING_INTERVAL) }}
|
|
||||||
</label>
|
|
||||||
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
|
||||||
<input
|
|
||||||
class="form-control form-control-sm"
|
|
||||||
type="number"
|
|
||||||
:value="warningInterval"
|
|
||||||
@input="$emit('update:warningInterval', $event.target.value)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
||||||
|
{{ trans(EVALUATION_MAXDATE) }}
|
||||||
|
</label>
|
||||||
|
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
||||||
|
<input
|
||||||
|
class="form-control form-control-sm"
|
||||||
|
type="date"
|
||||||
|
:value="maxDate"
|
||||||
|
@input="$emit('update:maxDate', $event.target.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
||||||
|
{{ trans(EVALUATION_WARNING_INTERVAL) }}
|
||||||
|
</label>
|
||||||
|
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
||||||
|
<input
|
||||||
|
class="form-control form-control-sm"
|
||||||
|
type="number"
|
||||||
|
:value="warningInterval"
|
||||||
|
@input="$emit('update:warningInterval', $event.target.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
EVALUATION_STARTDATE,
|
EVALUATION_STARTDATE,
|
||||||
EVALUATION_ENDDATE,
|
EVALUATION_ENDDATE,
|
||||||
EVALUATION_MAXDATE,
|
EVALUATION_MAXDATE,
|
||||||
EVALUATION_WARNING_INTERVAL,
|
EVALUATION_WARNING_INTERVAL,
|
||||||
trans,
|
trans,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
|
|
||||||
defineProps(["startDate", "endDate", "maxDate", "warningInterval"]);
|
defineProps(["startDate", "endDate", "maxDate", "warningInterval"]);
|
||||||
defineEmits([
|
defineEmits([
|
||||||
"update:startDate",
|
"update:startDate",
|
||||||
"update:endDate",
|
"update:endDate",
|
||||||
"update:maxDate",
|
"update:maxDate",
|
||||||
"update:warningInterval",
|
"update:warningInterval",
|
||||||
]);
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<h6>{{ trans(EVALUATION_DOCUMENT_ADD) }} :</h6>
|
<h6>{{ trans(EVALUATION_DOCUMENT_ADD) }} :</h6>
|
||||||
<pick-template
|
<pick-template
|
||||||
entityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation"
|
entityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation"
|
||||||
:id="evaluation.id"
|
:id="evaluation.id"
|
||||||
:templates="templates"
|
:templates="templates"
|
||||||
:preventDefaultMoveToGenerate="true"
|
:preventDefaultMoveToGenerate="true"
|
||||||
@go-to-generate-document="submitBeforeGenerate"
|
@go-to-generate-document="submitBeforeGenerate"
|
||||||
>
|
>
|
||||||
<template v-slot:title>
|
<template v-slot:title>
|
||||||
<label class="col-form-label">{{
|
<label class="col-form-label">{{
|
||||||
trans(EVALUATION_GENERATE_A_DOCUMENT)
|
trans(EVALUATION_GENERATE_A_DOCUMENT)
|
||||||
}}</label>
|
}}</label>
|
||||||
</template>
|
</template>
|
||||||
</pick-template>
|
</pick-template>
|
||||||
<div>
|
<div>
|
||||||
<label class="col-form-label">{{
|
<label class="col-form-label">{{
|
||||||
trans(EVALUATION_DOCUMENT_UPLOAD)
|
trans(EVALUATION_DOCUMENT_UPLOAD)
|
||||||
}}</label>
|
}}</label>
|
||||||
<ul class="record_actions document-upload">
|
<ul class="record_actions document-upload">
|
||||||
<li>
|
<li>
|
||||||
<drop-file-modal
|
<drop-file-modal
|
||||||
:allow-remove="false"
|
:allow-remove="false"
|
||||||
@add-document="emit('addDocument', $event)"
|
@add-document="emit('addDocument', $event)"
|
||||||
></drop-file-modal>
|
></drop-file-modal>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
|
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
|
||||||
import DropFileModal from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileModal.vue";
|
import DropFileModal from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileModal.vue";
|
||||||
import {
|
import {
|
||||||
EVALUATION_DOCUMENT_ADD,
|
EVALUATION_DOCUMENT_ADD,
|
||||||
EVALUATION_DOCUMENT_UPLOAD,
|
EVALUATION_DOCUMENT_UPLOAD,
|
||||||
EVALUATION_GENERATE_A_DOCUMENT,
|
EVALUATION_GENERATE_A_DOCUMENT,
|
||||||
trans,
|
trans,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
|
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
|
||||||
import { useStore } from "vuex";
|
import { useStore } from "vuex";
|
||||||
@@ -48,29 +48,29 @@ const props = defineProps(["evaluation", "templates"]);
|
|||||||
const emit = defineEmits(["addDocument"]);
|
const emit = defineEmits(["addDocument"]);
|
||||||
|
|
||||||
async function submitBeforeGenerate({ template }) {
|
async function submitBeforeGenerate({ template }) {
|
||||||
const callback = (data) => {
|
const callback = (data) => {
|
||||||
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(
|
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(
|
||||||
(e) => e.key === props.evaluation.key,
|
(e) => e.key === props.evaluation.key,
|
||||||
).id;
|
).id;
|
||||||
|
|
||||||
window.location.assign(
|
window.location.assign(
|
||||||
buildLink(
|
buildLink(
|
||||||
template,
|
template,
|
||||||
evaluationId,
|
evaluationId,
|
||||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation",
|
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return store.dispatch("submit", callback).catch((e) => {
|
return store.dispatch("submit", callback).catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
ul.document-upload {
|
ul.document-upload {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,288 +1,205 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<h5>{{ trans(EVALUATION_DOCUMENTS) }} :</h5>
|
<h5>{{ trans(EVALUATION_DOCUMENTS) }} :</h5>
|
||||||
<div class="flex-table">
|
<div class="flex-table">
|
||||||
<div
|
<div
|
||||||
class="item-bloc"
|
class="item-bloc"
|
||||||
v-for="(d, i) in documents"
|
v-for="(d, i) in documents"
|
||||||
:key="d.id"
|
:key="d.id"
|
||||||
:class="[
|
:class="[parseInt(docAnchorId) === d.id ? 'bg-blink' : 'nothing']"
|
||||||
parseInt(docAnchorId) === d.id ? 'bg-blink' : 'nothing',
|
>
|
||||||
]"
|
<div :id="'document_' + d.id" class="item-row">
|
||||||
>
|
<div class="input-group input-group-lg mb-3 row">
|
||||||
<div :id="'document_' + d.id" class="item-row">
|
<label class="col-sm-3 col-form-label">Titre du document:</label>
|
||||||
<div class="input-group input-group-lg mb-3 row">
|
<div class="col-sm-9">
|
||||||
<label class="col-sm-3 col-form-label"
|
<input
|
||||||
>Titre du document:</label
|
class="form-control document-title"
|
||||||
>
|
type="text"
|
||||||
<div class="col-sm-9">
|
:value="d.title"
|
||||||
<input
|
:id="d.id"
|
||||||
class="form-control document-title"
|
:data-key="i"
|
||||||
type="text"
|
@input="$emit('inputDocumentTitle', $event)"
|
||||||
:value="d.title"
|
/>
|
||||||
:id="d.id"
|
|
||||||
:data-key="i"
|
|
||||||
@input="$emit('inputDocumentTitle', $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item-row">
|
|
||||||
<div class="item-col item-meta">
|
|
||||||
<p v-if="d.createdBy" class="createdBy">
|
|
||||||
Créé par {{ d.createdBy.text }}<br />
|
|
||||||
Le
|
|
||||||
{{
|
|
||||||
$d(ISOToDatetime(d.createdAt.datetime), "long")
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item-row">
|
|
||||||
<div class="item-col">
|
|
||||||
<ul class="record_actions">
|
|
||||||
<li
|
|
||||||
v-if="
|
|
||||||
d.workflows_availables.length > 0 ||
|
|
||||||
d.workflows.length > 0
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<list-workflow-modal
|
|
||||||
:workflows="d.workflows"
|
|
||||||
:allowCreate="true"
|
|
||||||
relatedEntityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument"
|
|
||||||
:relatedEntityId="d.id"
|
|
||||||
:workflowsAvailables="
|
|
||||||
d.workflows_availables
|
|
||||||
"
|
|
||||||
:preventDefaultMoveToGenerate="true"
|
|
||||||
:goToGenerateWorkflowPayload="{ doc: d }"
|
|
||||||
@go-to-generate-workflow="
|
|
||||||
goToGenerateWorkflowEvaluationDocument
|
|
||||||
"
|
|
||||||
></list-workflow-modal>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
v-if="AmIRefferer"
|
|
||||||
class="btn btn-notify"
|
|
||||||
@click="
|
|
||||||
$emit(
|
|
||||||
'goToGenerateNotification',
|
|
||||||
d,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
></button>
|
|
||||||
<template v-else>
|
|
||||||
<button
|
|
||||||
id="btnGroupNotifyButtons"
|
|
||||||
type="button"
|
|
||||||
class="btn btn-notify dropdown-toggle"
|
|
||||||
:title="
|
|
||||||
trans(EVALUATION_NOTIFICATION_SEND)
|
|
||||||
"
|
|
||||||
data-bs-toggle="dropdown"
|
|
||||||
aria-expanded="false"
|
|
||||||
>
|
|
||||||
|
|
||||||
</button>
|
|
||||||
<ul
|
|
||||||
class="dropdown-menu"
|
|
||||||
aria-labelledby="btnGroupNotifyButtons"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
@click="
|
|
||||||
goToGenerateDocumentNotification(
|
|
||||||
d,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
trans(
|
|
||||||
EVALUATION_NOTIFICATION_NOTIFY_REFERRER,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
@click="
|
|
||||||
goToGenerateDocumentNotification(
|
|
||||||
d,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
trans(
|
|
||||||
EVALUATION_NOTIFICATION_NOTIFY_ANY,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<document-action-buttons-group
|
|
||||||
:stored-object="d.storedObject"
|
|
||||||
:filename="d.title"
|
|
||||||
:can-edit="true"
|
|
||||||
:execute-before-leave="
|
|
||||||
submitBeforeLeaveToEditor
|
|
||||||
"
|
|
||||||
:davLink="
|
|
||||||
d.storedObject._links?.dav_link.href
|
|
||||||
"
|
|
||||||
:davLinkExpiration="
|
|
||||||
d.storedObject._links?.dav_link
|
|
||||||
.expiration
|
|
||||||
"
|
|
||||||
@on-stored-object-status-change="
|
|
||||||
$emit('statusDocumentChanged', $event)
|
|
||||||
"
|
|
||||||
></document-action-buttons-group>
|
|
||||||
</li>
|
|
||||||
<!--replace document-->
|
|
||||||
<li
|
|
||||||
v-if="
|
|
||||||
Number.isInteger(d.id) &&
|
|
||||||
d.storedObject._permissions.canEdit
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<drop-file-modal
|
|
||||||
:existing-doc="d.storedObject"
|
|
||||||
:allow-remove="false"
|
|
||||||
@add-document="
|
|
||||||
(arg) =>
|
|
||||||
replaceDocument(
|
|
||||||
d,
|
|
||||||
arg.stored_object,
|
|
||||||
arg.stored_object_version,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
></drop-file-modal>
|
|
||||||
</li>
|
|
||||||
<li v-if="Number.isInteger(d.id)">
|
|
||||||
<div class="duplicate-dropdown">
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-primary dropdown-toggle"
|
|
||||||
type="button"
|
|
||||||
data-bs-toggle="dropdown"
|
|
||||||
aria-expanded="false"
|
|
||||||
>
|
|
||||||
<i class="bi bi-lightning-fill"></i>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<!--delete-->
|
|
||||||
<li v-if="d.workflows.length === 0">
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
@click="
|
|
||||||
$emit('removeDocument', d)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="fa fa-trash-o"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
{{
|
|
||||||
trans(
|
|
||||||
EVALUATION_DOCUMENT_DELETE,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<!--duplicate document-->
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
@click="
|
|
||||||
$emit(
|
|
||||||
'duplicateDocument',
|
|
||||||
d,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="fa fa-copy"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
{{
|
|
||||||
trans(
|
|
||||||
EVALUATION_DOCUMENT_DUPLICATE_HERE,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
@click="
|
|
||||||
prepareDocumentDuplicationToWork(
|
|
||||||
d,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="fa fa-copy"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
{{
|
|
||||||
trans(
|
|
||||||
EVALUATION_DOCUMENT_DUPLICATE_TO_OTHER_EVALUATION,
|
|
||||||
)
|
|
||||||
}}</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<!--move document-->
|
|
||||||
<li
|
|
||||||
v-if="
|
|
||||||
d.storedObject._permissions
|
|
||||||
.canEdit
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
@click="
|
|
||||||
prepareDocumentMoveToWork(d)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="fa fa-arrows"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
{{
|
|
||||||
trans(
|
|
||||||
EVALUATION_DOCUMENT_MOVE,
|
|
||||||
)
|
|
||||||
}}</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="item-row">
|
||||||
|
<div class="item-col item-meta">
|
||||||
|
<p v-if="d.createdBy" class="createdBy">
|
||||||
|
Créé par {{ d.createdBy.text }}<br />
|
||||||
|
Le
|
||||||
|
{{ $d(ISOToDatetime(d.createdAt.datetime), "long") }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item-row">
|
||||||
|
<div class="item-col">
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li
|
||||||
|
v-if="
|
||||||
|
d.workflows_availables.length > 0 || d.workflows.length > 0
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<list-workflow-modal
|
||||||
|
:workflows="d.workflows"
|
||||||
|
:allowCreate="true"
|
||||||
|
relatedEntityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument"
|
||||||
|
:relatedEntityId="d.id"
|
||||||
|
:workflowsAvailables="d.workflows_availables"
|
||||||
|
:preventDefaultMoveToGenerate="true"
|
||||||
|
:goToGenerateWorkflowPayload="{ doc: d }"
|
||||||
|
@go-to-generate-workflow="
|
||||||
|
goToGenerateWorkflowEvaluationDocument
|
||||||
|
"
|
||||||
|
></list-workflow-modal>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
v-if="AmIRefferer"
|
||||||
|
class="btn btn-notify"
|
||||||
|
@click="$emit('goToGenerateNotification', d, false)"
|
||||||
|
></button>
|
||||||
|
<template v-else>
|
||||||
|
<button
|
||||||
|
id="btnGroupNotifyButtons"
|
||||||
|
type="button"
|
||||||
|
class="btn btn-notify dropdown-toggle"
|
||||||
|
:title="trans(EVALUATION_NOTIFICATION_SEND)"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
|
||||||
|
</button>
|
||||||
|
<ul
|
||||||
|
class="dropdown-menu"
|
||||||
|
aria-labelledby="btnGroupNotifyButtons"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="goToGenerateDocumentNotification(d, true)"
|
||||||
|
>
|
||||||
|
{{ trans(EVALUATION_NOTIFICATION_NOTIFY_REFERRER) }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="goToGenerateDocumentNotification(d, false)"
|
||||||
|
>
|
||||||
|
{{ trans(EVALUATION_NOTIFICATION_NOTIFY_ANY) }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<document-action-buttons-group
|
||||||
|
:stored-object="d.storedObject"
|
||||||
|
:filename="d.title"
|
||||||
|
:can-edit="true"
|
||||||
|
:execute-before-leave="submitBeforeLeaveToEditor"
|
||||||
|
:davLink="d.storedObject._links?.dav_link.href"
|
||||||
|
:davLinkExpiration="
|
||||||
|
d.storedObject._links?.dav_link.expiration
|
||||||
|
"
|
||||||
|
@on-stored-object-status-change="
|
||||||
|
$emit('statusDocumentChanged', $event)
|
||||||
|
"
|
||||||
|
></document-action-buttons-group>
|
||||||
|
</li>
|
||||||
|
<!--replace document-->
|
||||||
|
<li
|
||||||
|
v-if="
|
||||||
|
Number.isInteger(d.id) && d.storedObject._permissions.canEdit
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<drop-file-modal
|
||||||
|
:existing-doc="d.storedObject"
|
||||||
|
:allow-remove="false"
|
||||||
|
@add-document="
|
||||||
|
(arg) =>
|
||||||
|
replaceDocument(
|
||||||
|
d,
|
||||||
|
arg.stored_object,
|
||||||
|
arg.stored_object_version,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
></drop-file-modal>
|
||||||
|
</li>
|
||||||
|
<li v-if="Number.isInteger(d.id)">
|
||||||
|
<div class="duplicate-dropdown">
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-primary dropdown-toggle"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
<i class="bi bi-lightning-fill"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<!--delete-->
|
||||||
|
<li v-if="d.workflows.length === 0">
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="$emit('removeDocument', d)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-trash-o" aria-hidden="true"></i>
|
||||||
|
{{ trans(EVALUATION_DOCUMENT_DELETE) }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<!--duplicate document-->
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="$emit('duplicateDocument', d)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-copy" aria-hidden="true"></i>
|
||||||
|
{{ trans(EVALUATION_DOCUMENT_DUPLICATE_HERE) }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="prepareDocumentDuplicationToWork(d)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-copy" aria-hidden="true"></i>
|
||||||
|
{{
|
||||||
|
trans(
|
||||||
|
EVALUATION_DOCUMENT_DUPLICATE_TO_OTHER_EVALUATION,
|
||||||
|
)
|
||||||
|
}}</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<!--move document-->
|
||||||
|
<li v-if="d.storedObject._permissions.canEdit">
|
||||||
|
<a
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="prepareDocumentMoveToWork(d)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-arrows" aria-hidden="true"></i>
|
||||||
|
{{ trans(EVALUATION_DOCUMENT_MOVE) }}</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<AccompanyingPeriodWorkSelectorModal
|
<AccompanyingPeriodWorkSelectorModal
|
||||||
v-if="showAccompanyingPeriodSelector"
|
v-if="showAccompanyingPeriodSelector"
|
||||||
v-model:selectedAcpw="selectedAcpw"
|
v-model:selectedAcpw="selectedAcpw"
|
||||||
:accompanying-period-id="accompanyingPeriodId"
|
:accompanying-period-id="accompanyingPeriodId"
|
||||||
:is-evaluation-selector="true"
|
:is-evaluation-selector="true"
|
||||||
:ignore-accompanying-period-work-ids="[]"
|
:ignore-accompanying-period-work-ids="[]"
|
||||||
@close-modal="showAccompanyingPeriodSelector = false"
|
@close-modal="showAccompanyingPeriodSelector = false"
|
||||||
@update:selectedEvaluation="selectedEvaluation = $event"
|
@update:selectedEvaluation="selectedEvaluation = $event"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -291,15 +208,15 @@ import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/
|
|||||||
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
|
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
|
||||||
import DropFileModal from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileModal.vue";
|
import DropFileModal from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileModal.vue";
|
||||||
import {
|
import {
|
||||||
EVALUATION_NOTIFICATION_NOTIFY_REFERRER,
|
EVALUATION_NOTIFICATION_NOTIFY_REFERRER,
|
||||||
EVALUATION_NOTIFICATION_NOTIFY_ANY,
|
EVALUATION_NOTIFICATION_NOTIFY_ANY,
|
||||||
EVALUATION_NOTIFICATION_SEND,
|
EVALUATION_NOTIFICATION_SEND,
|
||||||
EVALUATION_DOCUMENTS,
|
EVALUATION_DOCUMENTS,
|
||||||
EVALUATION_DOCUMENT_MOVE,
|
EVALUATION_DOCUMENT_MOVE,
|
||||||
EVALUATION_DOCUMENT_DELETE,
|
EVALUATION_DOCUMENT_DELETE,
|
||||||
EVALUATION_DOCUMENT_DUPLICATE_HERE,
|
EVALUATION_DOCUMENT_DUPLICATE_HERE,
|
||||||
EVALUATION_DOCUMENT_DUPLICATE_TO_OTHER_EVALUATION,
|
EVALUATION_DOCUMENT_DUPLICATE_TO_OTHER_EVALUATION,
|
||||||
trans,
|
trans,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, ref, watch } from "vue";
|
||||||
import AccompanyingPeriodWorkSelectorModal from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkSelectorModal.vue";
|
import AccompanyingPeriodWorkSelectorModal from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkSelectorModal.vue";
|
||||||
@@ -308,17 +225,17 @@ import { buildLinkCreate as buildLinkCreateNotification } from "ChillMainAssets/
|
|||||||
import { useStore } from "vuex";
|
import { useStore } from "vuex";
|
||||||
|
|
||||||
const props = defineProps([
|
const props = defineProps([
|
||||||
"documents",
|
"documents",
|
||||||
"docAnchorId",
|
"docAnchorId",
|
||||||
"accompanyingPeriodId",
|
"accompanyingPeriodId",
|
||||||
"evaluation",
|
"evaluation",
|
||||||
]);
|
]);
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
"inputDocumentTitle",
|
"inputDocumentTitle",
|
||||||
"removeDocument",
|
"removeDocument",
|
||||||
"duplicateDocument",
|
"duplicateDocument",
|
||||||
"statusDocumentChanged",
|
"statusDocumentChanged",
|
||||||
"duplicateDocumentToWork",
|
"duplicateDocumentToWork",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
@@ -329,67 +246,67 @@ const selectedDocumentToDuplicate = ref(null);
|
|||||||
const selectedDocumentToMove = ref(null);
|
const selectedDocumentToMove = ref(null);
|
||||||
|
|
||||||
const AmIRefferer = computed(() => {
|
const AmIRefferer = computed(() => {
|
||||||
return !(
|
return !(
|
||||||
store.state.work.accompanyingPeriod.user &&
|
store.state.work.accompanyingPeriod.user &&
|
||||||
store.state.me &&
|
store.state.me &&
|
||||||
store.state.work.accompanyingPeriod.user.id !== store.state.me.id
|
store.state.work.accompanyingPeriod.user.id !== store.state.me.id
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const prepareDocumentDuplicationToWork = (d) => {
|
const prepareDocumentDuplicationToWork = (d) => {
|
||||||
selectedDocumentToDuplicate.value = d;
|
selectedDocumentToDuplicate.value = d;
|
||||||
/** ensure selectedDocumentToMove is null */
|
/** ensure selectedDocumentToMove is null */
|
||||||
selectedDocumentToMove.value = null;
|
selectedDocumentToMove.value = null;
|
||||||
|
|
||||||
showAccompanyingPeriodSelector.value = true;
|
showAccompanyingPeriodSelector.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const prepareDocumentMoveToWork = (d) => {
|
const prepareDocumentMoveToWork = (d) => {
|
||||||
selectedDocumentToMove.value = d;
|
selectedDocumentToMove.value = d;
|
||||||
/** ensure selectedDocumentToDuplicate is null */
|
/** ensure selectedDocumentToDuplicate is null */
|
||||||
selectedDocumentToDuplicate.value = null;
|
selectedDocumentToDuplicate.value = null;
|
||||||
|
|
||||||
showAccompanyingPeriodSelector.value = true;
|
showAccompanyingPeriodSelector.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(selectedEvaluation, (val) => {
|
watch(selectedEvaluation, (val) => {
|
||||||
if (selectedDocumentToDuplicate.value) {
|
if (selectedDocumentToDuplicate.value) {
|
||||||
emit("duplicateDocumentToEvaluation", {
|
emit("duplicateDocumentToEvaluation", {
|
||||||
evaluation: val,
|
evaluation: val,
|
||||||
document: selectedDocumentToDuplicate.value,
|
document: selectedDocumentToDuplicate.value,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
emit("moveDocumentToEvaluation", {
|
emit("moveDocumentToEvaluation", {
|
||||||
evaluationDest: val,
|
evaluationDest: val,
|
||||||
document: selectedDocumentToMove.value,
|
document: selectedDocumentToMove.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function goToGenerateWorkflowEvaluationDocument({
|
async function goToGenerateWorkflowEvaluationDocument({
|
||||||
workflowName,
|
workflowName,
|
||||||
payload,
|
payload,
|
||||||
}) {
|
}) {
|
||||||
const callback = (data) => {
|
const callback = (data) => {
|
||||||
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
||||||
(e) => e.key === props.evaluation.key,
|
(e) => e.key === props.evaluation.key,
|
||||||
);
|
);
|
||||||
let updatedDocument = evaluation.documents.find(
|
let updatedDocument = evaluation.documents.find(
|
||||||
(d) => d.key === payload.doc.key,
|
(d) => d.key === payload.doc.key,
|
||||||
);
|
);
|
||||||
window.location.assign(
|
window.location.assign(
|
||||||
buildLinkCreate(
|
buildLinkCreate(
|
||||||
workflowName,
|
workflowName,
|
||||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
||||||
updatedDocument.id,
|
updatedDocument.id,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return store.dispatch("submit", callback).catch((e) => {
|
return store.dispatch("submit", callback).catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -401,55 +318,53 @@ async function goToGenerateWorkflowEvaluationDocument({
|
|||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
async function replaceDocument(oldDocument, storedObject, storedObjectVersion) {
|
async function replaceDocument(oldDocument, storedObject, storedObjectVersion) {
|
||||||
let document = {
|
let document = {
|
||||||
type: "accompanying_period_work_evaluation_document",
|
type: "accompanying_period_work_evaluation_document",
|
||||||
storedObject: storedObject,
|
storedObject: storedObject,
|
||||||
title: oldDocument.title,
|
title: oldDocument.title,
|
||||||
};
|
};
|
||||||
|
|
||||||
return store.commit("replaceDocument", {
|
return store.commit("replaceDocument", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
document,
|
document,
|
||||||
oldDocument: oldDocument,
|
oldDocument: oldDocument,
|
||||||
stored_object_version: storedObjectVersion,
|
stored_object_version: storedObjectVersion,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function goToGenerateDocumentNotification(document, tos) {
|
async function goToGenerateDocumentNotification(document, tos) {
|
||||||
const callback = (data) => {
|
const callback = (data) => {
|
||||||
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
||||||
(e) => e.key === props.evaluation.key,
|
(e) => e.key === props.evaluation.key,
|
||||||
);
|
);
|
||||||
let updatedDocument = evaluation.documents.find(
|
let updatedDocument = evaluation.documents.find(
|
||||||
(d) => d.key === document.key,
|
(d) => d.key === document.key,
|
||||||
);
|
);
|
||||||
window.location.assign(
|
window.location.assign(
|
||||||
buildLinkCreateNotification(
|
buildLinkCreateNotification(
|
||||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
||||||
updatedDocument.id,
|
updatedDocument.id,
|
||||||
tos === true
|
tos === true ? store.state.work.accompanyingPeriod.user?.id : null,
|
||||||
? store.state.work.accompanyingPeriod.user?.id
|
window.location.pathname +
|
||||||
: null,
|
window.location.search +
|
||||||
window.location.pathname +
|
window.location.hash,
|
||||||
window.location.search +
|
),
|
||||||
window.location.hash,
|
);
|
||||||
),
|
};
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return store.dispatch("submit", callback).catch((e) => {
|
return store.dispatch("submit", callback).catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitBeforeLeaveToEditor() {
|
async function submitBeforeLeaveToEditor() {
|
||||||
console.log("submit beore edit 2");
|
console.log("submit beore edit 2");
|
||||||
// empty callback
|
// empty callback
|
||||||
const callback = () => null;
|
const callback = () => null;
|
||||||
return store.dispatch("submit", callback).catch((e) => {
|
return store.dispatch("submit", callback).catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,49 +1,47 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="m-md-3">
|
<div class="m-md-3">
|
||||||
<DateInputs
|
<DateInputs
|
||||||
:startDate="startDate"
|
:startDate="startDate"
|
||||||
:endDate="endDate"
|
:endDate="endDate"
|
||||||
:maxDate="maxDate"
|
:maxDate="maxDate"
|
||||||
:warningInterval="warningInterval"
|
:warningInterval="warningInterval"
|
||||||
@update:startDate="updateStartDate"
|
@update:startDate="updateStartDate"
|
||||||
@update:endDate="updateEndDate"
|
@update:endDate="updateEndDate"
|
||||||
@update:maxDate="updateMaxDate"
|
@update:maxDate="updateMaxDate"
|
||||||
@update:warningInterval="updateWarningInterval"
|
@update:warningInterval="updateWarningInterval"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TimeSpentInput
|
<TimeSpentInput
|
||||||
:timeSpent="timeSpent"
|
:timeSpent="timeSpent"
|
||||||
:timeSpentChoices="timeSpentChoices"
|
:timeSpentChoices="timeSpentChoices"
|
||||||
@update:timeSpent="updateTimeSpent"
|
@update:timeSpent="updateTimeSpent"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CommentInput :comment="comment" @update:comment="updateComment" />
|
<CommentInput :comment="comment" @update:comment="updateComment" />
|
||||||
|
|
||||||
<DocumentsList
|
<DocumentsList
|
||||||
v-if="evaluation.documents.length > 0"
|
v-if="evaluation.documents.length > 0"
|
||||||
:documents="evaluation.documents"
|
:documents="evaluation.documents"
|
||||||
:docAnchorId="docAnchorId"
|
:docAnchorId="docAnchorId"
|
||||||
:evaluation="evaluation"
|
:evaluation="evaluation"
|
||||||
:accompanyingPeriodId="store.state.work.accompanyingPeriod.id"
|
:accompanyingPeriodId="store.state.work.accompanyingPeriod.id"
|
||||||
@inputDocumentTitle="onInputDocumentTitle"
|
@inputDocumentTitle="onInputDocumentTitle"
|
||||||
@removeDocument="removeDocument"
|
@removeDocument="removeDocument"
|
||||||
@duplicateDocument="duplicateDocument"
|
@duplicateDocument="duplicateDocument"
|
||||||
@duplicate-document-to-evaluation="
|
@duplicate-document-to-evaluation="duplicateDocumentToEvaluation"
|
||||||
duplicateDocumentToEvaluation
|
@move-document-to-evaluation="moveDocumentToEvaluation"
|
||||||
"
|
@statusDocumentChanged="onStatusDocumentChanged"
|
||||||
@move-document-to-evaluation="moveDocumentToEvaluation"
|
@goToGenerateNotification="goToGenerateDocumentNotification"
|
||||||
@statusDocumentChanged="onStatusDocumentChanged"
|
/>
|
||||||
@goToGenerateNotification="goToGenerateDocumentNotification"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DocumentActions
|
<DocumentActions
|
||||||
:evaluation="evaluation"
|
:evaluation="evaluation"
|
||||||
:templates="getTemplatesAvailables"
|
:templates="getTemplatesAvailables"
|
||||||
@addDocument="addDocument"
|
@addDocument="addDocument"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -55,9 +53,9 @@ import CommentInput from "./CommentInput.vue";
|
|||||||
import DocumentsList from "./DocumentsList.vue";
|
import DocumentsList from "./DocumentsList.vue";
|
||||||
import DocumentActions from "./DocumentActions.vue";
|
import DocumentActions from "./DocumentActions.vue";
|
||||||
import {
|
import {
|
||||||
trans,
|
trans,
|
||||||
EVALUATION_DOCUMENT_DUPLICATE_SUCCESS,
|
EVALUATION_DOCUMENT_DUPLICATE_SUCCESS,
|
||||||
EVALUATION_DOCUMENT_MOVE_SUCCESS,
|
EVALUATION_DOCUMENT_MOVE_SUCCESS,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import { useToast } from "vue-toast-notification";
|
import { useToast } from "vue-toast-notification";
|
||||||
import { buildLinkCreate as buildLinkCreateNotification } from "ChillMainAssets/lib/entity-notification/api";
|
import { buildLinkCreate as buildLinkCreateNotification } from "ChillMainAssets/lib/entity-notification/api";
|
||||||
@@ -68,359 +66,357 @@ const store = useStore();
|
|||||||
const $toast = useToast();
|
const $toast = useToast();
|
||||||
|
|
||||||
const timeSpentValues = [
|
const timeSpentValues = [
|
||||||
60,
|
60,
|
||||||
120,
|
120,
|
||||||
180,
|
180,
|
||||||
240,
|
240,
|
||||||
300,
|
300,
|
||||||
600,
|
600,
|
||||||
900,
|
900,
|
||||||
1200,
|
1200,
|
||||||
1500,
|
1500,
|
||||||
1800,
|
1800,
|
||||||
2700,
|
2700,
|
||||||
3600,
|
3600,
|
||||||
4500,
|
4500,
|
||||||
5400,
|
5400,
|
||||||
6300,
|
6300,
|
||||||
7200,
|
7200,
|
||||||
9000,
|
9000,
|
||||||
10800,
|
10800,
|
||||||
12600,
|
12600,
|
||||||
14400,
|
14400,
|
||||||
16200,
|
16200,
|
||||||
18000,
|
18000,
|
||||||
19800,
|
19800,
|
||||||
21600,
|
21600,
|
||||||
23400,
|
23400,
|
||||||
25200,
|
25200,
|
||||||
27000,
|
27000,
|
||||||
28800,
|
28800,
|
||||||
43200,
|
43200,
|
||||||
57600,
|
57600,
|
||||||
72000,
|
72000,
|
||||||
86400,
|
86400,
|
||||||
100800,
|
100800,
|
||||||
115200,
|
115200,
|
||||||
129600,
|
129600,
|
||||||
144000, // goes from 1 minute to 40 hours
|
144000, // goes from 1 minute to 40 hours
|
||||||
];
|
];
|
||||||
|
|
||||||
const formatDuration = (seconds, locale) => {
|
const formatDuration = (seconds, locale) => {
|
||||||
const currentLocale = locale || navigator.language || "fr";
|
const currentLocale = locale || navigator.language || "fr";
|
||||||
|
|
||||||
const totalHours = Math.floor(seconds / 3600);
|
const totalHours = Math.floor(seconds / 3600);
|
||||||
const remainingMinutes = Math.floor((seconds % 3600) / 60);
|
const remainingMinutes = Math.floor((seconds % 3600) / 60);
|
||||||
|
|
||||||
if (totalHours >= 8) {
|
if (totalHours >= 8) {
|
||||||
const days = Math.floor(totalHours / 8);
|
const days = Math.floor(totalHours / 8);
|
||||||
const remainingHours = totalHours % 8;
|
const remainingHours = totalHours % 8;
|
||||||
|
|
||||||
const parts = [];
|
|
||||||
|
|
||||||
if (days > 0) {
|
|
||||||
parts.push(
|
|
||||||
new Intl.NumberFormat(currentLocale, {
|
|
||||||
style: "unit",
|
|
||||||
unit: "day",
|
|
||||||
unitDisplay: "long",
|
|
||||||
}).format(days),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remainingHours > 0) {
|
|
||||||
parts.push(
|
|
||||||
new Intl.NumberFormat(currentLocale, {
|
|
||||||
style: "unit",
|
|
||||||
unit: "hour",
|
|
||||||
unitDisplay: "long",
|
|
||||||
}).format(remainingHours),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parts.join(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// For less than 8 hours, use hour and minute format
|
|
||||||
const parts = [];
|
const parts = [];
|
||||||
|
|
||||||
if (totalHours > 0) {
|
if (days > 0) {
|
||||||
parts.push(
|
parts.push(
|
||||||
new Intl.NumberFormat(currentLocale, {
|
new Intl.NumberFormat(currentLocale, {
|
||||||
style: "unit",
|
style: "unit",
|
||||||
unit: "hour",
|
unit: "day",
|
||||||
unitDisplay: "long",
|
unitDisplay: "long",
|
||||||
}).format(totalHours),
|
}).format(days),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remainingMinutes > 0) {
|
if (remainingHours > 0) {
|
||||||
parts.push(
|
parts.push(
|
||||||
new Intl.NumberFormat(currentLocale, {
|
new Intl.NumberFormat(currentLocale, {
|
||||||
style: "unit",
|
style: "unit",
|
||||||
unit: "minute",
|
unit: "hour",
|
||||||
unitDisplay: "long",
|
unitDisplay: "long",
|
||||||
}).format(remainingMinutes),
|
}).format(remainingHours),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(parts);
|
|
||||||
console.log(parts.join(" "));
|
|
||||||
|
|
||||||
return parts.join(" ");
|
return parts.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// For less than 8 hours, use hour and minute format
|
||||||
|
const parts = [];
|
||||||
|
|
||||||
|
if (totalHours > 0) {
|
||||||
|
parts.push(
|
||||||
|
new Intl.NumberFormat(currentLocale, {
|
||||||
|
style: "unit",
|
||||||
|
unit: "hour",
|
||||||
|
unitDisplay: "long",
|
||||||
|
}).format(totalHours),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainingMinutes > 0) {
|
||||||
|
parts.push(
|
||||||
|
new Intl.NumberFormat(currentLocale, {
|
||||||
|
style: "unit",
|
||||||
|
unit: "minute",
|
||||||
|
unitDisplay: "long",
|
||||||
|
}).format(remainingMinutes),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(parts);
|
||||||
|
console.log(parts.join(" "));
|
||||||
|
|
||||||
|
return parts.join(" ");
|
||||||
};
|
};
|
||||||
|
|
||||||
const timeSpentChoices = computed(() => {
|
const timeSpentChoices = computed(() => {
|
||||||
const locale = "fr";
|
const locale = "fr";
|
||||||
return timeSpentValues.map((value) => ({
|
return timeSpentValues.map((value) => ({
|
||||||
text: formatDuration(value, locale),
|
text: formatDuration(value, locale),
|
||||||
value: parseInt(value),
|
value: parseInt(value),
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
const startDate = computed({
|
const startDate = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.evaluation.startDate;
|
return props.evaluation.startDate;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
store.commit("setEvaluationStartDate", {
|
store.commit("setEvaluationStartDate", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
date: v,
|
date: v,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const endDate = computed({
|
const endDate = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.evaluation.endDate;
|
return props.evaluation.endDate;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
store.commit("setEvaluationEndDate", {
|
store.commit("setEvaluationEndDate", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
date: v,
|
date: v,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const maxDate = computed({
|
const maxDate = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.evaluation.maxDate;
|
return props.evaluation.maxDate;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
store.commit("setEvaluationMaxDate", {
|
store.commit("setEvaluationMaxDate", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
date: v,
|
date: v,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const warningInterval = computed({
|
const warningInterval = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.evaluation.warningInterval;
|
return props.evaluation.warningInterval;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
store.commit("setEvaluationWarningInterval", {
|
store.commit("setEvaluationWarningInterval", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
days: v,
|
days: v,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const timeSpent = computed({
|
const timeSpent = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.evaluation.timeSpent;
|
return props.evaluation.timeSpent;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
store.commit("setEvaluationTimeSpent", {
|
store.commit("setEvaluationTimeSpent", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
time: v,
|
time: v,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const comment = computed({
|
const comment = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.evaluation.comment;
|
return props.evaluation.comment;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
store.commit("setEvaluationComment", {
|
store.commit("setEvaluationComment", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
comment: v,
|
comment: v,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const getTemplatesAvailables = computed(() => {
|
const getTemplatesAvailables = computed(() => {
|
||||||
return store.getters.getTemplatesAvailablesForEvaluation(
|
return store.getters.getTemplatesAvailablesForEvaluation(
|
||||||
props.evaluation.evaluation,
|
props.evaluation.evaluation,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// const getAccompanyingPeriod = computed(() => store.work)
|
// const getAccompanyingPeriod = computed(() => store.work)
|
||||||
function updateStartDate(value) {
|
function updateStartDate(value) {
|
||||||
startDate.value = value;
|
startDate.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateEndDate(value) {
|
function updateEndDate(value) {
|
||||||
endDate.value = value;
|
endDate.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateMaxDate(value) {
|
function updateMaxDate(value) {
|
||||||
maxDate.value = value;
|
maxDate.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateWarningInterval(value) {
|
function updateWarningInterval(value) {
|
||||||
warningInterval.value = value;
|
warningInterval.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTimeSpent(value) {
|
function updateTimeSpent(value) {
|
||||||
timeSpent.value = parseInt(value);
|
timeSpent.value = parseInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateComment(value) {
|
function updateComment(value) {
|
||||||
comment.value = value;
|
comment.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onInputDocumentTitle(event) {
|
function onInputDocumentTitle(event) {
|
||||||
const id = Number(event.target.id);
|
const id = Number(event.target.id);
|
||||||
const key = Number(event.target.dataset.key) + 1;
|
const key = Number(event.target.dataset.key) + 1;
|
||||||
const title = event.target.value;
|
const title = event.target.value;
|
||||||
store.commit("updateDocumentTitle", {
|
store.commit("updateDocumentTitle", {
|
||||||
id: id,
|
id: id,
|
||||||
key: key,
|
key: key,
|
||||||
evaluationKey: props.evaluation.key,
|
evaluationKey: props.evaluation.key,
|
||||||
title: title,
|
title: title,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDocument({ stored_object, stored_object_version, file_name }) {
|
function addDocument({ stored_object, stored_object_version, file_name }) {
|
||||||
let document = {
|
let document = {
|
||||||
type: "accompanying_period_work_evaluation_document",
|
type: "accompanying_period_work_evaluation_document",
|
||||||
storedObject: stored_object,
|
storedObject: stored_object,
|
||||||
title: file_name,
|
title: file_name,
|
||||||
};
|
};
|
||||||
store.commit("addDocument", {
|
store.commit("addDocument", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
document,
|
document,
|
||||||
stored_object_version,
|
stored_object_version,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeDocument(document) {
|
function removeDocument(document) {
|
||||||
if (
|
if (
|
||||||
window.confirm(
|
window.confirm(
|
||||||
'Êtes-vous sûr·e de vouloir supprimer le document qui a pour titre "' +
|
'Êtes-vous sûr·e de vouloir supprimer le document qui a pour titre "' +
|
||||||
document.title +
|
document.title +
|
||||||
'" ?',
|
'" ?',
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
store.commit("removeDocument", {
|
store.commit("removeDocument", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
document: document,
|
document: document,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function duplicateDocument(document) {
|
function duplicateDocument(document) {
|
||||||
store.dispatch("duplicateDocument", {
|
store.dispatch("duplicateDocument", {
|
||||||
evaluation_key: props.evaluation.key,
|
evaluation_key: props.evaluation.key,
|
||||||
document: document,
|
document: document,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function duplicateDocumentToEvaluation({ evaluation, document }) {
|
function duplicateDocumentToEvaluation({ evaluation, document }) {
|
||||||
store
|
store
|
||||||
.dispatch("duplicateDocumentToEvaluation", {
|
.dispatch("duplicateDocumentToEvaluation", {
|
||||||
evaluation: evaluation,
|
evaluation: evaluation,
|
||||||
document: document,
|
document: document,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
$toast.open({
|
$toast.open({
|
||||||
message: trans(EVALUATION_DOCUMENT_DUPLICATE_SUCCESS),
|
message: trans(EVALUATION_DOCUMENT_DUPLICATE_SUCCESS),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveDocumentToEvaluation({ evaluationDest, document }) {
|
function moveDocumentToEvaluation({ evaluationDest, document }) {
|
||||||
console.log("dest eval in formEvaluation", evaluationDest);
|
console.log("dest eval in formEvaluation", evaluationDest);
|
||||||
store
|
store
|
||||||
.dispatch("moveDocumentToEvaluation", {
|
.dispatch("moveDocumentToEvaluation", {
|
||||||
evaluationInitial: props.evaluation,
|
evaluationInitial: props.evaluation,
|
||||||
evaluationDest: evaluationDest,
|
evaluationDest: evaluationDest,
|
||||||
document: document,
|
document: document,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
$toast.open({
|
$toast.open({
|
||||||
message: trans(EVALUATION_DOCUMENT_MOVE_SUCCESS),
|
message: trans(EVALUATION_DOCUMENT_MOVE_SUCCESS),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStatusDocumentChanged(newStatus) {
|
function onStatusDocumentChanged(newStatus) {
|
||||||
store.commit("statusDocumentChanged", {
|
store.commit("statusDocumentChanged", {
|
||||||
key: props.evaluation.key,
|
key: props.evaluation.key,
|
||||||
newStatus: newStatus,
|
newStatus: newStatus,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToGenerateDocumentNotification(document, tos) {
|
function goToGenerateDocumentNotification(document, tos) {
|
||||||
const callback = (data) => {
|
const callback = (data) => {
|
||||||
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
||||||
(e) => e.key === props.evaluation.key,
|
(e) => e.key === props.evaluation.key,
|
||||||
);
|
);
|
||||||
let updatedDocument = evaluation.documents.find(
|
let updatedDocument = evaluation.documents.find(
|
||||||
(d) => d.key === document.key,
|
(d) => d.key === document.key,
|
||||||
);
|
);
|
||||||
window.location.assign(
|
window.location.assign(
|
||||||
buildLinkCreateNotification(
|
buildLinkCreateNotification(
|
||||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
||||||
updatedDocument.id,
|
updatedDocument.id,
|
||||||
tos === true
|
tos === true ? store.state.work.accompanyingPeriod.user.id : null,
|
||||||
? store.state.work.accompanyingPeriod.user.id
|
window.location.pathname +
|
||||||
: null,
|
window.location.search +
|
||||||
window.location.pathname +
|
window.location.hash,
|
||||||
window.location.search +
|
),
|
||||||
window.location.hash,
|
);
|
||||||
),
|
};
|
||||||
);
|
store.dispatch("submit", callback).catch((e) => {
|
||||||
};
|
console.log(e);
|
||||||
store.dispatch("submit", callback).catch((e) => {
|
throw e;
|
||||||
console.log(e);
|
});
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
input.document-title {
|
input.document-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-blink {
|
.bg-blink {
|
||||||
color: #050000;
|
color: #050000;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
animation: blinkingBackground 2.2s infinite;
|
animation: blinkingBackground 2.2s infinite;
|
||||||
animation-iteration-count: 2;
|
animation-iteration-count: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes blinkingBackground {
|
@keyframes blinkingBackground {
|
||||||
0% {
|
0% {
|
||||||
background-color: #ed776d;
|
background-color: #ed776d;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
background-color: #ed776d;
|
background-color: #ed776d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
|
||||||
{{ trans(EVALUATION_TIME_SPENT) }}
|
{{ trans(EVALUATION_TIME_SPENT) }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
|
||||||
<select
|
<select
|
||||||
class="form-control form-control-sm"
|
class="form-control form-control-sm"
|
||||||
:value="timeSpent"
|
:value="timeSpent"
|
||||||
@input="$emit('update:timeSpent', $event.target.value)"
|
@input="$emit('update:timeSpent', $event.target.value)"
|
||||||
>
|
>
|
||||||
<option disabled value="">
|
<option disabled value="">
|
||||||
{{ trans(EVALUATION_TIME_SPENT) }}
|
{{ trans(EVALUATION_TIME_SPENT) }}
|
||||||
</option>
|
</option>
|
||||||
<option
|
<option
|
||||||
v-for="time in timeSpentChoices"
|
v-for="time in timeSpentChoices"
|
||||||
:value="time.value"
|
:value="time.value"
|
||||||
:key="time.value"
|
:key="time.value"
|
||||||
>
|
>
|
||||||
{{ time.text }}
|
{{ time.text }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
import {Center, Civility, Gender, SetCenter} from "ChillMainAssets/types";
|
import { Center, Civility, Gender, SetCenter } from "ChillMainAssets/types";
|
||||||
import {
|
import {
|
||||||
AltName,
|
AltName,
|
||||||
Person, PersonIdentifier,
|
Person,
|
||||||
|
PersonIdentifier,
|
||||||
PersonIdentifierWorker,
|
PersonIdentifierWorker,
|
||||||
PersonWrite,
|
PersonWrite,
|
||||||
} from "ChillPersonAssets/types";
|
} from "ChillPersonAssets/types";
|
||||||
@@ -26,21 +27,43 @@ export const personToWritePerson = (person: Person): PersonWrite => {
|
|||||||
type: "person",
|
type: "person",
|
||||||
firstName: person.firstName,
|
firstName: person.firstName,
|
||||||
lastName: person.lastName,
|
lastName: person.lastName,
|
||||||
altNames: person.altNames.map((altName) => ({key: altName.key, value: altName.label})),
|
altNames: person.altNames.map((altName) => ({
|
||||||
|
key: altName.key,
|
||||||
|
value: altName.label,
|
||||||
|
})),
|
||||||
addressId: null,
|
addressId: null,
|
||||||
birthdate: null === person.birthdate ? null : {datetime: person.birthdate.datetime8601},
|
birthdate:
|
||||||
deathdate: null === person.deathdate ? null : {datetime: person.deathdate.datetime8601},
|
null === person.birthdate
|
||||||
|
? null
|
||||||
|
: { datetime: person.birthdate.datetime8601 },
|
||||||
|
deathdate:
|
||||||
|
null === person.deathdate
|
||||||
|
? null
|
||||||
|
: { datetime: person.deathdate.datetime8601 },
|
||||||
phonenumber: person.phonenumber,
|
phonenumber: person.phonenumber,
|
||||||
mobilenumber: person.mobilenumber,
|
mobilenumber: person.mobilenumber,
|
||||||
center: null === person.centers ? null : person.centers
|
center:
|
||||||
.map((center): SetCenter => ({id: center.id, type: "center"}))
|
null === person.centers
|
||||||
.find(() => true) || null,
|
? null
|
||||||
|
: person.centers
|
||||||
|
.map((center): SetCenter => ({ id: center.id, type: "center" }))
|
||||||
|
.find(() => true) || null,
|
||||||
email: person.email,
|
email: person.email,
|
||||||
civility: null === person.civility ? null : {id: person.civility.id, type: "chill_main_civility"},
|
civility:
|
||||||
gender: null === person.gender ? null : {id: person.gender.id, type: "chill_main_gender"},
|
null === person.civility
|
||||||
identifiers: person.identifiers.map((identifier: PersonIdentifier) => ({type: "person_identifier", definition_id: identifier.definition.id, value: identifier.value})),
|
? null
|
||||||
}
|
: { id: person.civility.id, type: "chill_main_civility" },
|
||||||
}
|
gender:
|
||||||
|
null === person.gender
|
||||||
|
? null
|
||||||
|
: { id: person.gender.id, type: "chill_main_gender" },
|
||||||
|
identifiers: person.identifiers.map((identifier: PersonIdentifier) => ({
|
||||||
|
type: "person_identifier",
|
||||||
|
definition_id: identifier.definition.id,
|
||||||
|
value: identifier.value,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const getPersonAltNames = async (): Promise<AltName[]> =>
|
export const getPersonAltNames = async (): Promise<AltName[]> =>
|
||||||
fetch("/api/1.0/person/config/alt_names.json").then((response) => {
|
fetch("/api/1.0/person/config/alt_names.json").then((response) => {
|
||||||
@@ -65,10 +88,12 @@ export const getPersonIdentifiers = async (): Promise<
|
|||||||
PersonIdentifierWorker[]
|
PersonIdentifierWorker[]
|
||||||
> => fetchResults("/api/1.0/person/identifiers/workers");
|
> => fetchResults("/api/1.0/person/identifiers/workers");
|
||||||
|
|
||||||
export interface WritePersonViolationMap
|
export interface WritePersonViolationMap extends Record<
|
||||||
extends Record<string, Record<string, string>> {
|
string,
|
||||||
|
Record<string, string>
|
||||||
|
> {
|
||||||
firstName: {
|
firstName: {
|
||||||
"{{ value }}": string
|
"{{ value }}": string;
|
||||||
};
|
};
|
||||||
lastName: {
|
lastName: {
|
||||||
"{{ value }}": string;
|
"{{ value }}": string;
|
||||||
@@ -96,7 +121,7 @@ export interface WritePersonViolationMap
|
|||||||
birthdate: {};
|
birthdate: {};
|
||||||
identifiers: {
|
identifiers: {
|
||||||
"{{ value }}": string;
|
"{{ value }}": string;
|
||||||
"definition_id": string;
|
definition_id: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export const createPerson = async (person: PersonWrite): Promise<Person> => {
|
export const createPerson = async (person: PersonWrite): Promise<Person> => {
|
||||||
@@ -107,10 +132,13 @@ export const createPerson = async (person: PersonWrite): Promise<Person> => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editPerson = async (person: PersonWrite, personId: number): Promise<Person> => {
|
export const editPerson = async (
|
||||||
|
person: PersonWrite,
|
||||||
|
personId: number,
|
||||||
|
): Promise<Person> => {
|
||||||
return makeFetch<PersonWrite, Person, WritePersonViolationMap>(
|
return makeFetch<PersonWrite, Person, WritePersonViolationMap>(
|
||||||
"PATCH",
|
"PATCH",
|
||||||
`/api/1.0/person/person/${personId}.json`,
|
`/api/1.0/person/person/${personId}.json`,
|
||||||
person,
|
person,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -11,21 +11,21 @@ export const duplicate = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const duplicateDocumentToEvaluation = async (
|
export const duplicateDocumentToEvaluation = async (
|
||||||
document_id: number,
|
document_id: number,
|
||||||
evaluation_id: number,
|
evaluation_id: number,
|
||||||
): Promise<AccompanyingPeriodWorkEvaluationDocument> => {
|
): Promise<AccompanyingPeriodWorkEvaluationDocument> => {
|
||||||
return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>(
|
return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>(
|
||||||
"POST",
|
"POST",
|
||||||
`/api/1.0/person/accompanying-course-work-evaluation-document/${document_id}/evaluation/${evaluation_id}/duplicate`,
|
`/api/1.0/person/accompanying-course-work-evaluation-document/${document_id}/evaluation/${evaluation_id}/duplicate`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const moveDocumentToEvaluation = async (
|
export const moveDocumentToEvaluation = async (
|
||||||
document_id: number,
|
document_id: number,
|
||||||
evaluation_id: number,
|
evaluation_id: number,
|
||||||
): Promise<AccompanyingPeriodWorkEvaluationDocument> => {
|
): Promise<AccompanyingPeriodWorkEvaluationDocument> => {
|
||||||
return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>(
|
return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>(
|
||||||
"POST",
|
"POST",
|
||||||
`/api/1.0/person/accompanying-course-work-evaluation-document/${document_id}/evaluation/${evaluation_id}/move`,
|
`/api/1.0/person/accompanying-course-work-evaluation-document/${document_id}/evaluation/${evaluation_id}/move`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,53 +1,47 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="item-bloc">
|
<div class="item-bloc">
|
||||||
<div class="item-row">
|
<div class="item-row">
|
||||||
<h2 class="badge-title">
|
<h2 class="badge-title">
|
||||||
<span class="title_label"></span>
|
<span class="title_label"></span>
|
||||||
<span class="title_action">
|
<span class="title_action">
|
||||||
<span>
|
<span>
|
||||||
{{ trans(EVALUATION) }}:
|
{{ trans(EVALUATION) }}:
|
||||||
<span class="badge bg-light text-dark">
|
<span class="badge bg-light text-dark">
|
||||||
{{ eval?.evaluation?.title.fr }}
|
{{ eval?.evaluation?.title.fr }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<ul class="small_in_title columns mt-1">
|
<ul class="small_in_title columns mt-1">
|
||||||
<li>
|
<li>
|
||||||
<span class="item-key">
|
<span class="item-key">
|
||||||
{{
|
{{ trans(ACCOMPANYING_COURSE_WORK_START_DATE) }}
|
||||||
trans(
|
:
|
||||||
ACCOMPANYING_COURSE_WORK_START_DATE,
|
</span>
|
||||||
)
|
<b>{{ formatDate(eval.startDate) }}</b>
|
||||||
}}
|
</li>
|
||||||
:
|
|
||||||
</span>
|
|
||||||
<b>{{ formatDate(eval.startDate) }}</b>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li v-if="eval.endDate">
|
<li v-if="eval.endDate">
|
||||||
<span class="item-key">
|
<span class="item-key">
|
||||||
{{
|
{{ trans(ACCOMPANYING_COURSE_WORK_END_DATE) }}
|
||||||
trans(ACCOMPANYING_COURSE_WORK_END_DATE)
|
:
|
||||||
}}
|
</span>
|
||||||
:
|
<b>{{ formatDate(eval.endDate) }}</b>
|
||||||
</span>
|
</li>
|
||||||
<b>{{ formatDate(eval.endDate) }}</b>
|
</ul>
|
||||||
</li>
|
</span>
|
||||||
</ul>
|
</h2>
|
||||||
</span>
|
</div>
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
ACCOMPANYING_COURSE_WORK_END_DATE,
|
ACCOMPANYING_COURSE_WORK_END_DATE,
|
||||||
ACCOMPANYING_COURSE_WORK_START_DATE,
|
ACCOMPANYING_COURSE_WORK_START_DATE,
|
||||||
EVALUATION,
|
EVALUATION,
|
||||||
trans,
|
trans,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import { ISOToDate } from "ChillMainAssets/chill/js/date";
|
import { ISOToDate } from "ChillMainAssets/chill/js/date";
|
||||||
import { DateTime } from "ChillMainAssets/types";
|
import { DateTime } from "ChillMainAssets/types";
|
||||||
@@ -56,15 +50,15 @@ import { AccompanyingPeriodWorkEvaluation } from "../../../types";
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const props = defineProps<{ eval: AccompanyingPeriodWorkEvaluation }>();
|
const props = defineProps<{ eval: AccompanyingPeriodWorkEvaluation }>();
|
||||||
const formatDate = (dateObject: DateTime) => {
|
const formatDate = (dateObject: DateTime) => {
|
||||||
if (dateObject) {
|
if (dateObject) {
|
||||||
const parsedDate = ISOToDate(dateObject.datetime);
|
const parsedDate = ISOToDate(dateObject.datetime);
|
||||||
if (parsedDate) {
|
if (parsedDate) {
|
||||||
return new Intl.DateTimeFormat("default", {
|
return new Intl.DateTimeFormat("default", {
|
||||||
dateStyle: "short",
|
dateStyle: "short",
|
||||||
}).format(parsedDate);
|
}).format(parsedDate);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="results">
|
<div class="results">
|
||||||
<div
|
<div
|
||||||
v-for="evaluation in evaluations"
|
v-for="evaluation in evaluations"
|
||||||
:key="evaluation.id"
|
:key="evaluation.id"
|
||||||
class="list-item"
|
class="list-item"
|
||||||
>
|
>
|
||||||
<label class="acpw-item">
|
<label class="acpw-item">
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
:value="evaluation"
|
:value="evaluation"
|
||||||
v-model="selectedEvaluation"
|
v-model="selectedEvaluation"
|
||||||
name="item"
|
name="item"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<accompanying-period-work-evaluation-item :eval="evaluation" />
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<accompanying-period-work-evaluation-item :eval="evaluation" />
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -28,7 +28,7 @@ import AccompanyingPeriodWorkEvaluationItem from "ChillPersonAssets/vuejs/_compo
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
evaluations: AccompanyingPeriodWorkEvaluation[];
|
evaluations: AccompanyingPeriodWorkEvaluation[];
|
||||||
}>();
|
}>();
|
||||||
const selectedEvaluation = ref<AccompanyingPeriodWorkEvaluation | null>(null);
|
const selectedEvaluation = ref<AccompanyingPeriodWorkEvaluation | null>(null);
|
||||||
|
|
||||||
@@ -36,12 +36,12 @@ const selectedEvaluation = ref<AccompanyingPeriodWorkEvaluation | null>(null);
|
|||||||
const emit = defineEmits();
|
const emit = defineEmits();
|
||||||
|
|
||||||
watch(selectedEvaluation, (newValue) => {
|
watch(selectedEvaluation, (newValue) => {
|
||||||
emit("update:selectedEvaluation", newValue);
|
emit("update:selectedEvaluation", newValue);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.acpw-item {
|
.acpw-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -27,22 +27,22 @@ import { AccompanyingPeriodWork } from "../../../types";
|
|||||||
import { defineProps, ref, watch } from "vue";
|
import { defineProps, ref, watch } from "vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
accompanyingPeriodWorks: AccompanyingPeriodWork[];
|
accompanyingPeriodWorks: AccompanyingPeriodWork[];
|
||||||
selectedAcpw?: AccompanyingPeriodWork | null;
|
selectedAcpw?: AccompanyingPeriodWork | null;
|
||||||
}>();
|
}>();
|
||||||
const selectedAcpw = ref<AccompanyingPeriodWork | null>(
|
const selectedAcpw = ref<AccompanyingPeriodWork | null>(
|
||||||
props.selectedAcpw ?? null,
|
props.selectedAcpw ?? null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
"update:selectedAcpw": [value: AccompanyingPeriodWork | null];
|
"update:selectedAcpw": [value: AccompanyingPeriodWork | null];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.selectedAcpw,
|
() => props.selectedAcpw,
|
||||||
(val) => {
|
(val) => {
|
||||||
selectedAcpw.value = val ?? null;
|
selectedAcpw.value = val ?? null;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(selectedAcpw, (newValue) => {
|
watch(selectedAcpw, (newValue) => {
|
||||||
|
|||||||
@@ -20,26 +20,28 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<teleport to="body">
|
<teleport to="body">
|
||||||
<modal
|
<modal
|
||||||
v-if="showModal"
|
v-if="showModal"
|
||||||
@close="closeModal"
|
@close="closeModal"
|
||||||
modal-dialog-class="modal-dialog-scrollable modal-xl"
|
modal-dialog-class="modal-dialog-scrollable modal-xl"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3>
|
<h3>
|
||||||
{{ getModalTitle() }}
|
{{ getModalTitle() }}
|
||||||
</h3>
|
</h3>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #body>
|
<template #body>
|
||||||
<accompanying-period-work-list
|
<accompanying-period-work-list
|
||||||
v-if="evaluations.length === 0":accompanying-period-works="accompanyingPeriodWorks"
|
v-if="evaluations.length === 0"
|
||||||
v-model:selectedAcpw="selectedAcpw"/>
|
:accompanying-period-works="accompanyingPeriodWorks"
|
||||||
<accompanying-period-work-evaluation-list
|
v-model:selectedAcpw="selectedAcpw"
|
||||||
v-if="evaluations.length > 0"
|
/>
|
||||||
:evaluations="evaluations"
|
<accompanying-period-work-evaluation-list
|
||||||
v-model:selectedEvaluation="selectedEvaluation"
|
v-if="evaluations.length > 0"
|
||||||
|
:evaluations="evaluations"
|
||||||
|
v-model:selectedEvaluation="selectedEvaluation"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -59,13 +61,14 @@ import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
|||||||
import AccompanyingPeriodWorkList from "./AccompanyingPeriodWorkList.vue";
|
import AccompanyingPeriodWorkList from "./AccompanyingPeriodWorkList.vue";
|
||||||
import { AccompanyingPeriodWork } from "../../../types";
|
import { AccompanyingPeriodWork } from "../../../types";
|
||||||
import {
|
import {
|
||||||
trans,ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK,
|
trans,
|
||||||
ACPW_DUPLICATE_SELECT_AN_EVALUATION,CONFIRM,
|
ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK,
|
||||||
|
ACPW_DUPLICATE_SELECT_AN_EVALUATION,
|
||||||
|
CONFIRM,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods";
|
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
import AccompanyingPeriodWorkEvaluationList from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkEvaluationList.vue";
|
import AccompanyingPeriodWorkEvaluationList from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkEvaluationList.vue";
|
||||||
import { AccompanyingPeriodWorkEvaluation } from "../../../types";
|
import { AccompanyingPeriodWorkEvaluation } from "../../../types";
|
||||||
|
|
||||||
const selectedAcpw = ref<AccompanyingPeriodWork | null>(null);
|
const selectedAcpw = ref<AccompanyingPeriodWork | null>(null);
|
||||||
const selectedEvaluation = ref<AccompanyingPeriodWorkEvaluation | null>(null);
|
const selectedEvaluation = ref<AccompanyingPeriodWorkEvaluation | null>(null);
|
||||||
@@ -74,21 +77,21 @@ const accompanyingPeriodWorks = ref<AccompanyingPeriodWork[]>([]);
|
|||||||
const evaluations = ref<AccompanyingPeriodWorkEvaluation[]>([]);
|
const evaluations = ref<AccompanyingPeriodWorkEvaluation[]>([]);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
accompanyingPeriodId: string;
|
accompanyingPeriodId: string;
|
||||||
isEvaluationSelector: boolean;
|
isEvaluationSelector: boolean;
|
||||||
ignoreAccompanyingPeriodWorkIds: number[];
|
ignoreAccompanyingPeriodWorkIds: number[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
pickWork: [payload: { work: AccompanyingPeriodWork | null }];
|
pickWork: [payload: { work: AccompanyingPeriodWork | null }];
|
||||||
closeModal: [];
|
closeModal: [];
|
||||||
"update:selectedEvaluation": [evaluation: AccompanyingPeriodWorkEvaluation];
|
"update:selectedEvaluation": [evaluation: AccompanyingPeriodWorkEvaluation];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const getModalTitle = () =>
|
const getModalTitle = () =>
|
||||||
evaluations.value.length > 0
|
evaluations.value.length > 0
|
||||||
? trans(ACPW_DUPLICATE_SELECT_AN_EVALUATION)
|
? trans(ACPW_DUPLICATE_SELECT_AN_EVALUATION)
|
||||||
: trans(ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK);
|
: trans(ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.accompanyingPeriodId) {
|
if (props.accompanyingPeriodId) {
|
||||||
@@ -97,70 +100,70 @@ onMounted(() => {
|
|||||||
console.error("No accompanyingperiod id was given");
|
console.error("No accompanyingperiod id was given");
|
||||||
}
|
}
|
||||||
|
|
||||||
showModal.value = true;
|
showModal.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const getAccompanyingPeriodWorks = async (periodId: number) => {
|
const getAccompanyingPeriodWorks = async (periodId: number) => {
|
||||||
const url = `/api/1.0/person/accompanying-course/${periodId}/works.json`;
|
const url = `/api/1.0/person/accompanying-course/${periodId}/works.json`;
|
||||||
|
|
||||||
const accompanyingPeriodWorksFetched =
|
const accompanyingPeriodWorksFetched =
|
||||||
await fetchResults<AccompanyingPeriodWork>(url);
|
await fetchResults<AccompanyingPeriodWork>(url);
|
||||||
if (props.isEvaluationSelector) {
|
if (props.isEvaluationSelector) {
|
||||||
accompanyingPeriodWorks.value = accompanyingPeriodWorksFetched.filter(
|
accompanyingPeriodWorks.value = accompanyingPeriodWorksFetched.filter(
|
||||||
(acpw: AccompanyingPeriodWork) =>
|
(acpw: AccompanyingPeriodWork) =>
|
||||||
acpw.accompanyingPeriodWorkEvaluations.length > 0 &&
|
acpw.accompanyingPeriodWorkEvaluations.length > 0 &&
|
||||||
typeof acpw.id !== "undefined" &&
|
typeof acpw.id !== "undefined" &&
|
||||||
!props.ignoreAccompanyingPeriodWorkIds.includes(acpw.id),
|
!props.ignoreAccompanyingPeriodWorkIds.includes(acpw.id),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
accompanyingPeriodWorks.value = accompanyingPeriodWorksFetched;
|
accompanyingPeriodWorks.value = accompanyingPeriodWorksFetched;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(selectedAcpw, (newValue) => {
|
watch(selectedAcpw, (newValue) => {
|
||||||
const inputField = document.getElementById(
|
const inputField = document.getElementById(
|
||||||
"find_accompanying_period_work_acpw",
|
"find_accompanying_period_work_acpw",
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
if (inputField) {
|
if (inputField) {
|
||||||
inputField.value = String(newValue?.id || "");
|
inputField.value = String(newValue?.id || "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (!props.isEvaluationSelector) {
|
/* if (!props.isEvaluationSelector) {
|
||||||
console.log("Emitting from watch:", { work: newValue });
|
console.log("Emitting from watch:", { work: newValue });
|
||||||
emit("pickWork", { work: newValue });
|
emit("pickWork", { work: newValue });
|
||||||
}*/
|
}*/
|
||||||
});
|
});
|
||||||
|
|
||||||
const openModal = () => {
|
const openModal = () => {
|
||||||
showModal.value = true;
|
showModal.value = true;
|
||||||
};
|
};
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
showModal.value = false;
|
showModal.value = false;
|
||||||
selectedEvaluation.value = null;
|
selectedEvaluation.value = null;
|
||||||
// selectedAcpw.value = null;
|
// selectedAcpw.value = null;
|
||||||
emit("closeModal");
|
emit("closeModal");
|
||||||
};
|
};
|
||||||
const confirmSelection = () => {
|
const confirmSelection = () => {
|
||||||
selectedAcpw.value = selectedAcpw.value;
|
selectedAcpw.value = selectedAcpw.value;
|
||||||
console.log("selectedAcpw", selectedAcpw.value);
|
console.log("selectedAcpw", selectedAcpw.value);
|
||||||
|
|
||||||
if (!props.isEvaluationSelector) {
|
if (!props.isEvaluationSelector) {
|
||||||
if (selectedAcpw.value) {
|
if (selectedAcpw.value) {
|
||||||
// only emit if something is actually selected!emit("pickWork", { work: selectedAcpw.value });
|
// only emit if something is actually selected!emit("pickWork", { work: selectedAcpw.value });
|
||||||
closeModal();}
|
closeModal();
|
||||||
// optionally show some error or warning if not selected
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
// optionally show some error or warning if not selected
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedAcpw.value && props.isEvaluationSelector) {
|
if (selectedAcpw.value && props.isEvaluationSelector) {
|
||||||
evaluations.value =
|
evaluations.value = selectedAcpw.value.accompanyingPeriodWorkEvaluations;
|
||||||
selectedAcpw.value.accompanyingPeriodWorkEvaluations;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedEvaluation.value && props.isEvaluationSelector) {
|
if (selectedEvaluation.value && props.isEvaluationSelector) {
|
||||||
// console.log('evaluation log in modal', selectedEvaluation.value)
|
// console.log('evaluation log in modal', selectedEvaluation.value)
|
||||||
emit("update:selectedEvaluation", selectedEvaluation.value);
|
emit("update:selectedEvaluation", selectedEvaluation.value);
|
||||||
closeModal();
|
closeModal();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -25,7 +25,11 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<CreateModal
|
<CreateModal
|
||||||
v-if="creatableEntityTypes.length > 0 && showModalCreate && null == thirdPartyParentAddContact"
|
v-if="
|
||||||
|
creatableEntityTypes.length > 0 &&
|
||||||
|
showModalCreate &&
|
||||||
|
null == thirdPartyParentAddContact
|
||||||
|
"
|
||||||
action="create"
|
action="create"
|
||||||
:allowed-types="creatableEntityTypes"
|
:allowed-types="creatableEntityTypes"
|
||||||
:query="query"
|
:query="query"
|
||||||
@@ -50,7 +54,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, nextTick, useTemplateRef} from "vue";
|
import { ref, computed, nextTick, useTemplateRef } from "vue";
|
||||||
import PersonChooseModal from "./AddPersons/PersonChooseModal.vue";
|
import PersonChooseModal from "./AddPersons/PersonChooseModal.vue";
|
||||||
import type {
|
import type {
|
||||||
Suggestion,
|
Suggestion,
|
||||||
@@ -62,7 +66,10 @@ import type {
|
|||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import options = marked.options;
|
import options = marked.options;
|
||||||
import CreateModal from "ChillMainAssets/vuejs/OnTheFly/components/CreateModal.vue";
|
import CreateModal from "ChillMainAssets/vuejs/OnTheFly/components/CreateModal.vue";
|
||||||
import {Thirdparty, ThirdpartyCompany} from "../../../../../ChillThirdPartyBundle/Resources/public/types";
|
import {
|
||||||
|
Thirdparty,
|
||||||
|
ThirdpartyCompany,
|
||||||
|
} from "../../../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
|
|
||||||
interface AddPersonsConfig {
|
interface AddPersonsConfig {
|
||||||
suggested?: Suggestion[];
|
suggested?: Suggestion[];
|
||||||
@@ -80,13 +87,13 @@ const props = withDefaults(defineProps<AddPersonsConfig>(), {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const emit =
|
const emit =
|
||||||
defineEmits<{
|
defineEmits<
|
||||||
(e: "addNewPersons", payload: { selected: Suggestion[] }): void;
|
(e: "addNewPersons", payload: { selected: Suggestion[] }) => void
|
||||||
}
|
|
||||||
>();
|
>();
|
||||||
|
|
||||||
type PersonChooseModalType = InstanceType<typeof PersonChooseModal>;
|
type PersonChooseModalType = InstanceType<typeof PersonChooseModal>;
|
||||||
const personChooseModal = useTemplateRef<PersonChooseModalType>('personChooseModal');
|
const personChooseModal =
|
||||||
|
useTemplateRef<PersonChooseModalType>("personChooseModal");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to show/hide the modal "choose".
|
* Flag to show/hide the modal "choose".
|
||||||
@@ -106,7 +113,7 @@ const query = ref("");
|
|||||||
/**
|
/**
|
||||||
* Temporarily store the thirdparty company when calling "addContact"
|
* Temporarily store the thirdparty company when calling "addContact"
|
||||||
*/
|
*/
|
||||||
const thirdPartyParentAddContact = ref<ThirdpartyCompany|null>(null);
|
const thirdPartyParentAddContact = ref<ThirdpartyCompany | null>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the selected elements.
|
* Contains the selected elements.
|
||||||
@@ -156,7 +163,7 @@ function closeModalChoose(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeModalCreate(): void {
|
function closeModalCreate(): void {
|
||||||
if (null !== thirdPartyParentAddContact) {
|
if (null !== thirdPartyParentAddContact.value) {
|
||||||
thirdPartyParentAddContact.value = null;
|
thirdPartyParentAddContact.value = null;
|
||||||
}
|
}
|
||||||
showModalCreate.value = false;
|
showModalCreate.value = false;
|
||||||
@@ -165,7 +172,10 @@ function closeModalCreate(): void {
|
|||||||
/**
|
/**
|
||||||
* Called by PersonSuggestion's updateSelection event, when an element is checked/unchecked
|
* Called by PersonSuggestion's updateSelection event, when an element is checked/unchecked
|
||||||
*/
|
*/
|
||||||
function updateSelected(payload: {suggestion: Suggestion, isSelected: boolean}): void {
|
function updateSelected(payload: {
|
||||||
|
suggestion: Suggestion;
|
||||||
|
isSelected: boolean;
|
||||||
|
}): void {
|
||||||
if (payload.isSelected) {
|
if (payload.isSelected) {
|
||||||
addSuggestionToSelected(payload.suggestion);
|
addSuggestionToSelected(payload.suggestion);
|
||||||
} else {
|
} else {
|
||||||
@@ -194,7 +204,7 @@ function onPickEntities(): void {
|
|||||||
closeModalChoose();
|
closeModalChoose();
|
||||||
}
|
}
|
||||||
|
|
||||||
function triggerAddContact({parent}: {parent: ThirdpartyCompany}): void {
|
function triggerAddContact({ parent }: { parent: ThirdpartyCompany }): void {
|
||||||
closeModalChoose();
|
closeModalChoose();
|
||||||
openModalChoose();
|
openModalChoose();
|
||||||
thirdPartyParentAddContact.value = parent;
|
thirdPartyParentAddContact.value = parent;
|
||||||
@@ -216,7 +226,7 @@ function onPersonCreated(payload: { person: Person }): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onThirdPartyCreated(payload: {thirdParty: Thirdparty}): void {
|
function onThirdPartyCreated(payload: { thirdParty: Thirdparty }): void {
|
||||||
showModalCreate.value = false;
|
showModalCreate.value = false;
|
||||||
const suggestion = {
|
const suggestion = {
|
||||||
result: payload.thirdParty,
|
result: payload.thirdParty,
|
||||||
@@ -236,7 +246,7 @@ function resetSearch(): void {
|
|||||||
personChooseModal.value?.resetSearch();
|
personChooseModal.value?.resetSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({resetSearch})
|
defineExpose({ resetSearch });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -82,7 +82,11 @@
|
|||||||
v-if="props.allowCreate && query.length > 0"
|
v-if="props.allowCreate && query.length > 0"
|
||||||
class="create-button"
|
class="create-button"
|
||||||
>
|
>
|
||||||
<button type="button" class="btn btn-submit" @click="emit('onAskForCreate', { query })">
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-submit"
|
||||||
|
@click="emit('onAskForCreate', { query })"
|
||||||
|
>
|
||||||
{{ trans(ONTHEFLY_CREATE_BUTTON, { q: query }) }}
|
{{ trans(ONTHEFLY_CREATE_BUTTON, { q: query }) }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -125,7 +129,7 @@ import type {
|
|||||||
SearchOptions,
|
SearchOptions,
|
||||||
Entities,
|
Entities,
|
||||||
} from "ChillPersonAssets/types";
|
} from "ChillPersonAssets/types";
|
||||||
import {ThirdpartyCompany} from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
import { ThirdpartyCompany } from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modalTitle: string;
|
modalTitle: string;
|
||||||
@@ -147,7 +151,10 @@ const emit = defineEmits<{
|
|||||||
(e: "onPickEntities"): void;
|
(e: "onPickEntities"): void;
|
||||||
(e: "onAskForCreate", payload: { query: string }): void;
|
(e: "onAskForCreate", payload: { query: string }): void;
|
||||||
(e: "triggerAddContact", payload: { parent: ThirdpartyCompany }): void;
|
(e: "triggerAddContact", payload: { parent: ThirdpartyCompany }): void;
|
||||||
(e: "updateSelected", payload: {suggestion: Suggestion, isSelected: boolean}): void;
|
(
|
||||||
|
e: "updateSelected",
|
||||||
|
payload: { suggestion: Suggestion; isSelected: boolean },
|
||||||
|
): void;
|
||||||
(e: "cleanSelected"): void;
|
(e: "cleanSelected"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
@@ -181,27 +188,32 @@ const queryLength = computed(() => search.query.length);
|
|||||||
const suggestedCounter = computed(() => suggested.value.length);
|
const suggestedCounter = computed(() => suggested.value.length);
|
||||||
const selectedCounter = computed(() => props.selected.size);
|
const selectedCounter = computed(() => props.selected.size);
|
||||||
|
|
||||||
const checkUniq = computed(() =>
|
const checkUniq = computed(() => (props.options.uniq ? "radio" : "checkbox"));
|
||||||
props.options.uniq ? "radio" : "checkbox",
|
|
||||||
|
const selectedAndSuggested = computed<(Suggestion & { isSelected: boolean })[]>(
|
||||||
|
() => {
|
||||||
|
const selectedAndSuggested = [];
|
||||||
|
|
||||||
|
// add selected that are not in the search results
|
||||||
|
for (const selected of props.selected.values()) {
|
||||||
|
if (!suggested.value.some((s: Suggestion) => s.key === selected.key)) {
|
||||||
|
selectedAndSuggested.push({ ...selected, isSelected: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const suggestion of suggested.value) {
|
||||||
|
selectedAndSuggested.push({
|
||||||
|
...suggestion,
|
||||||
|
isSelected: props.selected.has(suggestion.key),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedAndSuggested;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedAndSuggested = computed<(Suggestion & {isSelected: boolean})[]>(() => {
|
const hasNoResult = computed(
|
||||||
const selectedAndSuggested = [];
|
() => search.hasPreviousQuery && suggested.value.length === 0,
|
||||||
|
);
|
||||||
// add selected that are not in the search results
|
|
||||||
for (const selected of props.selected.values()) {
|
|
||||||
if (!suggested.value.some((s: Suggestion) => s.key === selected.key)) {
|
|
||||||
selectedAndSuggested.push({...selected, isSelected: false});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const suggestion of suggested.value) {
|
|
||||||
selectedAndSuggested.push({...suggestion, isSelected: props.selected.has(suggestion.key)})
|
|
||||||
}
|
|
||||||
|
|
||||||
return selectedAndSuggested;
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasNoResult = computed(() => search.hasPreviousQuery && suggested.value.length === 0);
|
|
||||||
|
|
||||||
function setQuery(q: string) {
|
function setQuery(q: string) {
|
||||||
search.query = q;
|
search.query = q;
|
||||||
@@ -240,14 +252,15 @@ function setQuery(q: string) {
|
|||||||
}, delay);
|
}, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadSuggestions(
|
||||||
function loadSuggestions(suggestedArr: {relevance: number, result: Entities}[]): void {
|
suggestedArr: { relevance: number; result: Entities }[],
|
||||||
|
): void {
|
||||||
suggested.value = suggestedArr.map((item) => {
|
suggested.value = suggestedArr.map((item) => {
|
||||||
return {
|
return {
|
||||||
key: item.result.type + item.result.id,
|
key: item.result.type + item.result.id,
|
||||||
relevance: item.relevance,
|
relevance: item.relevance,
|
||||||
result: item.result
|
result: item.result,
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,11 +280,11 @@ function resetSearch() {
|
|||||||
|
|
||||||
function selectAll() {
|
function selectAll() {
|
||||||
suggested.value.forEach((suggestion: Suggestion) => {
|
suggested.value.forEach((suggestion: Suggestion) => {
|
||||||
emit("updateSelected", {suggestion, isSelected: true})
|
emit("updateSelected", { suggestion, isSelected: true });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function triggerAddContact(payload: {parent: ThirdpartyCompany}) {
|
function triggerAddContact(payload: { parent: ThirdpartyCompany }) {
|
||||||
emit("triggerAddContact", payload);
|
emit("triggerAddContact", payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +292,7 @@ function triggerAddContact(payload: {parent: ThirdpartyCompany}) {
|
|||||||
* Triggered when the user clicks on the "add" button.
|
* Triggered when the user clicks on the "add" button.
|
||||||
*/
|
*/
|
||||||
function pickEntities(): void {
|
function pickEntities(): void {
|
||||||
emit("onPickEntities", );
|
emit("onPickEntities");
|
||||||
search.query = "";
|
search.query = "";
|
||||||
emit("close");
|
emit("close");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="list-item" :class="{ checked: props.isSelected }">
|
<div class="list-item" :class="{ checked: props.isSelected }">
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
:type="type"
|
:type="type"
|
||||||
:value="props.item.key"
|
:value="props.item.key"
|
||||||
name="item"
|
name="item"
|
||||||
:id="props.item.key"
|
:id="props.item.key"
|
||||||
:checked="props.isSelected"
|
:checked="props.isSelected"
|
||||||
@click="onUpdateValue"
|
@click="onUpdateValue"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<suggestion-person
|
<suggestion-person
|
||||||
v-if="isSuggestionForPerson(item)"
|
v-if="isSuggestionForPerson(item)"
|
||||||
@@ -53,23 +53,27 @@ import SuggestionUserGroup from "./TypeUserGroup.vue";
|
|||||||
import {
|
import {
|
||||||
isSuggestionForHousehold,
|
isSuggestionForHousehold,
|
||||||
isSuggestionForPerson,
|
isSuggestionForPerson,
|
||||||
isSuggestionForThirdParty, isSuggestionForUser,
|
isSuggestionForThirdParty,
|
||||||
|
isSuggestionForUser,
|
||||||
isSuggestionForUserGroup,
|
isSuggestionForUserGroup,
|
||||||
Suggestion
|
Suggestion,
|
||||||
} from "ChillPersonAssets/types";
|
} from "ChillPersonAssets/types";
|
||||||
import {ThirdpartyCompany} from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
import { ThirdpartyCompany } from "../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
item: Suggestion;
|
item: Suggestion;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
type: "radio"|"checkbox";
|
type: "radio" | "checkbox";
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "updateSelected", payload: {suggestion: Suggestion, isSelected: boolean}): void;
|
(
|
||||||
|
e: "updateSelected",
|
||||||
|
payload: { suggestion: Suggestion; isSelected: boolean },
|
||||||
|
): void;
|
||||||
(e: "triggerAddContact", payload: { parent: ThirdpartyCompany }): void;
|
(e: "triggerAddContact", payload: { parent: ThirdpartyCompany }): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const isChecked = computed<boolean>(() => props.isSelected)
|
const isChecked = computed<boolean>(() => props.isSelected);
|
||||||
|
|
||||||
const onUpdateValue = (event: Event) => {
|
const onUpdateValue = (event: Event) => {
|
||||||
const target = event?.target;
|
const target = event?.target;
|
||||||
@@ -77,10 +81,13 @@ const onUpdateValue = (event: Event) => {
|
|||||||
console.error("the value of checked is not an HTMLInputElement");
|
console.error("the value of checked is not an HTMLInputElement");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit("updateSelected", {suggestion: props.item, isSelected: props.type === "radio" ? true : target.checked});
|
emit("updateSelected", {
|
||||||
}
|
suggestion: props.item,
|
||||||
|
isSelected: props.type === "radio" ? true : target.checked,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function triggerAddContact(payload: {parent: ThirdpartyCompany}) {
|
function triggerAddContact(payload: { parent: ThirdpartyCompany }) {
|
||||||
emit("triggerAddContact", payload);
|
emit("triggerAddContact", payload);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ import { defineProps } from "vue";
|
|||||||
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
||||||
import HouseholdRenderBox from "ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue";
|
import HouseholdRenderBox from "ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue";
|
||||||
import { Suggestion } from "ChillPersonAssets/types";
|
import { Suggestion } from "ChillPersonAssets/types";
|
||||||
import {Household} from "ChillMainAssets/types";
|
import { Household } from "ChillMainAssets/types";
|
||||||
|
|
||||||
interface TypeHouseholdProps {
|
interface TypeHouseholdProps {
|
||||||
item: Suggestion & {result: Household};
|
item: Suggestion & { result: Household };
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<TypeHouseholdProps>();
|
defineProps<TypeHouseholdProps>();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { computed, defineProps } from "vue";
|
|||||||
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
|
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
|
||||||
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
||||||
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
|
||||||
import {Person, Suggestion} from "ChillPersonAssets/types";
|
import { Person, Suggestion } from "ChillPersonAssets/types";
|
||||||
|
|
||||||
function formatDate(dateString: string | undefined, format: string) {
|
function formatDate(dateString: string | undefined, format: string) {
|
||||||
if (!dateString) return "";
|
if (!dateString) return "";
|
||||||
@@ -36,7 +36,7 @@ function formatDate(dateString: string | undefined, format: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
item: Suggestion & { result: Person },
|
item: Suggestion & { result: Person };
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const hasBirthdate = computed(() => props.item.result.birthdate !== null);
|
const hasBirthdate = computed(() => props.item.result.birthdate !== null);
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container tpartycontainer">
|
<div class="container tpartycontainer">
|
||||||
<div class="tparty-identification">
|
<div class="tparty-identification">
|
||||||
<span v-if="(isThirdpartyChild(item.result) || isThirdpartyContact(item.result)) && item.result.profession" class="profession">{{
|
<span
|
||||||
item.result.profession
|
v-if="
|
||||||
}}</span>
|
(isThirdpartyChild(item.result) ||
|
||||||
|
isThirdpartyContact(item.result)) &&
|
||||||
|
item.result.profession
|
||||||
|
"
|
||||||
|
class="profession"
|
||||||
|
>{{ item.result.profession }}</span
|
||||||
|
>
|
||||||
<span class="name"> {{ item.result.text }} </span>
|
<span class="name"> {{ item.result.text }} </span>
|
||||||
<span class="location">
|
<span class="location">
|
||||||
<template v-if="hasAddress">
|
<template v-if="hasAddress">
|
||||||
@@ -12,7 +18,10 @@
|
|||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tpartyparent" v-if="isThirdpartyChild(item.result) && null !== item.result.parent">
|
<div
|
||||||
|
class="tpartyparent"
|
||||||
|
v-if="isThirdpartyChild(item.result) && null !== item.result.parent"
|
||||||
|
>
|
||||||
<span class="name"> > {{ item.result.parent.text }} </span>
|
<span class="name"> > {{ item.result.parent.text }} </span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -22,8 +31,9 @@
|
|||||||
<a
|
<a
|
||||||
v-if="item.result.type === 'thirdparty' && item.result.kind === 'company'"
|
v-if="item.result.type === 'thirdparty' && item.result.kind === 'company'"
|
||||||
class="btn btn-tpchild"
|
class="btn btn-tpchild"
|
||||||
@click="emit('triggerAddContact', {parent: item.result})"
|
@click="emit('triggerAddContact', { parent: item.result })"
|
||||||
><i class="bi bi-person-fill-add"></i></a>
|
><i class="bi bi-person-fill-add"></i
|
||||||
|
></a>
|
||||||
<on-the-fly type="thirdparty" :id="item.result.id" action="show" />
|
<on-the-fly type="thirdparty" :id="item.result.id" action="show" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -38,16 +48,20 @@ import { Result, Suggestion } from "ChillPersonAssets/types";
|
|||||||
import {
|
import {
|
||||||
isThirdpartyChild,
|
isThirdpartyChild,
|
||||||
isThirdpartyContact,
|
isThirdpartyContact,
|
||||||
Thirdparty, ThirdpartyCompany
|
Thirdparty,
|
||||||
|
ThirdpartyCompany,
|
||||||
} from "./../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
} from "./../../../../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
|
|
||||||
interface TypeThirdPartyProps {
|
interface TypeThirdPartyProps {
|
||||||
item: Suggestion & {result: Thirdparty};
|
item: Suggestion & { result: Thirdparty };
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<TypeThirdPartyProps>();
|
const props = defineProps<TypeThirdPartyProps>();
|
||||||
|
|
||||||
const emit = defineEmits<(e: "triggerAddContact", payload: {parent: ThirdpartyCompany}) => void>();
|
const emit =
|
||||||
|
defineEmits<
|
||||||
|
(e: "triggerAddContact", payload: { parent: ThirdpartyCompany }) => void
|
||||||
|
>();
|
||||||
|
|
||||||
const onTheFly = ref<InstanceType<typeof OnTheFly> | null>(null);
|
const onTheFly = ref<InstanceType<typeof OnTheFly> | null>(null);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
@@ -56,7 +70,10 @@ const hasAddress = computed(() => {
|
|||||||
if (props.item.result.address !== null) {
|
if (props.item.result.address !== null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (isThirdpartyChild(props.item.result) && props.item.result.parent !== null) {
|
if (
|
||||||
|
isThirdpartyChild(props.item.result) &&
|
||||||
|
props.item.result.parent !== null
|
||||||
|
) {
|
||||||
return props.item.result.parent.address !== null;
|
return props.item.result.parent.address !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +84,11 @@ const getAddress = computed(() => {
|
|||||||
if (props.item.result.address !== null) {
|
if (props.item.result.address !== null) {
|
||||||
return props.item.result.address;
|
return props.item.result.address;
|
||||||
}
|
}
|
||||||
if (isThirdpartyChild(props.item.result) && props.item.result.parent !== null && props.item.result.parent.address !== null) {
|
if (
|
||||||
|
isThirdpartyChild(props.item.result) &&
|
||||||
|
props.item.result.parent !== null &&
|
||||||
|
props.item.result.parent.address !== null
|
||||||
|
) {
|
||||||
return props.item.result.parent.address;
|
return props.item.result.parent.address;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -14,14 +14,13 @@ import { computed, defineProps } from "vue";
|
|||||||
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
||||||
import UserRenderBoxBadge from "ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge.vue";
|
import UserRenderBoxBadge from "ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge.vue";
|
||||||
import { Suggestion } from "ChillPersonAssets/types";
|
import { Suggestion } from "ChillPersonAssets/types";
|
||||||
import {User} from "ChillMainAssets/types";
|
import { User } from "ChillMainAssets/types";
|
||||||
|
|
||||||
interface TypeUserProps {
|
interface TypeUserProps {
|
||||||
item: Suggestion & {result: User};
|
item: Suggestion & { result: User };
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<TypeUserProps>();
|
const props = defineProps<TypeUserProps>();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import UserGroupRenderBox from "ChillMainAssets/vuejs/_components/Entity/UserGro
|
|||||||
import { Suggestion } from "ChillPersonAssets/types";
|
import { Suggestion } from "ChillPersonAssets/types";
|
||||||
|
|
||||||
interface TypeUserGroupProps {
|
interface TypeUserGroupProps {
|
||||||
item: Suggestion & {result: UserGroup};
|
item: Suggestion & { result: UserGroup };
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<TypeUserGroupProps>();
|
const props = defineProps<TypeUserGroupProps>();
|
||||||
|
|||||||
@@ -23,35 +23,39 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<span
|
<span v-if="options.addId == true" :title="person.personId"
|
||||||
v-if="options.addId == true"
|
|
||||||
:title="person.personId"
|
|
||||||
><i class="bi bi-info-circle"></i> {{ person.personId }}</span
|
><i class="bi bi-info-circle"></i> {{ person.personId }}</span
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p v-if="options.addInfo === true" class="moreinfo">
|
<p v-if="options.addInfo === true" class="moreinfo">
|
||||||
<gender-icon-render-box
|
<gender-icon-render-box
|
||||||
v-if="person.gender"
|
v-if="person.gender"
|
||||||
:gender="person.gender"
|
:gender="person.gender"
|
||||||
/> <span
|
/>
|
||||||
v-if="person.birthdate"
|
<span v-if="person.birthdate">
|
||||||
>
|
{{
|
||||||
{{ trans(RENDERBOX_BIRTHDAY_STATEMENT, {gender: toGenderTranslation(person.gender), birthdate: ISOToDate(person.birthdate?.datetime)}) }}
|
trans(RENDERBOX_BIRTHDAY_STATEMENT, {
|
||||||
|
gender: toGenderTranslation(person.gender),
|
||||||
|
birthdate: ISOToDate(person.birthdate?.datetime),
|
||||||
|
})
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="options.addAge && person.birthdate" class="age">
|
<span v-if="options.addAge && person.birthdate" class="age">
|
||||||
({{ trans(RENDERBOX_YEARS_OLD, {n: person.age}) }})
|
({{ trans(RENDERBOX_YEARS_OLD, { n: person.age }) }})
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<span
|
<span v-if="person.deathdate">
|
||||||
v-if="person.deathdate"
|
{{
|
||||||
>
|
trans(RENDERBOX_DEATHDATE_STATEMENT, {
|
||||||
{{ trans(RENDERBOX_DEATHDATE_STATEMENT, {gender: toGenderTranslation(person.gender), deathdate: ISOToDate(person.deathdate?.datetime)}) }}
|
gender: toGenderTranslation(person.gender),
|
||||||
|
deathdate: ISOToDate(person.deathdate?.datetime),
|
||||||
|
})
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -59,11 +63,11 @@
|
|||||||
<div class="float-button bottom">
|
<div class="float-button bottom">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<slot name="record-actions"/>
|
<slot name="record-actions" />
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-content fa-ul">
|
<ul class="list-content fa-ul">
|
||||||
<li v-if="person.current_household_id">
|
<li v-if="person.current_household_id">
|
||||||
<i class="fa fa-li fa-map-marker"/>
|
<i class="fa fa-li fa-map-marker" />
|
||||||
<address-render-box
|
<address-render-box
|
||||||
v-if="person.current_household_address"
|
v-if="person.current_household_address"
|
||||||
:address="person.current_household_address"
|
:address="person.current_household_address"
|
||||||
@@ -84,7 +88,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-map-marker"/>
|
<i class="fa fa-li fa-map-marker" />
|
||||||
<p class="chill-no-data-statement">
|
<p class="chill-no-data-statement">
|
||||||
{{ trans(RENDERBOX_NO_DATA) }}
|
{{ trans(RENDERBOX_NO_DATA) }}
|
||||||
</p>
|
</p>
|
||||||
@@ -100,7 +104,7 @@
|
|||||||
v-for="(addr, i) in person.current_residential_addresses"
|
v-for="(addr, i) in person.current_residential_addresses"
|
||||||
:key="i"
|
:key="i"
|
||||||
>
|
>
|
||||||
<i class="fa fa-li fa-map-marker"/>
|
<i class="fa fa-li fa-map-marker" />
|
||||||
<div v-if="addr.address">
|
<div v-if="addr.address">
|
||||||
<span class="item-key">
|
<span class="item-key">
|
||||||
{{ trans(RENDERBOX_RESIDENTIAL_ADDRESS) }}:
|
{{ trans(RENDERBOX_RESIDENTIAL_ADDRESS) }}:
|
||||||
@@ -145,36 +149,36 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<li v-if="person.email">
|
<li v-if="person.email">
|
||||||
<i class="fa fa-li fa-envelope-o"/>
|
<i class="fa fa-li fa-envelope-o" />
|
||||||
<a :href="'mailto: ' + person.email">{{ person.email }}</a>
|
<a :href="'mailto: ' + person.email">{{ person.email }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-envelope-o"/>
|
<i class="fa fa-li fa-envelope-o" />
|
||||||
<p class="chill-no-data-statement">
|
<p class="chill-no-data-statement">
|
||||||
{{ trans(RENDERBOX_NO_DATA) }}
|
{{ trans(RENDERBOX_NO_DATA) }}
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-if="person.mobilenumber">
|
<li v-if="person.mobilenumber">
|
||||||
<i class="fa fa-li fa-mobile"/>
|
<i class="fa fa-li fa-mobile" />
|
||||||
<a :href="'tel: ' + person.mobilenumber">
|
<a :href="'tel: ' + person.mobilenumber">
|
||||||
{{ person.mobilenumber }}
|
{{ person.mobilenumber }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-mobile"/>
|
<i class="fa fa-li fa-mobile" />
|
||||||
<p class="chill-no-data-statement">
|
<p class="chill-no-data-statement">
|
||||||
{{ trans(RENDERBOX_NO_DATA) }}
|
{{ trans(RENDERBOX_NO_DATA) }}
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="person.phonenumber">
|
<li v-if="person.phonenumber">
|
||||||
<i class="fa fa-li fa-phone"/>
|
<i class="fa fa-li fa-phone" />
|
||||||
<a :href="'tel: ' + person.phonenumber">
|
<a :href="'tel: ' + person.phonenumber">
|
||||||
{{ person.phonenumber }}
|
{{ person.phonenumber }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-phone"/>
|
<i class="fa fa-li fa-phone" />
|
||||||
<p class="chill-no-data-statement">
|
<p class="chill-no-data-statement">
|
||||||
{{ trans(RENDERBOX_NO_DATA) }}
|
{{ trans(RENDERBOX_NO_DATA) }}
|
||||||
</p>
|
</p>
|
||||||
@@ -187,25 +191,25 @@
|
|||||||
options.addCenter
|
options.addCenter
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="fa fa-li fa-long-arrow-right"/>
|
<i class="fa fa-li fa-long-arrow-right" />
|
||||||
<template v-for="c in person.centers">
|
<template v-for="c in person.centers">
|
||||||
{{ c.name }}
|
{{ c.name }}
|
||||||
</template>
|
</template>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-long-arrow-right"/>
|
<i class="fa fa-li fa-long-arrow-right" />
|
||||||
<p class="chill-no-data-statement">
|
<p class="chill-no-data-statement">
|
||||||
{{ trans(RENDERBOX_NO_DATA) }}
|
{{ trans(RENDERBOX_NO_DATA) }}
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<slot name="custom-zone"/>
|
<slot name="custom-zone" />
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<slot name="end-bloc"/>
|
<slot name="end-bloc" />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -219,11 +223,11 @@
|
|||||||
class="fa-stack fa-holder"
|
class="fa-stack fa-holder"
|
||||||
:title="trans(RENDERBOX_HOLDER)"
|
:title="trans(RENDERBOX_HOLDER)"
|
||||||
>
|
>
|
||||||
<i class="fa fa-circle fa-stack-1x text-success"/>
|
<i class="fa fa-circle fa-stack-1x text-success" />
|
||||||
<i class="fa fa-stack-1x">T</i>
|
<i class="fa fa-stack-1x">T</i>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<person-text :person="person"/>
|
<person-text :person="person" />
|
||||||
</a>
|
</a>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
<span
|
<span
|
||||||
@@ -231,18 +235,18 @@
|
|||||||
class="fa-stack fa-holder"
|
class="fa-stack fa-holder"
|
||||||
:title="trans(RENDERBOX_HOLDER)"
|
:title="trans(RENDERBOX_HOLDER)"
|
||||||
>
|
>
|
||||||
<i class="fa fa-circle fa-stack-1x text-success"/>
|
<i class="fa fa-circle fa-stack-1x text-success" />
|
||||||
<i class="fa fa-stack-1x">T</i>
|
<i class="fa fa-stack-1x">T</i>
|
||||||
</span>
|
</span>
|
||||||
<person-text :person="person"/>
|
<person-text :person="person" />
|
||||||
</span>
|
</span>
|
||||||
<slot name="post-badge"/>
|
<slot name="post-badge" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed} from "vue";
|
import { computed } from "vue";
|
||||||
import {ISOToDate} from "ChillMainAssets/chill/js/date";
|
import { ISOToDate } from "ChillMainAssets/chill/js/date";
|
||||||
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
|
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
|
||||||
import GenderIconRenderBox from "ChillMainAssets/vuejs/_components/Entity/GenderIconRenderBox.vue";
|
import GenderIconRenderBox from "ChillMainAssets/vuejs/_components/Entity/GenderIconRenderBox.vue";
|
||||||
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
||||||
@@ -260,8 +264,8 @@ import {
|
|||||||
// PERSONS_ASSOCIATED_SHOW_HOUSEHOLD_NUMBER,
|
// PERSONS_ASSOCIATED_SHOW_HOUSEHOLD_NUMBER,
|
||||||
RENDERBOX_YEARS_OLD,
|
RENDERBOX_YEARS_OLD,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import {Person} from "ChillPersonAssets/types";
|
import { Person } from "ChillPersonAssets/types";
|
||||||
import {toGenderTranslation} from "ChillMainAssets/lib/api/genderHelper";
|
import { toGenderTranslation } from "ChillMainAssets/lib/api/genderHelper";
|
||||||
|
|
||||||
interface RenderOptions {
|
interface RenderOptions {
|
||||||
addInfo?: boolean;
|
addInfo?: boolean;
|
||||||
@@ -302,7 +306,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
addNoData: true,
|
addNoData: true,
|
||||||
isMultiline: true,
|
isMultiline: true,
|
||||||
isHolder: false,
|
isHolder: false,
|
||||||
addHouseholdLink: true
|
addHouseholdLink: true,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ interface Props {
|
|||||||
query?: string;
|
query?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {query: ""});
|
const props = withDefaults(defineProps<Props>(), { query: "" });
|
||||||
|
|
||||||
const person = ref<Person | null>(null);
|
const person = ref<Person | null>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -81,11 +81,12 @@
|
|||||||
value=""
|
value=""
|
||||||
@input="onAltNameInput($event, a.key)"
|
@input="onAltNameInput($event, a.key)"
|
||||||
/>
|
/>
|
||||||
<label :for="'label_' + a.key">{{ localizeString(a.labels) }}</label>
|
<label :for="'label_' + a.key">{{
|
||||||
|
localizeString(a.labels)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="action === 'create'">
|
<template v-if="action === 'create'">
|
||||||
@@ -98,18 +99,30 @@
|
|||||||
<div class="form-floating">
|
<div class="form-floating">
|
||||||
<input
|
<input
|
||||||
class="form-control form-control-lg"
|
class="form-control form-control-lg"
|
||||||
:class="{'is-invalid': violations.hasViolationWithParameter('identifiers', 'definition_id', worker.definition_id.toString())}"
|
:class="{
|
||||||
|
'is-invalid': violations.hasViolationWithParameter(
|
||||||
|
'identifiers',
|
||||||
|
'definition_id',
|
||||||
|
worker.definition_id.toString(),
|
||||||
|
),
|
||||||
|
}"
|
||||||
type="text"
|
type="text"
|
||||||
:name="'worker_' + worker.definition_id"
|
:name="'worker_' + worker.definition_id"
|
||||||
:placeholder="localizeString(worker.label)"
|
:placeholder="localizeString(worker.label)"
|
||||||
@input="onIdentifierInput($event, worker.definition_id)"
|
@input="onIdentifierInput($event, worker.definition_id)"
|
||||||
/>
|
/>
|
||||||
<label :for="'worker_' + worker.definition_id" :class="{required: worker.presence == 'REQUIRED'}">{{
|
<label
|
||||||
localizeString(worker.label)
|
:for="'worker_' + worker.definition_id"
|
||||||
}}</label>
|
:class="{ required: worker.presence == 'REQUIRED' }"
|
||||||
|
>{{ localizeString(worker.label) }}</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="err in violations.violationTitlesWithParameter('identifiers', 'definition_id', worker.definition_id.toString())"
|
v-for="err in violations.violationTitlesWithParameter(
|
||||||
|
'identifiers',
|
||||||
|
'definition_id',
|
||||||
|
worker.definition_id.toString(),
|
||||||
|
)"
|
||||||
class="invalid-feedback was-validated-force"
|
class="invalid-feedback was-validated-force"
|
||||||
>
|
>
|
||||||
{{ err }}
|
{{ err }}
|
||||||
@@ -163,7 +176,9 @@
|
|||||||
{{ c.name }}
|
{{ c.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<label for="center" class="required">{{ trans(PERSON_MESSAGES_PERSON_CENTER_TITLE) }}</label>
|
<label for="center" class="required">{{
|
||||||
|
trans(PERSON_MESSAGES_PERSON_CENTER_TITLE)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="err in violations.violationTitles('center')"
|
v-for="err in violations.violationTitles('center')"
|
||||||
@@ -190,7 +205,9 @@
|
|||||||
{{ localizeString(c.name) }}
|
{{ localizeString(c.name) }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<label for="civility">{{ trans(PERSON_MESSAGES_PERSON_CIVILITY_TITLE) }}</label>
|
<label for="civility">{{
|
||||||
|
trans(PERSON_MESSAGES_PERSON_CIVILITY_TITLE)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="err in violations.violationTitles('civility')"
|
v-for="err in violations.violationTitles('civility')"
|
||||||
@@ -215,7 +232,7 @@
|
|||||||
v-model="birthDate"
|
v-model="birthDate"
|
||||||
:placeholder="trans(BIRTHDATE)"
|
:placeholder="trans(BIRTHDATE)"
|
||||||
:aria-label="trans(BIRTHDATE)"
|
:aria-label="trans(BIRTHDATE)"
|
||||||
/>
|
/>
|
||||||
<label for="birthdate">{{ trans(BIRTHDATE) }}</label>
|
<label for="birthdate">{{ trans(BIRTHDATE) }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -241,7 +258,9 @@
|
|||||||
:aria-label="trans(PERSON_MESSAGES_PERSON_PHONENUMBER)"
|
:aria-label="trans(PERSON_MESSAGES_PERSON_PHONENUMBER)"
|
||||||
aria-describedby="phonenumber"
|
aria-describedby="phonenumber"
|
||||||
/>
|
/>
|
||||||
<label for="phonenumber">{{ trans(PERSON_MESSAGES_PERSON_PHONENUMBER) }}</label>
|
<label for="phonenumber">{{
|
||||||
|
trans(PERSON_MESSAGES_PERSON_PHONENUMBER)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="err in violations.violationTitles('phonenumber')"
|
v-for="err in violations.violationTitles('phonenumber')"
|
||||||
@@ -266,7 +285,9 @@
|
|||||||
:aria-label="trans(PERSON_MESSAGES_PERSON_MOBILENUMBER)"
|
:aria-label="trans(PERSON_MESSAGES_PERSON_MOBILENUMBER)"
|
||||||
aria-describedby="mobilenumber"
|
aria-describedby="mobilenumber"
|
||||||
/>
|
/>
|
||||||
<label for="mobilenumber">{{ trans(PERSON_MESSAGES_PERSON_MOBILENUMBER) }}</label>
|
<label for="mobilenumber">{{
|
||||||
|
trans(PERSON_MESSAGES_PERSON_MOBILENUMBER)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="err in violations.violationTitles('mobilenumber')"
|
v-for="err in violations.violationTitles('mobilenumber')"
|
||||||
@@ -326,11 +347,8 @@
|
|||||||
ref="addAddress"
|
ref="addAddress"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -338,7 +356,8 @@ import { ref, reactive, computed, onMounted } from "vue";
|
|||||||
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
||||||
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
||||||
import {
|
import {
|
||||||
createPerson, editPerson,
|
createPerson,
|
||||||
|
editPerson,
|
||||||
getCentersForPersonCreation,
|
getCentersForPersonCreation,
|
||||||
getCivilities,
|
getCivilities,
|
||||||
getGenders,
|
getGenders,
|
||||||
@@ -366,23 +385,20 @@ import {
|
|||||||
PERSON_MESSAGES_PERSON_ADDRESS_SHOW_ADDRESS_FORM,
|
PERSON_MESSAGES_PERSON_ADDRESS_SHOW_ADDRESS_FORM,
|
||||||
PERSON_MESSAGES_PERSON_ADDRESS_WARNING,
|
PERSON_MESSAGES_PERSON_ADDRESS_WARNING,
|
||||||
} from "translator";
|
} from "translator";
|
||||||
import {
|
import { Center, Civility, Gender } from "ChillMainAssets/types";
|
||||||
Center,
|
|
||||||
Civility,
|
|
||||||
Gender,
|
|
||||||
} from "ChillMainAssets/types";
|
|
||||||
import {
|
import {
|
||||||
AltName,
|
AltName,
|
||||||
Person,
|
Person,
|
||||||
PersonWrite,
|
PersonWrite,
|
||||||
PersonIdentifierWorker,
|
PersonIdentifierWorker,
|
||||||
} from "ChillPersonAssets/types";
|
} from "ChillPersonAssets/types";
|
||||||
|
import { isValidationException } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
import { useToast } from "vue-toast-notification";
|
||||||
import {
|
import {
|
||||||
isValidationException,
|
getTimezoneOffsetString,
|
||||||
} from "ChillMainAssets/lib/api/apiMethods";
|
ISOToDate,
|
||||||
import {useToast} from "vue-toast-notification";
|
} from "ChillMainAssets/chill/js/date";
|
||||||
import {getTimezoneOffsetString, ISOToDate} from "ChillMainAssets/chill/js/date";
|
import { useViolationList } from "ChillMainAssets/vuejs/_composables/violationList";
|
||||||
import {useViolationList} from "ChillMainAssets/vuejs/_composables/violationList";
|
|
||||||
|
|
||||||
interface PersonEditComponentConfig {
|
interface PersonEditComponentConfig {
|
||||||
id?: number | null;
|
id?: number | null;
|
||||||
@@ -486,13 +502,16 @@ const birthDate = computed({
|
|||||||
person.birthdate = null;
|
person.birthdate = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const offset = getTimezoneOffsetString(date, Intl.DateTimeFormat().resolvedOptions().timeZone);
|
const offset = getTimezoneOffsetString(
|
||||||
|
date,
|
||||||
|
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||||
|
);
|
||||||
if (person.birthdate) {
|
if (person.birthdate) {
|
||||||
person.birthdate.datetime = value + "T00:00:00" + offset;
|
person.birthdate.datetime = value + "T00:00:00" + offset;
|
||||||
} else {
|
} else {
|
||||||
person.birthdate = { datetime: value + "T00:00:00" + offset };
|
person.birthdate = { datetime: value + "T00:00:00" + offset };
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const phonenumber = computed({
|
const phonenumber = computed({
|
||||||
get: () => person.phonenumber,
|
get: () => person.phonenumber,
|
||||||
@@ -566,7 +585,7 @@ async function loadData() {
|
|||||||
const w = personToWritePerson(p);
|
const w = personToWritePerson(p);
|
||||||
person.firstName = w.firstName;
|
person.firstName = w.firstName;
|
||||||
person.lastName = w.lastName;
|
person.lastName = w.lastName;
|
||||||
person.altNames.push(...w.altNames)
|
person.altNames.push(...w.altNames);
|
||||||
person.civility = w.civility;
|
person.civility = w.civility;
|
||||||
person.addressId = w.addressId;
|
person.addressId = w.addressId;
|
||||||
person.birthdate = w.birthdate;
|
person.birthdate = w.birthdate;
|
||||||
@@ -633,7 +652,7 @@ function submitNewAddress(payload: { addressId: number }) {
|
|||||||
|
|
||||||
async function postPerson(): Promise<Person> {
|
async function postPerson(): Promise<Person> {
|
||||||
try {
|
try {
|
||||||
if (props.action === 'create') {
|
if (props.action === "create") {
|
||||||
const createdPerson = await createPerson(person);
|
const createdPerson = await createPerson(person);
|
||||||
emit("onPersonCreated", { person: createdPerson });
|
emit("onPersonCreated", { person: createdPerson });
|
||||||
|
|
||||||
@@ -667,8 +686,8 @@ onMounted(() => {
|
|||||||
getPersonIdentifiers().then((identifiers) => {
|
getPersonIdentifiers().then((identifiers) => {
|
||||||
config.identifiers = identifiers.filter(
|
config.identifiers = identifiers.filter(
|
||||||
(w: PersonIdentifierWorker) =>
|
(w: PersonIdentifierWorker) =>
|
||||||
w.presence === 'ON_CREATION' || w.presence === 'REQUIRED'
|
w.presence === "ON_CREATION" || w.presence === "REQUIRED",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (props.action !== "create") {
|
if (props.action !== "create") {
|
||||||
loadData();
|
loadData();
|
||||||
|
|||||||
@@ -1,64 +1,63 @@
|
|||||||
const personMessages = {
|
const personMessages = {
|
||||||
fr: {
|
fr: {
|
||||||
add_persons: {
|
add_persons: {
|
||||||
title: "Ajouter des usagers",
|
title: "Ajouter des usagers",
|
||||||
suggested_counter:
|
suggested_counter: "Pas de résultats | 1 résultat | {count} résultats",
|
||||||
"Pas de résultats | 1 résultat | {count} résultats",
|
selected_counter: " 1 sélectionné | {count} sélectionnés",
|
||||||
selected_counter: " 1 sélectionné | {count} sélectionnés",
|
search_some_persons: "Rechercher des personnes..",
|
||||||
search_some_persons: "Rechercher des personnes..",
|
|
||||||
},
|
|
||||||
item: {
|
|
||||||
type_person: "Usager",
|
|
||||||
type_user: "TMS",
|
|
||||||
type_thirdparty: "Tiers professionnel",
|
|
||||||
type_household: "Ménage",
|
|
||||||
},
|
|
||||||
person: {
|
|
||||||
firstname: "Prénom",
|
|
||||||
lastname: "Nom",
|
|
||||||
born: (ctx: { gender: "man" | "woman" | "neutral" }) => {
|
|
||||||
if (ctx.gender === "man") {
|
|
||||||
return "Né le";
|
|
||||||
} else if (ctx.gender === "woman") {
|
|
||||||
return "Née le";
|
|
||||||
} else {
|
|
||||||
return "Né·e le";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
center_id: "Identifiant du territoire",
|
|
||||||
center_type: "Type de territoire",
|
|
||||||
center_name: "Territoire", // vendée
|
|
||||||
phonenumber: "Téléphone",
|
|
||||||
mobilenumber: "Mobile",
|
|
||||||
altnames: "Autres noms",
|
|
||||||
email: "Courriel",
|
|
||||||
gender: {
|
|
||||||
title: "Genre",
|
|
||||||
placeholder: "Choisissez le genre de l'usager",
|
|
||||||
woman: "Féminin",
|
|
||||||
man: "Masculin",
|
|
||||||
neutral: "Neutre, non binaire",
|
|
||||||
unknown: "Non renseigné",
|
|
||||||
undefined: "Non renseigné",
|
|
||||||
},
|
|
||||||
civility: {
|
|
||||||
title: "Civilité",
|
|
||||||
placeholder: "Choisissez la civilité",
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
create_address: "Ajouter une adresse",
|
|
||||||
show_address_form:
|
|
||||||
"Ajouter une adresse pour un usager non suivi et seul dans un ménage",
|
|
||||||
warning:
|
|
||||||
"Un nouveau ménage va être créé. L'usager sera membre de ce ménage.",
|
|
||||||
},
|
|
||||||
center: {
|
|
||||||
placeholder: "Choisissez un territoire",
|
|
||||||
title: "territoire",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
error_only_one_person: "Une seule personne peut être sélectionnée !",
|
|
||||||
},
|
},
|
||||||
|
item: {
|
||||||
|
type_person: "Usager",
|
||||||
|
type_user: "TMS",
|
||||||
|
type_thirdparty: "Tiers professionnel",
|
||||||
|
type_household: "Ménage",
|
||||||
|
},
|
||||||
|
person: {
|
||||||
|
firstname: "Prénom",
|
||||||
|
lastname: "Nom",
|
||||||
|
born: (ctx: { gender: "man" | "woman" | "neutral" }) => {
|
||||||
|
if (ctx.gender === "man") {
|
||||||
|
return "Né le";
|
||||||
|
} else if (ctx.gender === "woman") {
|
||||||
|
return "Née le";
|
||||||
|
} else {
|
||||||
|
return "Né·e le";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
center_id: "Identifiant du territoire",
|
||||||
|
center_type: "Type de territoire",
|
||||||
|
center_name: "Territoire", // vendée
|
||||||
|
phonenumber: "Téléphone",
|
||||||
|
mobilenumber: "Mobile",
|
||||||
|
altnames: "Autres noms",
|
||||||
|
email: "Courriel",
|
||||||
|
gender: {
|
||||||
|
title: "Genre",
|
||||||
|
placeholder: "Choisissez le genre de l'usager",
|
||||||
|
woman: "Féminin",
|
||||||
|
man: "Masculin",
|
||||||
|
neutral: "Neutre, non binaire",
|
||||||
|
unknown: "Non renseigné",
|
||||||
|
undefined: "Non renseigné",
|
||||||
|
},
|
||||||
|
civility: {
|
||||||
|
title: "Civilité",
|
||||||
|
placeholder: "Choisissez la civilité",
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
create_address: "Ajouter une adresse",
|
||||||
|
show_address_form:
|
||||||
|
"Ajouter une adresse pour un usager non suivi et seul dans un ménage",
|
||||||
|
warning:
|
||||||
|
"Un nouveau ménage va être créé. L'usager sera membre de ce ménage.",
|
||||||
|
},
|
||||||
|
center: {
|
||||||
|
placeholder: "Choisissez un territoire",
|
||||||
|
title: "territoire",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
error_only_one_person: "Une seule personne peut être sélectionnée !",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export { personMessages };
|
export { personMessages };
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import {
|
|||||||
Address,
|
Address,
|
||||||
Center,
|
Center,
|
||||||
Civility,
|
Civility,
|
||||||
DateTime, SetAddress, SetCivility,
|
DateTime,
|
||||||
|
SetAddress,
|
||||||
|
SetCivility,
|
||||||
User,
|
User,
|
||||||
} from "ChillMainAssets/types";
|
} from "ChillMainAssets/types";
|
||||||
|
|
||||||
@@ -10,7 +12,7 @@ export type ThirdPartyKind = "contact" | "child" | "company";
|
|||||||
|
|
||||||
export interface BaseThirdParty {
|
export interface BaseThirdParty {
|
||||||
type: "thirdparty";
|
type: "thirdparty";
|
||||||
kind: ""|ThirdPartyKind;
|
kind: "" | ThirdPartyKind;
|
||||||
text: string;
|
text: string;
|
||||||
acronym: string | null;
|
acronym: string | null;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
@@ -35,7 +37,10 @@ function isBaseThirdParty(t: unknown): t is BaseThirdParty {
|
|||||||
(o as any).type === "thirdparty" &&
|
(o as any).type === "thirdparty" &&
|
||||||
typeof o.id === "number" &&
|
typeof o.id === "number" &&
|
||||||
typeof o.text === "string" &&
|
typeof o.text === "string" &&
|
||||||
(o.kind === "" || o.kind === "contact" || o.kind === "child" || o.kind === "company") &&
|
(o.kind === "" ||
|
||||||
|
o.kind === "contact" ||
|
||||||
|
o.kind === "child" ||
|
||||||
|
o.kind === "company") &&
|
||||||
typeof o.active === "boolean"
|
typeof o.active === "boolean"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -51,13 +56,8 @@ export interface ThirdpartyCompany extends BaseThirdParty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Type guard to distinguish a ThirdpartyCompany
|
// Type guard to distinguish a ThirdpartyCompany
|
||||||
export function isThirdpartyCompany(
|
export function isThirdpartyCompany(t: BaseThirdParty): t is ThirdpartyCompany {
|
||||||
t: BaseThirdParty
|
return t.type === "thirdparty" && t.kind === "company";
|
||||||
): t is ThirdpartyCompany {
|
|
||||||
return (
|
|
||||||
t.type === "thirdparty" &&
|
|
||||||
t.kind === "company"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ThirdpartyChild extends BaseThirdParty {
|
export interface ThirdpartyChild extends BaseThirdParty {
|
||||||
@@ -75,13 +75,8 @@ export interface ThirdpartyChild extends BaseThirdParty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Type guard to distinguish a ThirdpartyChild
|
// Type guard to distinguish a ThirdpartyChild
|
||||||
export function isThirdpartyChild(
|
export function isThirdpartyChild(t: BaseThirdParty): t is ThirdpartyChild {
|
||||||
t: BaseThirdParty
|
return t.type === "thirdparty" && t.kind === "child";
|
||||||
): t is ThirdpartyChild {
|
|
||||||
return (
|
|
||||||
t.type === "thirdparty" &&
|
|
||||||
t.kind === "child"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ThirdpartyContact extends BaseThirdParty {
|
export interface ThirdpartyContact extends BaseThirdParty {
|
||||||
@@ -99,24 +94,23 @@ export interface ThirdpartyContact extends BaseThirdParty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Type guard to distinguish a ThirdpartyContact
|
// Type guard to distinguish a ThirdpartyContact
|
||||||
export function isThirdpartyContact(
|
export function isThirdpartyContact(t: BaseThirdParty): t is ThirdpartyContact {
|
||||||
t: BaseThirdParty
|
return t.type === "thirdparty" && t.kind === "contact";
|
||||||
): t is ThirdpartyContact {
|
|
||||||
return (
|
|
||||||
t.type === "thirdparty" &&
|
|
||||||
t.kind === "contact"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Thirdparty = ThirdpartyCompany | ThirdpartyContact | ThirdpartyChild;
|
export type Thirdparty =
|
||||||
|
| ThirdpartyCompany
|
||||||
|
| ThirdpartyContact
|
||||||
|
| ThirdpartyChild;
|
||||||
|
|
||||||
export function isThirdparty(t: unknown): t is Thirdparty {
|
export function isThirdparty(t: unknown): t is Thirdparty {
|
||||||
if (!isBaseThirdParty(t)) {
|
if (!isBaseThirdParty(t)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (isThirdpartyCompany(t) || isThirdpartyContact(t) || isThirdpartyChild(t));
|
return (
|
||||||
|
isThirdpartyCompany(t) || isThirdpartyContact(t) || isThirdpartyChild(t)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ThirdpartyType {
|
interface ThirdpartyType {
|
||||||
@@ -153,7 +147,7 @@ export interface ThirdPartyWrite {
|
|||||||
email: string;
|
email: string;
|
||||||
telephone: string;
|
telephone: string;
|
||||||
telephone2: string;
|
telephone2: string;
|
||||||
address: null|SetAddress;
|
address: null | SetAddress;
|
||||||
comment: string;
|
comment: string;
|
||||||
parent: SetThirdParty|null;
|
parent: SetThirdParty | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* GET a thirdparty by id
|
* GET a thirdparty by id
|
||||||
*/
|
*/
|
||||||
import {isThirdpartyChild, isThirdpartyCompany, isThirdpartyContact, Thirdparty, ThirdPartyWrite} from '../../types';
|
import {
|
||||||
import {makeFetch} from "ChillMainAssets/lib/api/apiMethods";
|
isThirdpartyChild,
|
||||||
|
isThirdpartyCompany,
|
||||||
|
isThirdpartyContact,
|
||||||
|
Thirdparty,
|
||||||
|
ThirdPartyWrite,
|
||||||
|
} from "../../types";
|
||||||
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
|
||||||
export const getThirdparty = async (id: number) : Promise<Thirdparty> => {
|
export const getThirdparty = async (id: number): Promise<Thirdparty> => {
|
||||||
const url = `/api/1.0/thirdparty/thirdparty/${id}.json`;
|
const url = `/api/1.0/thirdparty/thirdparty/${id}.json`;
|
||||||
return fetch(url).then((response) => {
|
return fetch(url).then((response) => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
@@ -21,40 +27,41 @@ export const thirdpartyToWriteThirdParty = (t: Thirdparty): ThirdPartyWrite => {
|
|||||||
const isChild = isThirdpartyChild(t);
|
const isChild = isThirdpartyChild(t);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'thirdparty',
|
type: "thirdparty",
|
||||||
kind: t.kind,
|
kind: t.kind,
|
||||||
civility:
|
civility:
|
||||||
(isContact || isChild) && t.civility
|
(isContact || isChild) && t.civility
|
||||||
? { type: 'chill_main_civility', id: t.civility.id }
|
? { type: "chill_main_civility", id: t.civility.id }
|
||||||
: null,
|
: null,
|
||||||
profession: (isContact || isChild) ? (t.profession ?? '') : '',
|
profession: isContact || isChild ? (t.profession ?? "") : "",
|
||||||
firstname: isCompany ? '' : (t.firstname ?? ''),
|
firstname: isCompany ? "" : (t.firstname ?? ""),
|
||||||
name: isCompany
|
name: isCompany ? (t.nameCompany ?? "") : (t.name ?? ""),
|
||||||
? (t.nameCompany ?? '')
|
email: t.email ?? "",
|
||||||
: (t.name ?? ''),
|
telephone: t.telephone ?? "",
|
||||||
email: t.email ?? '',
|
telephone2: t.telephone2 ?? "",
|
||||||
telephone: t.telephone ?? '',
|
|
||||||
telephone2: t.telephone2 ?? '',
|
|
||||||
address: null,
|
address: null,
|
||||||
comment: isChild ? (t.comment ?? '') : '',
|
comment: isChild ? (t.comment ?? "") : "",
|
||||||
parent: isChild && t.parent ? { type: 'thirdparty', id: t.parent.id } : null,
|
parent:
|
||||||
|
isChild && t.parent ? { type: "thirdparty", id: t.parent.id } : null,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface WriteThirdPartyViolationMap
|
export interface WriteThirdPartyViolationMap extends Record<
|
||||||
extends Record<string, Record<string, string>> {
|
string,
|
||||||
|
Record<string, string>
|
||||||
|
> {
|
||||||
email: {
|
email: {
|
||||||
"{{ value }}": string;
|
"{{ value }}": string;
|
||||||
},
|
};
|
||||||
name: {
|
name: {
|
||||||
"{{ value }}": string;
|
"{{ value }}": string;
|
||||||
},
|
};
|
||||||
telephone: {
|
telephone: {
|
||||||
"{{ value }}": string;
|
"{{ value }}": string;
|
||||||
}
|
};
|
||||||
telephone2: {
|
telephone2: {
|
||||||
"{{ value }}": string;
|
"{{ value }}": string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -63,13 +70,16 @@ extends Record<string, Record<string, string>> {
|
|||||||
export const createThirdParty = async (body: ThirdPartyWrite) => {
|
export const createThirdParty = async (body: ThirdPartyWrite) => {
|
||||||
const url = `/api/1.0/thirdparty/thirdparty.json`;
|
const url = `/api/1.0/thirdparty/thirdparty.json`;
|
||||||
|
|
||||||
return makeFetch<ThirdPartyWrite, Thirdparty>('POST', url, body);
|
return makeFetch<ThirdPartyWrite, Thirdparty>("POST", url, body);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PATCH an existing thirdparty
|
* PATCH an existing thirdparty
|
||||||
*/
|
*/
|
||||||
export const patchThirdparty = async (id: number, body: ThirdPartyWrite): Promise<Thirdparty> => {
|
export const patchThirdparty = async (
|
||||||
|
id: number,
|
||||||
|
body: ThirdPartyWrite,
|
||||||
|
): Promise<Thirdparty> => {
|
||||||
const url = `/api/1.0/thirdparty/thirdparty/${id}.json`;
|
const url = `/api/1.0/thirdparty/thirdparty/${id}.json`;
|
||||||
return makeFetch('PATCH', url, body);
|
return makeFetch("PATCH", url, body);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li v-if="isThirdpartyChild(props.thirdparty)">
|
<li v-if="isThirdpartyChild(props.thirdparty)">
|
||||||
<i class="fa fa-li fa-hand-o-right" />
|
<i class="fa fa-li fa-hand-o-right" />
|
||||||
<b class="me-2">{{ trans(THIRDPARTY_MESSAGES_CHILD_OF)}}</b>
|
<b class="me-2">{{ trans(THIRDPARTY_MESSAGES_CHILD_OF) }}</b>
|
||||||
<on-the-fly
|
<on-the-fly
|
||||||
:type="props.thirdparty.parent.type"
|
:type="props.thirdparty.parent.type"
|
||||||
:id="props.thirdparty.parent.id"
|
:id="props.thirdparty.parent.id"
|
||||||
@@ -133,13 +133,14 @@ import { computed, defineAsyncComponent } from "vue";
|
|||||||
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
|
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
|
||||||
import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
|
import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
|
||||||
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
||||||
import {isThirdpartyChild, isThirdpartyCompany, Thirdparty} from "../../../types";
|
|
||||||
import {localizeString} from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
|
||||||
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
|
|
||||||
import {
|
import {
|
||||||
THIRDPARTY_MESSAGES_CHILD_OF,
|
isThirdpartyChild,
|
||||||
trans
|
isThirdpartyCompany,
|
||||||
} from "translator";
|
Thirdparty,
|
||||||
|
} from "../../../types";
|
||||||
|
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
||||||
|
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
|
||||||
|
import { THIRDPARTY_MESSAGES_CHILD_OF, trans } from "translator";
|
||||||
|
|
||||||
// Async to avoid recursive resolution issues
|
// Async to avoid recursive resolution issues
|
||||||
/*
|
/*
|
||||||
@@ -160,7 +161,9 @@ interface RenderOptions {
|
|||||||
|
|
||||||
const props = defineProps<{ thirdparty: Thirdparty; options: RenderOptions }>();
|
const props = defineProps<{ thirdparty: Thirdparty; options: RenderOptions }>();
|
||||||
|
|
||||||
const isMultiline = computed<boolean>(() => props.options?.isMultiline ?? false);
|
const isMultiline = computed<boolean>(
|
||||||
|
() => props.options?.isMultiline ?? false,
|
||||||
|
);
|
||||||
|
|
||||||
const hasParent = computed<boolean>(() => {
|
const hasParent = computed<boolean>(() => {
|
||||||
return isThirdpartyChild(props.thirdparty);
|
return isThirdpartyChild(props.thirdparty);
|
||||||
|
|||||||
@@ -20,48 +20,53 @@
|
|||||||
action === 'edit' || action === 'create' || action === 'addContact'
|
action === 'edit' || action === 'create' || action === 'addContact'
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<ThirdPartyEdit :id="id" :type="type" :action="action" :query="query" :parent="parent" />
|
<ThirdPartyEdit
|
||||||
|
:id="id"
|
||||||
|
:type="type"
|
||||||
|
:action="action"
|
||||||
|
:query="query"
|
||||||
|
:parent="parent"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {onMounted, ref} from 'vue'
|
import { onMounted, ref } from "vue";
|
||||||
import ThirdPartyRenderBox from '../Entity/ThirdPartyRenderBox.vue'
|
import ThirdPartyRenderBox from "../Entity/ThirdPartyRenderBox.vue";
|
||||||
import ThirdPartyEdit from './ThirdPartyEdit.vue'
|
import ThirdPartyEdit from "./ThirdPartyEdit.vue";
|
||||||
import { getThirdparty } from '../../_api/OnTheFly'
|
import { getThirdparty } from "../../_api/OnTheFly";
|
||||||
import {Thirdparty, ThirdpartyCompany} from '../../../types'
|
import { Thirdparty, ThirdpartyCompany } from "../../../types";
|
||||||
|
|
||||||
type ThirdPartyProp = {
|
interface ThirdPartyProp {
|
||||||
id: number,
|
id: number;
|
||||||
type: 'thirdparty',
|
type: "thirdparty";
|
||||||
action: 'show'|'edit'|'create',
|
action: "show" | "edit" | "create";
|
||||||
parent?: null,
|
parent?: null;
|
||||||
}
|
}
|
||||||
type ThirdPartyAddContact = {
|
interface ThirdPartyAddContact {
|
||||||
id: number,
|
id: number;
|
||||||
type: 'thirdparty',
|
type: "thirdparty";
|
||||||
action: 'addContact',
|
action: "addContact";
|
||||||
parent: ThirdpartyCompany,
|
parent: ThirdpartyCompany;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ThirdPartyProps = ThirdPartyProp|ThirdPartyAddContact;
|
type ThirdPartyProps = ThirdPartyProp | ThirdPartyAddContact;
|
||||||
|
|
||||||
const props = withDefaults(defineProps<ThirdPartyProps>(), {
|
const props = withDefaults(defineProps<ThirdPartyProps>(), {
|
||||||
parent: null,
|
parent: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const thirdparty = ref<Thirdparty|null>(null);
|
const thirdparty = ref<Thirdparty | null>(null);
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
thirdparty.value = await getThirdparty(props.id);
|
thirdparty.value = await getThirdparty(props.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.action === 'show' && props.id) {
|
if (props.action === "show" && props.id) {
|
||||||
loadData()
|
loadData();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<div v-if="resolvedParent">
|
<div v-if="resolvedParent">
|
||||||
<div class="parent-info">
|
<div class="parent-info">
|
||||||
<i class="fa fa-li fa-hand-o-right"/>
|
<i class="fa fa-li fa-hand-o-right" />
|
||||||
<b class="me-2">{{ trans(THIRDPARTY_MESSAGES_CHILD_OF) }}</b>
|
<b class="me-2">{{ trans(THIRDPARTY_MESSAGES_CHILD_OF) }}</b>
|
||||||
<span class="chill-entity badge-thirdparty">{{ resolvedParent.text }}</span>
|
<span class="chill-entity badge-thirdparty">{{
|
||||||
|
resolvedParent.text
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating mb-3" v-else-if="props.action === 'create'">
|
<div class="form-floating mb-3" v-else-if="props.action === 'create'">
|
||||||
@@ -77,7 +79,9 @@
|
|||||||
{{ localizeString(civility.name) }}
|
{{ localizeString(civility.name) }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<label for="civility">{{ trans(THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY) }}</label>
|
<label for="civility">{{
|
||||||
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,7 +97,9 @@
|
|||||||
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)"
|
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)"
|
||||||
aria-describedby="profession"
|
aria-describedby="profession"
|
||||||
/>
|
/>
|
||||||
<label for="profession">{{ trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION) }}</label>
|
<label for="profession">{{
|
||||||
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -110,8 +116,8 @@
|
|||||||
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)"
|
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)"
|
||||||
/>
|
/>
|
||||||
<label for="firstname">{{
|
<label for="firstname">{{
|
||||||
trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="queryItems">
|
<div v-if="queryItems">
|
||||||
@@ -139,8 +145,8 @@
|
|||||||
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)"
|
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)"
|
||||||
/>
|
/>
|
||||||
<label for="name">{{
|
<label for="name">{{
|
||||||
trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -177,8 +183,8 @@
|
|||||||
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)"
|
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)"
|
||||||
/>
|
/>
|
||||||
<label for="name">{{
|
<label for="name">{{
|
||||||
trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)
|
||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -212,7 +218,7 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="input-group has-validation">
|
<div class="input-group has-validation">
|
||||||
<span id="email" class="input-group-text">
|
<span id="email" class="input-group-text">
|
||||||
<i class="fa fa-fw fa-at"/>
|
<i class="fa fa-fw fa-at" />
|
||||||
</span>
|
</span>
|
||||||
<div class="form-floating">
|
<div class="form-floating">
|
||||||
<input
|
<input
|
||||||
@@ -224,7 +230,9 @@
|
|||||||
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)"
|
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)"
|
||||||
aria-describedby="email"
|
aria-describedby="email"
|
||||||
/>
|
/>
|
||||||
<label for="email">{{ trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL) }}</label>
|
<label for="email">{{
|
||||||
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -238,19 +246,21 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="input-group has-validation">
|
<div class="input-group has-validation">
|
||||||
<span class="input-group-text" id="phonenumber">
|
<span class="input-group-text" id="phonenumber">
|
||||||
<i class="fa fa-fw fa-phone"/>
|
<i class="fa fa-fw fa-phone" />
|
||||||
</span>
|
</span>
|
||||||
<div class="form-floating">
|
<div class="form-floating">
|
||||||
<input
|
<input
|
||||||
class="form-control form-control-lg"
|
class="form-control form-control-lg"
|
||||||
:class="{'is-invalid': violations.hasViolation('telephone') }"
|
:class="{ 'is-invalid': violations.hasViolation('telephone') }"
|
||||||
name="phonenumber"
|
name="phonenumber"
|
||||||
v-model="thirdParty.telephone"
|
v-model="thirdParty.telephone"
|
||||||
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
|
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
|
||||||
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
|
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
|
||||||
aria-describedby="phonenumber"
|
aria-describedby="phonenumber"
|
||||||
/>
|
/>
|
||||||
<label for="phonenumber">{{ trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER) }}</label>
|
<label for="phonenumber">{{
|
||||||
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -263,7 +273,9 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="input-group has-validation">
|
<div class="input-group has-validation">
|
||||||
<span class="input-group-text" id="phonenumber2"><i class="fa fa-fw fa-phone"/></span>
|
<span class="input-group-text" id="phonenumber2"
|
||||||
|
><i class="fa fa-fw fa-phone"
|
||||||
|
/></span>
|
||||||
<div class="form-floating">
|
<div class="form-floating">
|
||||||
<input
|
<input
|
||||||
class="form-control form-control-lg"
|
class="form-control form-control-lg"
|
||||||
@@ -274,7 +286,9 @@
|
|||||||
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)"
|
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)"
|
||||||
aria-describedby="phonenumber2"
|
aria-describedby="phonenumber2"
|
||||||
/>
|
/>
|
||||||
<label for="phonenumber2">{{ trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2) }}</label>
|
<label for="phonenumber2">{{
|
||||||
|
trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)
|
||||||
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -288,7 +302,7 @@
|
|||||||
<div v-if="props.action !== 'addContact'">
|
<div v-if="props.action !== 'addContact'">
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<span class="input-group-text" id="comment"
|
<span class="input-group-text" id="comment"
|
||||||
><i class="fa fa-fw fa-pencil"
|
><i class="fa fa-fw fa-pencil"
|
||||||
/></span>
|
/></span>
|
||||||
<textarea
|
<textarea
|
||||||
class="form-control form-control-lg"
|
class="form-control form-control-lg"
|
||||||
@@ -301,17 +315,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, reactive, computed, onMounted, getCurrentInstance} from 'vue'
|
import { ref, reactive, computed, onMounted, getCurrentInstance } from "vue";
|
||||||
import ThirdPartyRenderBox from '../Entity/ThirdPartyRenderBox.vue'
|
import ThirdPartyRenderBox from "../Entity/ThirdPartyRenderBox.vue";
|
||||||
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
||||||
import {
|
import {
|
||||||
createThirdParty,
|
createThirdParty,
|
||||||
getThirdparty, patchThirdparty,
|
getThirdparty,
|
||||||
|
patchThirdparty,
|
||||||
thirdpartyToWriteThirdParty,
|
thirdpartyToWriteThirdParty,
|
||||||
WriteThirdPartyViolationMap
|
WriteThirdPartyViolationMap,
|
||||||
} from '../../_api/OnTheFly'
|
} from "../../_api/OnTheFly";
|
||||||
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue'
|
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
|
||||||
import {localizeString as _localizeString} from 'ChillMainAssets/lib/localizationHelper/localizationHelper'
|
import { localizeString as _localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
||||||
import {
|
import {
|
||||||
trans,
|
trans,
|
||||||
THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME,
|
THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME,
|
||||||
@@ -323,11 +338,13 @@ import {
|
|||||||
THIRDPARTY_MESSAGES_THIRDPARTY_COMMENT,
|
THIRDPARTY_MESSAGES_THIRDPARTY_COMMENT,
|
||||||
THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION,
|
THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION,
|
||||||
THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY,
|
THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY,
|
||||||
THIRDPARTY_MESSAGES_CHILD_OF, PERSON_EDIT_ERROR_WHILE_SAVING,
|
THIRDPARTY_MESSAGES_CHILD_OF,
|
||||||
} from 'translator'
|
PERSON_EDIT_ERROR_WHILE_SAVING,
|
||||||
|
} from "translator";
|
||||||
import {
|
import {
|
||||||
createPerson,
|
createPerson,
|
||||||
getCivilities, WritePersonViolationMap,
|
getCivilities,
|
||||||
|
WritePersonViolationMap,
|
||||||
} from "ChillPersonAssets/vuejs/_api/OnTheFly";
|
} from "ChillPersonAssets/vuejs/_api/OnTheFly";
|
||||||
import {
|
import {
|
||||||
isThirdpartyChild,
|
isThirdpartyChild,
|
||||||
@@ -335,44 +352,49 @@ import {
|
|||||||
Thirdparty,
|
Thirdparty,
|
||||||
ThirdpartyCompany,
|
ThirdpartyCompany,
|
||||||
ThirdPartyKind,
|
ThirdPartyKind,
|
||||||
ThirdPartyWrite
|
ThirdPartyWrite,
|
||||||
} from "../../../types";
|
} from "../../../types";
|
||||||
import {Civility, SetCivility} from "ChillMainAssets/types";
|
import { Civility, SetCivility } from "ChillMainAssets/types";
|
||||||
import {isValidationException} from "ChillMainAssets/lib/api/apiMethods";
|
import { isValidationException } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
import {useViolationList} from "ChillMainAssets/vuejs/_composables/violationList";
|
import { useViolationList } from "ChillMainAssets/vuejs/_composables/violationList";
|
||||||
import {useToast} from "vue-toast-notification";
|
import { useToast } from "vue-toast-notification";
|
||||||
|
|
||||||
|
|
||||||
interface ThirdPartyEditWriteProps {
|
interface ThirdPartyEditWriteProps {
|
||||||
id?: number;
|
id?: number;
|
||||||
type?: 'thirdparty';
|
type?: "thirdparty";
|
||||||
action: 'edit' | 'create'
|
action: "edit" | "create";
|
||||||
query?: string;
|
query?: string;
|
||||||
parent?: null;
|
parent?: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ThirdPartyAddContactProps {
|
interface ThirdPartyAddContactProps {
|
||||||
id?: null;
|
id?: null;
|
||||||
type?: 'thirdparty';
|
type?: "thirdparty";
|
||||||
action: 'addContact';
|
action: "addContact";
|
||||||
query?: "";
|
query?: "";
|
||||||
parent: ThirdpartyCompany;
|
parent: ThirdpartyCompany;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ThirdPartyEditProps = ThirdPartyAddContactProps | ThirdPartyEditWriteProps;
|
type ThirdPartyEditProps = ThirdPartyAddContactProps | ThirdPartyEditWriteProps;
|
||||||
|
|
||||||
const props = withDefaults(defineProps<ThirdPartyEditProps>(), {type: 'thirdparty', query: "", parent: null});
|
const props = withDefaults(defineProps<ThirdPartyEditProps>(), {
|
||||||
|
type: "thirdparty",
|
||||||
|
query: "",
|
||||||
|
parent: null,
|
||||||
|
});
|
||||||
|
|
||||||
const emit =
|
const emit =
|
||||||
defineEmits<(e: "onThirdPartyCreated", payload: { thirdParty: Thirdparty }) => void>();
|
defineEmits<
|
||||||
|
(e: "onThirdPartyCreated", payload: { thirdParty: Thirdparty }) => void
|
||||||
|
>();
|
||||||
|
|
||||||
defineExpose({postThirdParty});
|
defineExpose({ postThirdParty });
|
||||||
|
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
const thirdParty = ref<ThirdPartyWrite>({
|
const thirdParty = ref<ThirdPartyWrite>({
|
||||||
type: "thirdparty",
|
type: "thirdparty",
|
||||||
kind: 'company',
|
kind: "company",
|
||||||
address: null,
|
address: null,
|
||||||
civility: null,
|
civility: null,
|
||||||
email: "",
|
email: "",
|
||||||
@@ -385,7 +407,7 @@ const thirdParty = ref<ThirdPartyWrite>({
|
|||||||
parent: null,
|
parent: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const originalThirdParty = ref<Thirdparty|null>(null);
|
const originalThirdParty = ref<Thirdparty | null>(null);
|
||||||
|
|
||||||
const civility = computed<number | null>({
|
const civility = computed<number | null>({
|
||||||
get: () => {
|
get: () => {
|
||||||
@@ -397,21 +419,21 @@ const civility = computed<number | null>({
|
|||||||
},
|
},
|
||||||
set: (value: number | null) => {
|
set: (value: number | null) => {
|
||||||
thirdParty.value.civility =
|
thirdParty.value.civility =
|
||||||
value !== null ? {id: value, type: "chill_main_civility"} : null;
|
value !== null ? { id: value, type: "chill_main_civility" } : null;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const civilities = ref<Civility[]>([])
|
const civilities = ref<Civility[]>([]);
|
||||||
|
|
||||||
const addAddress = reactive({
|
const addAddress = reactive({
|
||||||
options: {
|
options: {
|
||||||
openPanesInModal: true,
|
openPanesInModal: true,
|
||||||
onlyButton: false,
|
onlyButton: false,
|
||||||
button: {size: 'btn-sm'},
|
button: { size: "btn-sm" },
|
||||||
title: {create: 'add_an_address_title', edit: 'edit_address'},
|
title: { create: "add_an_address_title", edit: "edit_address" },
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
const addAddressRef = ref<any>(null)
|
const addAddressRef = ref<any>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We need a specific computed for the kind
|
* We need a specific computed for the kind
|
||||||
@@ -421,31 +443,34 @@ const kind = computed<ThirdPartyKind>({
|
|||||||
return thirdParty.value.kind;
|
return thirdParty.value.kind;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
thirdParty.value.kind = v
|
thirdParty.value.kind = v;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const context = computed(() => {
|
const context = computed(() => {
|
||||||
const ctx: any = {
|
const ctx: any = {
|
||||||
target: {name: props.type, id: props.id},
|
target: { name: props.type, id: props.id },
|
||||||
edit: false,
|
edit: false,
|
||||||
addressId: null as number | null,
|
addressId: null as number | null,
|
||||||
defaults: (window as any).addaddress,
|
defaults: (window as any).addaddress,
|
||||||
}
|
};
|
||||||
if (thirdParty.value.address) {
|
if (thirdParty.value.address) {
|
||||||
ctx.addressId = thirdParty.value.address.id
|
ctx.addressId = thirdParty.value.address.id;
|
||||||
ctx.edit = true
|
ctx.edit = true;
|
||||||
}
|
}
|
||||||
return ctx
|
return ctx;
|
||||||
})
|
});
|
||||||
|
|
||||||
const resolvedParent = computed<null|ThirdpartyCompany>(() => {
|
const resolvedParent = computed<null | ThirdpartyCompany>(() => {
|
||||||
if (null !== originalThirdParty.value && isThirdpartyChild(originalThirdParty.value)) {
|
if (
|
||||||
|
null !== originalThirdParty.value &&
|
||||||
|
isThirdpartyChild(originalThirdParty.value)
|
||||||
|
) {
|
||||||
return originalThirdParty.value.parent;
|
return originalThirdParty.value.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return props.parent ?? null;
|
return props.parent ?? null;
|
||||||
})
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the query items to display for suggestion
|
* Find the query items to display for suggestion
|
||||||
@@ -461,7 +486,10 @@ const queryItems = computed(() => {
|
|||||||
.trim()
|
.trim()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.split(" ");
|
.split(" ");
|
||||||
const lastNameWords = (thirdParty.value.name || "").trim().toLowerCase().split(" ");
|
const lastNameWords = (thirdParty.value.name || "")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.split(" ");
|
||||||
|
|
||||||
return words
|
return words
|
||||||
.filter((word) => !firstNameWords.includes(word.toLowerCase()))
|
.filter((word) => !firstNameWords.includes(word.toLowerCase()))
|
||||||
@@ -469,20 +497,19 @@ const queryItems = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function localizeString(str: any) {
|
function localizeString(str: any) {
|
||||||
return _localizeString(str)
|
return _localizeString(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getCivilities().then((cv) => {
|
getCivilities().then((cv) => {
|
||||||
civilities.value = cv;
|
civilities.value = cv;
|
||||||
});
|
});
|
||||||
if (props.action === "edit") {
|
if (props.action === "edit") {
|
||||||
loadData();
|
loadData();
|
||||||
} else if (props.action === 'addContact') {
|
} else if (props.action === "addContact") {
|
||||||
thirdParty.value.kind = 'child';
|
thirdParty.value.kind = "child";
|
||||||
thirdParty.value.address = null;
|
thirdParty.value.address = null;
|
||||||
thirdParty.value.parent = {id: props.parent.id, type: 'thirdparty'};
|
thirdParty.value.parent = { id: props.parent.id, type: "thirdparty" };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -495,38 +522,38 @@ async function loadData(): Promise<void> {
|
|||||||
|
|
||||||
function submitAddress(payload: { addressId: number }) {
|
function submitAddress(payload: { addressId: number }) {
|
||||||
console.log(payload);
|
console.log(payload);
|
||||||
thirdParty.value.address = {id: payload.addressId};
|
thirdParty.value.address = { id: payload.addressId };
|
||||||
}
|
}
|
||||||
|
|
||||||
function addQueryItem(field: 'name' | 'firstName', queryItem: string) {
|
function addQueryItem(field: "name" | "firstName", queryItem: string) {
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'name':
|
case "name":
|
||||||
if (thirdParty.value.name) {
|
if (thirdParty.value.name) {
|
||||||
thirdParty.value.name += ` ${queryItem}`
|
thirdParty.value.name += ` ${queryItem}`;
|
||||||
} else {
|
} else {
|
||||||
thirdParty.value.name = queryItem
|
thirdParty.value.name = queryItem;
|
||||||
}
|
}
|
||||||
break
|
break;
|
||||||
case 'firstName':
|
case "firstName":
|
||||||
thirdParty.value.firstname = queryItem
|
thirdParty.value.firstname = queryItem;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addQuery(query: string) {
|
function addQuery(query: string) {
|
||||||
thirdParty.value.name = query
|
thirdParty.value.name = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
const violations = useViolationList<WriteThirdPartyViolationMap>();
|
const violations = useViolationList<WriteThirdPartyViolationMap>();
|
||||||
|
|
||||||
async function postThirdParty(): Promise<Thirdparty> {
|
async function postThirdParty(): Promise<Thirdparty> {
|
||||||
try {
|
try {
|
||||||
if (props.action === 'edit' && props.id) {
|
if (props.action === "edit" && props.id) {
|
||||||
const tp = await patchThirdparty(props.id, thirdParty.value);
|
const tp = await patchThirdparty(props.id, thirdParty.value);
|
||||||
return Promise.resolve(tp);
|
return Promise.resolve(tp);
|
||||||
} else if (props.action === 'addContact' || props.action === 'create') {
|
} else if (props.action === "addContact" || props.action === "create") {
|
||||||
const tp = await createThirdParty(thirdParty.value);
|
const tp = await createThirdParty(thirdParty.value);
|
||||||
emit('onThirdPartyCreated', {thirdParty: tp});
|
emit("onThirdPartyCreated", { thirdParty: tp });
|
||||||
return Promise.resolve(tp);
|
return Promise.resolve(tp);
|
||||||
}
|
}
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
@@ -539,7 +566,6 @@ async function postThirdParty(): Promise<Thirdparty> {
|
|||||||
}
|
}
|
||||||
throw "'action' is not edit with and id, or addContact or create";
|
throw "'action' is not edit with and id, or addContact or create";
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -148,9 +148,8 @@ export type TicketHistoryLine =
|
|||||||
| CallerStateEvent;
|
| CallerStateEvent;
|
||||||
|
|
||||||
interface BaseTicket<
|
interface BaseTicket<
|
||||||
T extends
|
T extends "ticket_ticket:simple" | "ticket_ticket:extended" =
|
||||||
| "ticket_ticket:simple"
|
"ticket_ticket:simple",
|
||||||
| "ticket_ticket:extended" = "ticket_ticket:simple",
|
|
||||||
> {
|
> {
|
||||||
type_extended: T;
|
type_extended: T;
|
||||||
type: "ticket_ticket";
|
type: "ticket_ticket";
|
||||||
|
|||||||
Reference in New Issue
Block a user