@dejwcake/craftable 0.1.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +117 -3
  2. package/dist/buildMatchPatternFn-BV4I8r8j.js +63 -0
  3. package/dist/buildMatchPatternFn-T5KjFTBQ.cjs +1 -0
  4. package/dist/craftable.css +2 -0
  5. package/dist/cs-B5QMxFrl.js +682 -0
  6. package/dist/cs-MAoetkhe.cjs +1 -0
  7. package/dist/de-BlQ2ZKmc.js +526 -0
  8. package/dist/de-BoVLAn6U.cjs +1 -0
  9. package/dist/en-US-BLvEnhs4.js +443 -0
  10. package/dist/en-US-Dz8vkDZ_.cjs +1 -0
  11. package/dist/en-US-X9gX759i.cjs +1 -0
  12. package/dist/es-DBHDeXHI.cjs +1 -0
  13. package/dist/es-YEqfkBY2.js +437 -0
  14. package/dist/fr-B7MHC2AN.js +407 -0
  15. package/dist/fr-DLs3QoNB.cjs +1 -0
  16. package/dist/hu-BKZPI9jH.cjs +1 -0
  17. package/dist/hu-reoJgNxD.js +425 -0
  18. package/dist/index.cjs +1 -0
  19. package/dist/index.mjs +3866 -0
  20. package/dist/isSameWeek-CC6GX_zp.js +40 -0
  21. package/dist/isSameWeek-Mctj6Tdj.cjs +1 -0
  22. package/dist/pl-B5A0Rjp7.js +628 -0
  23. package/dist/pl-BMyrOO-Q.cjs +1 -0
  24. package/dist/sk-B7JF2MoV.cjs +1 -0
  25. package/dist/sk-Btro3W4S.js +602 -0
  26. package/package.json +68 -40
  27. package/scripts/publish-components.js +118 -0
  28. package/scss/_images.scss +1 -1
  29. package/scss/_variables.scss +13 -6
  30. package/scss/app.scss +4 -4
  31. package/scss/overrides/_alerts.scss +0 -2
  32. package/scss/overrides/_badges.scss +1 -17
  33. package/scss/overrides/_buttons.scss +64 -7
  34. package/scss/overrides/_cards.scss +4 -51
  35. package/scss/overrides/_checkboxes.scss +54 -59
  36. package/scss/overrides/_forms.scss +270 -176
  37. package/scss/overrides/_index.scss +18 -18
  38. package/scss/overrides/_keyframes.scss +6 -4
  39. package/scss/overrides/_layout.scss +24 -30
  40. package/scss/overrides/_media-wysiwyg.scss +9 -111
  41. package/scss/overrides/_modal.scss +0 -18
  42. package/scss/overrides/_multiselect.scss +63 -7
  43. package/scss/overrides/_nav.scss +55 -33
  44. package/scss/overrides/_notifications.scss +6 -1
  45. package/scss/overrides/_pagination.scss +3 -3
  46. package/scss/overrides/_sidebar.scss +84 -0
  47. package/scss/overrides/_tables.scss +52 -37
  48. package/scss/overrides/_text.scss +1 -3
  49. package/scss/overrides/_wysiwyg.scss +151 -48
  50. package/scss/styles/_auth.scss +32 -37
  51. package/scss/styles/_custom.scss +44 -1
  52. package/scss/styles/_index.scss +4 -4
  53. package/scss/styles/_legacy.scss +5 -81
  54. package/scss/styles/_others.scss +232 -337
  55. package/scss/vendor/_index.scss +5 -4
  56. package/src/auth/ActivationError.vue +23 -0
  57. package/src/auth/ActivationForm.vue +69 -0
  58. package/src/auth/ForgotPasswordForm.vue +74 -0
  59. package/src/auth/LoginForm.vue +107 -0
  60. package/src/auth/ResetPasswordForm.vue +122 -0
  61. package/src/components/ConfirmModal.vue +65 -0
  62. package/src/components/UserDetailTooltip.vue +88 -0
  63. package/src/components/form/CkeditorEditor.vue +205 -0
  64. package/src/components/form/FormCheckbox.vue +29 -0
  65. package/src/components/form/FormDatePicker.vue +52 -0
  66. package/src/components/form/FormEmail.vue +17 -0
  67. package/src/components/form/FormInput.vue +31 -0
  68. package/src/components/form/FormLocalizedInput.vue +47 -0
  69. package/src/components/form/FormLocalizedWysiwyg.vue +55 -0
  70. package/src/components/form/FormLocalizedWysiwygSimple.vue +55 -0
  71. package/src/components/form/FormMultiSelect.vue +36 -0
  72. package/src/components/form/FormPasswordConfirm.vue +49 -0
  73. package/src/components/form/FormSelect.vue +35 -0
  74. package/src/components/form/FormSubmit.vue +13 -0
  75. package/src/components/form/FormTextarea.vue +31 -0
  76. package/src/components/form/FormWysiwyg.vue +31 -0
  77. package/src/components/form/FormWysiwygSimple.vue +31 -0
  78. package/src/components/form/LocalizationBar.vue +90 -0
  79. package/src/components/form/MediaUpload.vue +317 -0
  80. package/src/components/form/TiptapEditor.vue +238 -0
  81. package/src/components/listing/BulkCheckboxHeader.vue +18 -0
  82. package/src/components/listing/BulkCheckboxRow.vue +21 -0
  83. package/src/components/listing/BulkOperationsBar.vue +41 -0
  84. package/src/components/listing/DeleteButton.vue +46 -0
  85. package/src/components/listing/EditButton.vue +17 -0
  86. package/src/components/listing/EmptyState.vue +25 -0
  87. package/src/components/listing/ListingHeader.vue +24 -0
  88. package/src/components/listing/Pagination.vue +158 -0
  89. package/src/components/listing/PerPage.vue +15 -0
  90. package/src/components/listing/PublishedAtColumn.vue +226 -0
  91. package/src/components/listing/Search.vue +81 -0
  92. package/src/components/listing/Sortable.vue +28 -0
  93. package/src/components/listing/ToggleSwitch.vue +47 -0
  94. package/src/composables/useAdmin.js +39 -0
  95. package/src/composables/useBaseAuth.js +81 -0
  96. package/src/composables/useBaseForm.js +265 -0
  97. package/src/composables/useBaseListing.js +316 -0
  98. package/src/composables/useResponsiveColumns.js +62 -0
  99. package/src/index.js +62 -0
  100. package/src/translation/TranslationListing.vue +230 -0
  101. package/src/translation/modals/TranslationEditModal.vue +86 -0
  102. package/src/translation/modals/TranslationExportModal.vue +74 -0
  103. package/src/translation/modals/TranslationImportModal.vue +255 -0
  104. package/src/ui/index.js +99 -0
  105. package/src/utils/ckeditorHelpers.js +36 -0
  106. package/src/utils/dateFnsLocale.js +24 -0
  107. package/src/utils/dateFormatters.js +30 -0
  108. package/src/utils/mediaProps.js +14 -0
  109. package/src/utils/notify.js +22 -0
  110. package/dist/admin/Admin.js +0 -42
  111. package/dist/auth/Form.js +0 -15
  112. package/dist/base-components/Form/BaseForm.js +0 -392
  113. package/dist/base-components/Form/BaseUpload.js +0 -188
  114. package/dist/base-components/Form/bootstrap.js +0 -21
  115. package/dist/base-components/Listing/BaseListing.js +0 -454
  116. package/dist/base-components/Listing/components/Pagination.js +0 -105
  117. package/dist/base-components/Listing/components/Sortable.js +0 -48
  118. package/dist/base-components/Listing/components/UserDetailTooltip.js +0 -55
  119. package/dist/index.js +0 -70
  120. package/dist/overrides/trumbowyg.edit-embed-template.js +0 -72
  121. package/dist/overrides/trumbowyg.reupload.js +0 -146
  122. package/dist/overrides/trumbowyg.template.js +0 -67
  123. package/dist/translation/Form.js +0 -15
  124. package/dist/translation/Listing.js +0 -283
  125. package/dist/ui/index.js +0 -33
  126. package/scss/overrides/_switches.scss +0 -25
@@ -1,4 +1,5 @@
1
- @use "~@coreui/icons/css/coreui-icons.min.css" as *;
2
- @use "~font-awesome/scss/font-awesome.scss" as *;
3
- @use "~simple-line-icons/scss/simple-line-icons.scss" as *;
4
- @use "~@coreui/coreui/scss/coreui" as *;
1
+ @import '@fortawesome/fontawesome-free/css/fontawesome.css';
2
+ @import '@fortawesome/fontawesome-free/css/solid.css';
3
+ @import '@fortawesome/fontawesome-free/css/regular.css';
4
+ @import '@coreui/coreui/scss/coreui';
5
+ @import 'vue-multiselect/dist/vue-multiselect.css';
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div class="card">
3
+ <div class="card-body">
4
+ <div class="auth-header">
5
+ <h1 class="auth-title">{{ translations.title }}</h1>
6
+ </div>
7
+ <div class="auth-body">
8
+ <div v-if="serverErrors.length" class="alert alert-danger">
9
+ <ul>
10
+ <li v-for="(error, index) in serverErrors" :key="index">{{ error }}</li>
11
+ </ul>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script setup>
19
+ defineProps({
20
+ translations: { type: Object, default: () => ({}) },
21
+ serverErrors: { type: Array, default: () => [] },
22
+ });
23
+ </script>
@@ -0,0 +1,69 @@
1
+ <template>
2
+ <div class="card">
3
+ <div class="card-body">
4
+ <form role="form" method="POST" :action="action" novalidate @submit.prevent="onSubmit">
5
+ <div class="auth-header">
6
+ <h1 class="auth-title">{{ translations.title }}</h1>
7
+ <p class="auth-subtitle">{{ translations.note }}</p>
8
+ </div>
9
+ <div class="auth-body">
10
+ <div v-if="successMessage" class="alert alert-success">
11
+ {{ successMessage }}
12
+ </div>
13
+ <div v-if="statusMessage && !successMessage" class="alert alert-success">
14
+ {{ statusMessage }}
15
+ </div>
16
+ <div v-if="serverErrors.length" class="alert alert-danger">
17
+ <ul>
18
+ <li v-for="(error, index) in serverErrors" :key="index">{{ error }}</li>
19
+ </ul>
20
+ </div>
21
+
22
+ <div class="mb-3">
23
+ <label for="email">{{ translations.email }}</label>
24
+ <div class="input-group input-group--custom">
25
+ <span class="input-group-text"><i class="fa fa-envelope"></i></span>
26
+ <input
27
+ id="email"
28
+ v-model="form.email"
29
+ type="text"
30
+ class="form-control"
31
+ :class="{ 'is-invalid': errors.email }"
32
+ name="email"
33
+ :placeholder="translations.email"
34
+ />
35
+ </div>
36
+ <div v-if="errors.email" class="invalid-feedback d-block form-text">
37
+ {{ errors.email }}
38
+ </div>
39
+ </div>
40
+
41
+ <div class="mb-3">
42
+ <button type="submit" class="btn btn-primary submit-btn" :disabled="submitting">
43
+ <i v-if="submitting" class="fa fa-spinner fa-spin"></i>
44
+ {{ translations.button }}
45
+ </button>
46
+ </div>
47
+ </div>
48
+ </form>
49
+ </div>
50
+ </div>
51
+ </template>
52
+
53
+ <script setup>
54
+ import { useBaseAuth } from '@dejwcake/craftable';
55
+
56
+ const props = defineProps({
57
+ action: { type: String, required: true },
58
+ translations: { type: Object, default: () => ({}) },
59
+ statusMessage: { type: String, default: '' },
60
+ serverErrors: { type: Array, default: () => [] },
61
+ });
62
+
63
+ const { form, errors, submitting, successMessage, onSubmit } = useBaseAuth(props, {
64
+ formDefaults: { email: '' },
65
+ validationSchema: {
66
+ email: 'required|email',
67
+ },
68
+ });
69
+ </script>
@@ -0,0 +1,74 @@
1
+ <template>
2
+ <div class="card">
3
+ <div class="card-body">
4
+ <form role="form" method="POST" :action="action" novalidate @submit.prevent="onSubmit">
5
+ <div class="auth-header">
6
+ <h1 class="auth-title">{{ translations.title }}</h1>
7
+ <p class="auth-subtitle">{{ translations.note }}</p>
8
+ </div>
9
+ <div class="auth-body">
10
+ <div v-if="successMessage" class="alert alert-success">
11
+ {{ successMessage }}
12
+ </div>
13
+ <div v-if="statusMessage && !successMessage" class="alert alert-success">
14
+ {{ statusMessage }}
15
+ </div>
16
+ <div v-if="serverErrors.length" class="alert alert-danger">
17
+ <ul>
18
+ <li v-for="(error, index) in serverErrors" :key="index">{{ error }}</li>
19
+ </ul>
20
+ </div>
21
+
22
+ <div class="mb-3">
23
+ <label for="email">{{ translations.email }}</label>
24
+ <div class="input-group input-group--custom">
25
+ <span class="input-group-text"><i class="fa fa-envelope"></i></span>
26
+ <input
27
+ id="email"
28
+ v-model="form.email"
29
+ type="text"
30
+ class="form-control"
31
+ :class="{ 'is-invalid': errors.email }"
32
+ name="email"
33
+ :placeholder="translations.email"
34
+ />
35
+ </div>
36
+ <div v-if="errors.email" class="invalid-feedback d-block form-text">
37
+ {{ errors.email }}
38
+ </div>
39
+ </div>
40
+
41
+ <div class="mb-3">
42
+ <button type="submit" class="btn btn-primary submit-btn" :disabled="submitting">
43
+ <i v-if="submitting" class="fa fa-spinner fa-spin"></i>
44
+ {{ translations.button }}
45
+ </button>
46
+ </div>
47
+
48
+ <div v-if="loginUrl" class="text-center">
49
+ <a :href="loginUrl" class="auth-ghost-link">{{ translations.backToLogin }}</a>
50
+ </div>
51
+ </div>
52
+ </form>
53
+ </div>
54
+ </div>
55
+ </template>
56
+
57
+ <script setup>
58
+ import { useBaseAuth } from '@dejwcake/craftable';
59
+
60
+ const props = defineProps({
61
+ action: { type: String, required: true },
62
+ loginUrl: { type: String, default: '' },
63
+ translations: { type: Object, default: () => ({}) },
64
+ statusMessage: { type: String, default: '' },
65
+ serverErrors: { type: Array, default: () => [] },
66
+ });
67
+
68
+ const { form, errors, submitting, successMessage, onSubmit } = useBaseAuth(props, {
69
+ formDefaults: { email: '' },
70
+ validationSchema: {
71
+ email: 'required|email',
72
+ },
73
+ });
74
+ </script>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <div class="card">
3
+ <div class="card-body">
4
+ <form role="form" method="POST" :action="action" novalidate @submit.prevent="onSubmit">
5
+ <div class="auth-header">
6
+ <h1 class="auth-title">{{ translations.title }}</h1>
7
+ <p class="auth-subtitle">{{ translations.signInText }}</p>
8
+ </div>
9
+ <div class="auth-body">
10
+ <div v-if="statusMessage" class="alert alert-success">
11
+ {{ statusMessage }}
12
+ </div>
13
+ <div v-if="serverErrors.length" class="alert alert-danger">
14
+ <ul>
15
+ <li v-for="(error, index) in serverErrors" :key="index">{{ error }}</li>
16
+ </ul>
17
+ </div>
18
+
19
+ <div class="mb-3">
20
+ <label for="email">{{ translations.email }}</label>
21
+ <div class="input-group input-group--custom">
22
+ <span class="input-group-text"><i class="fa fa-envelope"></i></span>
23
+ <input
24
+ id="email"
25
+ v-model="form.email"
26
+ type="text"
27
+ class="form-control"
28
+ :class="{ 'is-invalid': errors.email }"
29
+ name="email"
30
+ :placeholder="translations.email"
31
+ />
32
+ </div>
33
+ <div v-if="errors.email" class="invalid-feedback d-block form-text">
34
+ {{ errors.email }}
35
+ </div>
36
+ </div>
37
+
38
+ <div class="mb-3">
39
+ <label for="password">{{ translations.password }}</label>
40
+ <div class="input-group input-group--custom">
41
+ <span class="input-group-text"><i class="fa fa-lock"></i></span>
42
+ <input
43
+ id="password"
44
+ v-model="form.password"
45
+ type="password"
46
+ class="form-control"
47
+ :class="{ 'is-invalid': errors.password }"
48
+ name="password"
49
+ :placeholder="translations.password"
50
+ />
51
+ </div>
52
+ <div v-if="errors.password" class="invalid-feedback d-block form-text">
53
+ {{ errors.password }}
54
+ </div>
55
+ </div>
56
+
57
+ <div class="mb-3">
58
+ <input type="hidden" name="remember" value="1" />
59
+ <button type="submit" class="btn btn-primary submit-btn" :disabled="submitting">
60
+ <i v-if="submitting" class="fa fa-spinner fa-spin"></i>
61
+ {{ translations.button }}
62
+ </button>
63
+ </div>
64
+ <div class="mb-3 text-center">
65
+ <a :href="passwordResetUrl" class="auth-ghost-link forgot-link">{{
66
+ translations.forgotPassword
67
+ }}</a>
68
+ </div>
69
+ </div>
70
+ </form>
71
+ </div>
72
+ </div>
73
+ </template>
74
+
75
+ <script setup>
76
+ import { useBaseAuth } from '@dejwcake/craftable';
77
+
78
+ const props = defineProps({
79
+ action: { type: String, required: true },
80
+ redirectUrl: { type: String, default: '/admin' },
81
+ translations: { type: Object, default: () => ({}) },
82
+ passwordResetUrl: { type: String, default: '/admin/password-reset' },
83
+ statusMessage: { type: String, default: '' },
84
+ serverErrors: { type: Array, default: () => [] },
85
+ });
86
+
87
+ const { form, errors, submitting, onSubmit } = useBaseAuth(props, {
88
+ formDefaults: { email: '', password: '' },
89
+ validationSchema: {
90
+ email: 'required|email',
91
+ password: 'required',
92
+ },
93
+ onSuccess() {
94
+ window.location.replace(props.redirectUrl);
95
+ },
96
+ });
97
+ </script>
98
+
99
+ <style scoped>
100
+ .forgot-link {
101
+ text-decoration: none;
102
+ }
103
+
104
+ .forgot-link:hover {
105
+ text-decoration: none;
106
+ }
107
+ </style>
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <div class="card">
3
+ <div class="card-body">
4
+ <form role="form" method="POST" :action="action" novalidate @submit.prevent="onSubmit">
5
+ <div class="auth-header">
6
+ <h1 class="auth-title">{{ translations.title }}</h1>
7
+ <p class="auth-subtitle">{{ translations.note }}</p>
8
+ </div>
9
+ <div class="auth-body">
10
+ <div v-if="statusMessage" class="alert alert-success">
11
+ {{ statusMessage }}
12
+ </div>
13
+ <div v-if="serverErrors.length" class="alert alert-danger">
14
+ <ul>
15
+ <li v-for="(error, index) in serverErrors" :key="index">{{ error }}</li>
16
+ </ul>
17
+ </div>
18
+
19
+ <div class="mb-3">
20
+ <label for="email">{{ translations.email }}</label>
21
+ <div class="input-group input-group--custom">
22
+ <span class="input-group-text"><i class="fa fa-envelope"></i></span>
23
+ <input
24
+ id="email"
25
+ v-model="form.email"
26
+ type="text"
27
+ class="form-control"
28
+ :class="{ 'is-invalid': errors.email }"
29
+ name="email"
30
+ :placeholder="translations.email"
31
+ />
32
+ </div>
33
+ <div v-if="errors.email" class="invalid-feedback d-block form-text">
34
+ {{ errors.email }}
35
+ </div>
36
+ </div>
37
+
38
+ <div class="mb-3">
39
+ <label for="password">{{ translations.password }}</label>
40
+ <div class="input-group input-group--custom">
41
+ <span class="input-group-text"><i class="fa fa-lock"></i></span>
42
+ <input
43
+ id="password"
44
+ v-model="form.password"
45
+ type="password"
46
+ class="form-control"
47
+ :class="{ 'is-invalid': errors.password }"
48
+ name="password"
49
+ :placeholder="translations.password"
50
+ />
51
+ </div>
52
+ <div v-if="errors.password" class="invalid-feedback d-block form-text">
53
+ {{ errors.password }}
54
+ </div>
55
+ </div>
56
+
57
+ <div class="mb-3">
58
+ <label for="password_confirmation">{{ translations.passwordConfirm }}</label>
59
+ <div class="input-group input-group--custom">
60
+ <span class="input-group-text"><i class="fa fa-lock"></i></span>
61
+ <input
62
+ id="password_confirmation"
63
+ v-model="form.password_confirmation"
64
+ type="password"
65
+ class="form-control"
66
+ :class="{ 'is-invalid': errors.password_confirmation }"
67
+ name="password_confirmation"
68
+ :placeholder="translations.passwordConfirm"
69
+ />
70
+ </div>
71
+ <div v-if="errors.password_confirmation" class="invalid-feedback d-block form-text">
72
+ {{ errors.password_confirmation }}
73
+ </div>
74
+ </div>
75
+
76
+ <div class="mb-3">
77
+ <button type="submit" class="btn btn-primary submit-btn" :disabled="submitting">
78
+ <i v-if="submitting" class="fa fa-spinner fa-spin"></i>
79
+ {{ translations.button }}
80
+ </button>
81
+ </div>
82
+
83
+ <div v-if="loginUrl" class="text-center">
84
+ <a :href="loginUrl" class="auth-ghost-link">{{ translations.backToLogin }}</a>
85
+ </div>
86
+ </div>
87
+ </form>
88
+ </div>
89
+ </div>
90
+ </template>
91
+
92
+ <script setup>
93
+ import { useBaseAuth } from '@dejwcake/craftable';
94
+
95
+ const props = defineProps({
96
+ action: { type: String, required: true },
97
+ loginUrl: { type: String, default: '' },
98
+ translations: { type: Object, default: () => ({}) },
99
+ statusMessage: { type: String, default: '' },
100
+ serverErrors: { type: Array, default: () => [] },
101
+ email: { type: String, default: '' },
102
+ token: { type: String, required: true },
103
+ redirectUrl: { type: String, default: '/admin' },
104
+ });
105
+
106
+ const { form, errors, submitting, onSubmit } = useBaseAuth(props, {
107
+ formDefaults: {
108
+ email: props.email,
109
+ password: '',
110
+ password_confirmation: '',
111
+ token: props.token,
112
+ },
113
+ validationSchema: {
114
+ email: 'required|email',
115
+ password: 'required|min:7',
116
+ password_confirmation: 'required|confirmed:@password',
117
+ },
118
+ onSuccess(data) {
119
+ window.location.replace(data.redirect || props.redirectUrl);
120
+ },
121
+ });
122
+ </script>
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <Teleport to="body">
3
+ <div v-if="show" class="modal-backdrop fade show" @click="$emit('cancel')"></div>
4
+ <div v-if="show" class="modal fade show d-block" tabindex="-1" role="dialog" @click.self="$emit('cancel')">
5
+ <div class="modal-dialog modal-dialog-centered" role="document">
6
+ <div class="modal-content">
7
+ <div class="modal-header">
8
+ <h5 class="modal-title">
9
+ <i :class="iconClass" class="me-2"></i>
10
+ {{ translations.confirm_title }}
11
+ </h5>
12
+ <button type="button" class="btn-close" @click="$emit('cancel')"></button>
13
+ </div>
14
+ <div class="modal-body">
15
+ <p>{{ translations.confirm_text }}</p>
16
+ </div>
17
+ <div class="modal-footer">
18
+ <button type="button" class="btn btn-secondary" @click="$emit('cancel')">
19
+ {{ translations.cancel_btn }}
20
+ </button>
21
+ <button type="button" :class="btnClass" @click="$emit('confirm')">
22
+ {{ translations.confirm_btn }}
23
+ </button>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ </Teleport>
29
+ </template>
30
+
31
+ <script setup>
32
+ import { computed } from 'vue';
33
+
34
+ const props = defineProps({
35
+ show: { type: Boolean, default: false },
36
+ variant: {
37
+ type: String,
38
+ default: 'danger',
39
+ validator: (v) => ['danger', 'success', 'primary', 'warning'].includes(v),
40
+ },
41
+ translations: {
42
+ type: Object,
43
+ default: () => ({
44
+ confirm_title: 'Warning!',
45
+ confirm_text: 'Are you sure?',
46
+ confirm_btn: 'Yes, confirm',
47
+ cancel_btn: 'Cancel',
48
+ }),
49
+ },
50
+ });
51
+
52
+ const btnClass = computed(() => {
53
+ const base = `btn btn-${props.variant}`;
54
+ return ['success', 'primary'].includes(props.variant) ? `${base} text-white` : base;
55
+ });
56
+
57
+ const iconClass = computed(() => {
58
+ if (props.variant === 'danger') return 'fa fa-triangle-exclamation text-danger';
59
+ if (props.variant === 'warning') return 'fa fa-triangle-exclamation text-warning';
60
+ if (props.variant === 'success') return 'fa fa-circle-check text-success';
61
+ return 'fa fa-circle-question text-primary';
62
+ });
63
+
64
+ defineEmits(['confirm', 'cancel']);
65
+ </script>
@@ -0,0 +1,88 @@
1
+ <template>
2
+ <div class="user-detail-tooltip d-inline-flex align-items-center">
3
+ <label v-if="label" class="col-form-label text-body-secondary me-2 mb-0">{{ label }} :</label>
4
+ <Popper arrow click>
5
+ <div class="d-inline-flex align-items-center cursor-pointer">
6
+ <img
7
+ v-if="user.avatar_thumb_url"
8
+ :src="user.avatar_thumb_url"
9
+ class="avatar-photo"
10
+ :alt="user.full_name"
11
+ />
12
+ <div v-else class="avatar-initials">
13
+ {{ abbr }}
14
+ </div>
15
+
16
+ <div v-if="options.showFullNameLabel" class="avatar-trigger-text">
17
+ <span class="avatar-full-name">{{ user.full_name }}</span>
18
+ <span v-if="datetime" class="d-block user-info-span">{{ datetime }}</span>
19
+ </div>
20
+ </div>
21
+
22
+ <template #content>
23
+ <div class="user-detail-popper d-flex align-items-center">
24
+ <div class="user-avatar flex-shrink-0">
25
+ <img
26
+ v-if="user.avatar_thumb_url"
27
+ :src="user.avatar_thumb_url"
28
+ class="avatar-photo"
29
+ :alt="user.full_name"
30
+ />
31
+ <div v-else class="avatar-initials">
32
+ {{ abbr }}
33
+ </div>
34
+ </div>
35
+
36
+ <div class="user-info ms-3">
37
+ <h3>
38
+ {{ user.full_name }}
39
+ <small v-if="userText">
40
+ | <strong class="text-uppercase">{{ userText }}</strong>
41
+ </small>
42
+ </h3>
43
+ <a v-if="user.email" :href="'mailto:' + user.email">{{ user.email }}</a>
44
+ <p v-if="datetimeText">{{ datetimeText }}</p>
45
+ </div>
46
+ </div>
47
+ </template>
48
+ </Popper>
49
+ </div>
50
+ </template>
51
+
52
+ <script setup>
53
+ import { computed } from 'vue';
54
+ import Popper from 'vue3-popper';
55
+
56
+ const props = defineProps({
57
+ user: {
58
+ type: Object,
59
+ required: true,
60
+ },
61
+ userText: {
62
+ type: String,
63
+ default: '',
64
+ },
65
+ label: {
66
+ type: String,
67
+ default: '',
68
+ },
69
+ datetimeText: {
70
+ type: String,
71
+ default: '',
72
+ },
73
+ options: {
74
+ type: Object,
75
+ default: () => ({
76
+ showFullNameLabel: true,
77
+ }),
78
+ },
79
+ datetime: {
80
+ type: String,
81
+ default: '',
82
+ },
83
+ });
84
+
85
+ const abbr = computed(() => {
86
+ return `${props.user.first_name.slice(0, 1)}${props.user.last_name.slice(0, 1)}`;
87
+ });
88
+ </script>