@concretecms/bedrock 1.3.6 → 1.4.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 (108) hide show
  1. package/.eslintrc.yml +2 -0
  2. package/assets/account/js/frontend/components/AvatarCropper.vue +159 -0
  3. package/assets/account/js/frontend.js +1 -1
  4. package/assets/account/scss/frontend/_frontend.scss +2 -0
  5. package/assets/account/scss/frontend/avatar/_avatar-cropper.scss +82 -0
  6. package/assets/account/scss/frontend/avatar/_avatar.scss +6 -0
  7. package/assets/bedrock/scss/_frontend.scss +0 -1
  8. package/assets/calendar/js/backend/duration.js +13 -13
  9. package/assets/calendar/js/vendor/fullcalendar.js +1 -0
  10. package/assets/cms/components/Announcement/Action/ExternalLinkAction.vue +25 -0
  11. package/assets/cms/components/Announcement/Action/GuideAction.vue +36 -0
  12. package/assets/cms/components/Announcement/Action/VideoAction.vue +31 -0
  13. package/assets/cms/components/Announcement/Broadcast.vue +63 -0
  14. package/assets/cms/components/Announcement/Button/ExternalLinkButton.vue +26 -0
  15. package/assets/cms/components/Announcement/Header/Header.vue +33 -0
  16. package/assets/cms/components/Announcement/Item/Item.vue +50 -0
  17. package/assets/cms/components/Announcement/Modal/Modal.vue +77 -0
  18. package/assets/cms/components/Announcement/Slide/CollectSiteInformationSlide.vue +61 -0
  19. package/assets/cms/components/Announcement/Slide/FeatureSlide.vue +81 -0
  20. package/assets/cms/components/Announcement/Slide/WelcomeSlide.vue +87 -0
  21. package/assets/cms/components/Help/Modal.vue +48 -0
  22. package/assets/cms/components/Image/ThumbnailEditor.vue +117 -0
  23. package/assets/cms/components/RunningProcessList.vue +6 -1
  24. package/assets/cms/components/customizer/FontFamilyPageCustomizerWidget.vue +27 -7
  25. package/assets/cms/components/file-manager/Chooser/FileManager.vue +0 -1
  26. package/assets/cms/components/file-manager/Chooser/FileUpload.vue +5 -0
  27. package/assets/cms/components/file-manager/Chooser/FolderBookmark.vue +0 -1
  28. package/assets/cms/components/file-manager/Chooser.vue +6 -1
  29. package/assets/cms/components/file-manager/Uploader/UploadFromComputer.vue +49 -9
  30. package/assets/cms/components/file-manager/Uploader.vue +7 -0
  31. package/assets/cms/components/form/ConcreteAjaxSelect.vue +173 -0
  32. package/assets/cms/components/form/ConcreteExpressEntrySelect.vue +74 -0
  33. package/assets/cms/components/form/ConcreteFileDirectoryInput.vue +28 -26
  34. package/assets/cms/components/form/ConcreteFileInput.vue +17 -5
  35. package/assets/cms/components/form/ConcreteGroupInput.vue +134 -0
  36. package/assets/cms/components/form/ConcreteLocaleSelect.vue +58 -0
  37. package/assets/cms/components/form/ConcreteOptionSelect.vue +92 -0
  38. package/assets/cms/components/form/ConcretePageSelect.vue +67 -0
  39. package/assets/cms/components/form/ConcreteSelect.vue +75 -0
  40. package/assets/cms/components/form/ConcreteThemeColorInput.vue +19 -14
  41. package/assets/cms/components/form/ConcreteUserInput.vue +69 -29
  42. package/assets/cms/components/form/ConcreteUserSelect.vue +126 -0
  43. package/assets/cms/components/form/IconSelector.vue +14 -5
  44. package/assets/cms/components/form/PasswordInput.vue +141 -24
  45. package/assets/cms/components/groups/Chooser.vue +6 -5
  46. package/assets/cms/components/index.js +24 -0
  47. package/assets/cms/components/toolbar/ConcreteToolbarSiteList.vue +62 -0
  48. package/assets/cms/components/user/Chooser/Search.vue +5 -0
  49. package/assets/cms/components/user/Chooser/Users.vue +6 -2
  50. package/assets/cms/components/user/Chooser.vue +9 -3
  51. package/assets/cms/js/ajax-request/base.js +13 -4
  52. package/assets/cms/js/alert.js +2 -1
  53. package/assets/cms/js/base.js +3 -10
  54. package/assets/cms/js/edit-mode/area.js +0 -35
  55. package/assets/cms/js/edit-mode/block.js +27 -0
  56. package/assets/cms/js/edit-mode/containerblock.js +33 -3
  57. package/assets/cms/js/edit-mode/editmode.js +12 -0
  58. package/assets/cms/js/edit-mode/layout.js +56 -0
  59. package/assets/cms/js/edit-mode/style-customizer/style-customizer.js +0 -1
  60. package/assets/cms/js/file-manager/uploader.js +64 -209
  61. package/assets/cms/js/help/help.js +11 -8
  62. package/assets/cms/js/in-context-menu.js +5 -0
  63. package/assets/cms/js/jquery-vue.js +22 -0
  64. package/assets/cms/js/legacy-dialog.js +74 -65
  65. package/assets/cms/js/modal.js +73 -0
  66. package/assets/cms/js/panels.js +8 -0
  67. package/assets/cms/js/search/base.js +0 -18
  68. package/assets/cms/js/search/field-selector.js +6 -14
  69. package/assets/cms/js/select-combo-box.js +2 -0
  70. package/assets/cms/js/sitemap/sitemap-selector.js +2 -2
  71. package/assets/cms/js/sitemap/sitemap.js +15 -20
  72. package/assets/cms/js/toolbar.js +25 -2
  73. package/assets/cms/js/tree.js +7 -7
  74. package/assets/cms/js/users/group-manager.js +55 -0
  75. package/assets/cms/js/users/user-manager.js +2 -1
  76. package/assets/cms/js/users.js +1 -0
  77. package/assets/cms/js/vue/Manager.js +6 -3
  78. package/assets/cms/scss/_base.scss +2 -8
  79. package/assets/cms/scss/_cards.scss +7 -0
  80. package/assets/cms/scss/_file-manager.scss +1 -0
  81. package/assets/cms/scss/_file-uploader.scss +13 -3
  82. package/assets/cms/scss/_help.scss +11 -2
  83. package/assets/cms/scss/_item-selector.scss +10 -0
  84. package/assets/cms/scss/_layouts.scss +16 -0
  85. package/assets/cms/scss/_page-areas.scss +517 -245
  86. package/assets/cms/scss/_popover.scss +5 -0
  87. package/assets/cms/scss/_select-combo-box.scss +18 -0
  88. package/assets/cms/scss/_toolbar.scss +5 -14
  89. package/assets/cms/scss/_transitions.scss +13 -0
  90. package/assets/cms/scss/_variables.scss +18 -7
  91. package/assets/cms/scss/bootstrap/_reboot-tags.scss +17 -32
  92. package/assets/cms/scss/bootstrap/_reboot.scss +17 -7
  93. package/assets/cms/scss/bootstrap/_root-modified.scss +41 -20
  94. package/assets/cms/scss/file-manager/_thumbnail-image-editor.scss +45 -0
  95. package/assets/cms/scss/panels/_help.scss +0 -10
  96. package/assets/staging/scss/frontend/_frontend.scss +12 -0
  97. package/assets/staging/scss/frontend.scss +4 -0
  98. package/package.json +9 -9
  99. package/assets/account/js/frontend/components/Avatar/Avatar.js +0 -270
  100. package/assets/account/js/frontend/components/Avatar/Avatar.scss +0 -17
  101. package/assets/account/js/frontend/components/Avatar/Avatar.vue +0 -18
  102. package/assets/account/js/frontend/components/Avatar/Cropper.js +0 -202
  103. package/assets/account/js/frontend/components/Avatar/Cropper.scss +0 -136
  104. package/assets/account/js/frontend/components/Avatar/Cropper.vue +0 -40
  105. package/assets/bedrock/scss/_theme-grid.scss +0 -7
  106. package/assets/cms/js/edit-mode/style-customizer/inline-toolbar.js +0 -279
  107. package/assets/cms/js/modifiable-ajax-bootstrap-select.js +0 -78
  108. package/assets/cms/js/modifiable-bootstrap-select.js +0 -112
@@ -0,0 +1,134 @@
1
+ <template>
2
+ <div class="ccm-item-selector-group">
3
+ <input type="hidden" :name="inputName" :value="selectedGroup ? selectedGroup.gID : ''" v-if="inputName !== ''" />
4
+
5
+ <div v-if="isLoading">
6
+ <div class="btn-group">
7
+ <div class="btn btn-secondary"><svg class="ccm-loader-dots"><use xlink:href="#icon-loader-circles" /></svg></div>
8
+ <button type="button" @click="reset" :disabled="readonly" class="ccm-item-selector-reset btn btn-secondary">
9
+ <i class="fa fa-times-circle"></i>
10
+ </button>
11
+ </div>
12
+ </div>
13
+
14
+ <div v-else-if="selectedGroup === null" class="ccm-item-selector-choose">
15
+ <button type="button" @click="openChooser" :disabled="readonly" class="btn btn-secondary">
16
+ {{chooseText}}
17
+ </button>
18
+ </div>
19
+
20
+ <div v-else class="ccm-item-selector-loaded">
21
+ <div class="btn-group">
22
+ <div class="btn btn-secondary" :class="{disabled: readonly}" @click="openChooser">
23
+ <span class="ccm-item-selector-title" v-bind:title="`ID: ${selectedGroup.gID}`">{{selectedGroup.gDisplayName}}</span>
24
+ </div>
25
+ <button type="button" @click="reset" :disabled="readonly" class="ccm-item-selector-reset btn btn-secondary">
26
+ <i class="fa fa-times-circle"></i>
27
+ </button>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </template>
32
+
33
+ <script>
34
+
35
+ export default {
36
+ data() {
37
+ return {
38
+ isLoadingGroupId: 0 /* integer */,
39
+ selectedGroup: null, /* json object */
40
+ mounted: false
41
+ }
42
+ },
43
+ computed: {
44
+ isLoading() {
45
+ return this.isLoadingGroupId !== 0
46
+ }
47
+ },
48
+ props: {
49
+ inputName: {
50
+ type: String,
51
+ default: ''
52
+ },
53
+ groupId: {
54
+ type: Number,
55
+ default: 0
56
+ },
57
+ chooseText: {
58
+ type: String,
59
+ default: 'Choose a Group'
60
+ },
61
+ readonly: {
62
+ type: Boolean,
63
+ default: false
64
+ }
65
+ },
66
+ watch: {
67
+ groupId: {
68
+ immediate: true,
69
+ handler(value) {
70
+ if (this.mounted) {
71
+ this.loadGroup()
72
+ }
73
+ }
74
+ }
75
+ },
76
+ beforeMount() {
77
+ this.mounted = true
78
+ },
79
+ mounted() {
80
+ this.loadGroup(true)
81
+ },
82
+ beforeUnmount() {
83
+ this.mounted = false
84
+ },
85
+ methods: {
86
+ setSelectedGroup(group, triggerChange) {
87
+ const currentlySelectedGroupID = parseInt(this.selectedGroup?.gID) || 0
88
+ const newlySelectedGroupID = parseInt(group?.gID) || 0
89
+ this.isLoadingGroupId = 0
90
+ this.selectedGroup = group
91
+ if (triggerChange && currentlySelectedGroupID !== newlySelectedGroupID) {
92
+ this.$emit('change', this.selectedGroup)
93
+ }
94
+ },
95
+ openChooser: function() {
96
+ window.ConcreteUserGroupManager.launchDialog((group) => {
97
+ this.setSelectedGroup(group, true)
98
+ })
99
+ },
100
+ loadGroup(initial) {
101
+ const wantedGroupId = Math.max(parseInt(this.groupId) || 0)
102
+ if (wantedGroupId === 0) {
103
+ this.setSelectedGroup(null, !initial)
104
+ return
105
+ }
106
+ const currentGroupId = parseInt(this.selectedGroup?.gID) || 0
107
+ if (wantedGroupId === currentGroupId) {
108
+ this.isLoadingGroupId = 0
109
+ return
110
+ }
111
+ this.isLoadingGroupId = wantedGroupId
112
+ window.ConcreteUserGroupManager.getGroupDetails(
113
+ wantedGroupId,
114
+ (r) => {
115
+ if (this.isLoadingGroupId !== wantedGroupId) {
116
+ return
117
+ }
118
+ this.setSelectedGroup(r.groups[0], !initial)
119
+ },
120
+ (r) => {
121
+ if (this.isLoadingGroupId !== wantedGroupId) {
122
+ return
123
+ }
124
+ this.setSelectedGroup(null, !initial)
125
+ window.ConcreteAlert.dialog(ccmi18n.error, ConcreteAjaxRequest.renderJsonError(r, true))
126
+ }
127
+ )
128
+ },
129
+ reset() {
130
+ this.setSelectedGroup(null, true)
131
+ }
132
+ }
133
+ }
134
+ </script>
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <input :name="name" v-model="selectedValue" />
3
+ </template>
4
+
5
+ <script>
6
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
7
+ /* globals TomSelect, WebFont */
8
+ export default {
9
+ data() {
10
+ return {
11
+ selectedValue: this.value
12
+ }
13
+ },
14
+ props: {
15
+ value: {
16
+ },
17
+ name: {
18
+ type: String,
19
+ required: true
20
+ },
21
+ selectedLocale: {
22
+ required: false
23
+ },
24
+ locales: {
25
+ type: Array,
26
+ required: true
27
+ }
28
+ },
29
+ watch: {
30
+ },
31
+ mounted() {
32
+ var config = {}
33
+ config.maxOptions = null
34
+ config.maxItems = 1
35
+ config.items = [this.selectedLocale]
36
+ config.options = this.locales
37
+ config.valueField = 'id'
38
+ config.render = {
39
+ option: function (data, escape) {
40
+ return `<div><img class="me-2" src="${data.flag}">${data.language.text}</div>`
41
+ },
42
+ item: function (item, escape) {
43
+ return `<div><img class="me-2" src="${item.flag}">${item.language.text}</div>`
44
+ }
45
+ }
46
+ this.$nextTick(() => {
47
+ const select = new TomSelect(this.$el, config)
48
+ select.on('change', (option) => {
49
+ this.selectedValue = option
50
+ })
51
+ select.sync()
52
+ })
53
+ },
54
+ methods: {
55
+
56
+ }
57
+ }
58
+ </script>
@@ -0,0 +1,92 @@
1
+ <template>
2
+ <concrete-ajax-select
3
+ :name="inputName"
4
+ :access-token="accessToken"
5
+ :data-source-url="dataSourceUrl"
6
+ :selected-options-url="selectedOptionsUrl"
7
+ :value="value"
8
+ @change="updateSelected"
9
+ :form-data="formData"
10
+ :max-items="maxItems"
11
+ :remove-button="maxItems != 1"
12
+ :allow-create="true"
13
+ >
14
+ </concrete-ajax-select>
15
+ </template>
16
+
17
+ <script>
18
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
19
+ /* globals TomSelect */
20
+ import ConcreteAjaxSelect from './ConcreteAjaxSelect'
21
+ export default {
22
+ components: { ConcreteAjaxSelect },
23
+ prop: ['value'],
24
+ model: {
25
+ prop: 'value',
26
+ event: 'change'
27
+ },
28
+ props: {
29
+ dataSourceUrl: {
30
+ type: String,
31
+ required: true
32
+ },
33
+ selectedOptionsUrl: {
34
+ type: String,
35
+ required: true
36
+ },
37
+ allowMultipleValues: {
38
+ type: Boolean,
39
+ default: false
40
+ },
41
+ attributeKeyId: {
42
+ type: [String, Number],
43
+ required: true
44
+ },
45
+ accessToken: {
46
+ type: String,
47
+ required: true
48
+ },
49
+ inputName: {
50
+ type: String
51
+ },
52
+ value: {
53
+ type: Array,
54
+ required: false
55
+ }
56
+ },
57
+ computed: {
58
+ maxItems() {
59
+ if (this.allowMultipleValues) {
60
+ return null
61
+ } else {
62
+ return 1
63
+ }
64
+ },
65
+ formData() {
66
+ return {
67
+ akID: this.attributeKeyId,
68
+ optionId: this.value
69
+ }
70
+ }
71
+ },
72
+ data() {
73
+ return {
74
+ selectedValue: null
75
+ }
76
+ },
77
+ watch: {
78
+ entryId: {
79
+ immediate: true,
80
+ handler: function(value) {
81
+ this.selectedValue = value
82
+ }
83
+ }
84
+ },
85
+ methods: {
86
+ updateSelected(value) {
87
+ this.selectedValue = value
88
+ this.$emit('change', this.selectedValue)
89
+ }
90
+ }
91
+ }
92
+ </script>
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <concrete-ajax-select
3
+ :name="inputName"
4
+ :access-token="accessToken"
5
+ :data-source-url="dataSourceUrl"
6
+ :selected-options-url="selectedOptionsUrl"
7
+ :value="pageId"
8
+ @change="updateSelected"
9
+ :form-data="formData"
10
+ >
11
+ </concrete-ajax-select>
12
+ </template>
13
+
14
+ <script>
15
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
16
+ /* globals TomSelect */
17
+ import ConcreteAjaxSelect from './ConcreteAjaxSelect'
18
+ export default {
19
+ components: { ConcreteAjaxSelect },
20
+ prop: ['pageId'],
21
+ model: {
22
+ prop: 'pageId',
23
+ event: 'change'
24
+ },
25
+ props: {
26
+ accessToken: {
27
+ type: String,
28
+ required: true
29
+ },
30
+ inputName: {
31
+ type: String
32
+ },
33
+ pageId: {
34
+ type: [Number, String, Array],
35
+ required: false
36
+ }
37
+ },
38
+ computed: {
39
+ formData() {
40
+ return {
41
+ pageId: this.pageId
42
+ }
43
+ }
44
+ },
45
+ data() {
46
+ return {
47
+ dataSourceUrl: CCM_DISPATCHER_FILENAME + '/ccm/system/page/autocomplete',
48
+ selectedOptionsUrl: CCM_DISPATCHER_FILENAME + '/ccm/system/page/autocomplete/get_selected',
49
+ selectedPageId: null
50
+ }
51
+ },
52
+ watch: {
53
+ pageId: {
54
+ immediate: true,
55
+ handler: function(pageId) {
56
+ this.selectedPageId = pageId
57
+ }
58
+ }
59
+ },
60
+ methods: {
61
+ updateSelected(value) {
62
+ this.selectedPageId = value
63
+ this.$emit('change', this.selectedPageId)
64
+ }
65
+ }
66
+ }
67
+ </script>
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <select :name="name" :multiple="multiple" v-model="selectedValue">
3
+ <template v-if="hasOptGroups">
4
+ <optgroup v-for="(optgroupOptions, optgroupLabel) in options" :label="optgroupLabel">
5
+ <option v-for="(label, value) in optgroupOptions" :value="value">
6
+ {{label}}
7
+ </option>
8
+ </optgroup>
9
+ </template>
10
+ <template v-else>
11
+ <option v-for="(label, value) in options" :value="value" :key="value">
12
+ {{label}}
13
+ </option>
14
+ </template>
15
+ </select>
16
+ </template>
17
+
18
+ <script>
19
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
20
+ /* globals TomSelect */
21
+ export default {
22
+ data() {
23
+ return {
24
+ selectedValue: this.value
25
+ }
26
+ },
27
+ props: {
28
+ name: {
29
+ type: String,
30
+ required: true
31
+ },
32
+ value: {
33
+ required: false
34
+ },
35
+ multiple: {
36
+ type: Boolean,
37
+ required: false,
38
+ default: false
39
+ },
40
+ options: {
41
+ type: Object,
42
+ required: true
43
+ }
44
+ },
45
+ watch: {
46
+
47
+ },
48
+ mounted() {
49
+ var options = {}
50
+ options.maxOptions = null
51
+ if (this.multiple) {
52
+ options.plugins = {
53
+ remove_button: {
54
+
55
+ }
56
+ }
57
+ }
58
+ this.$nextTick(() => {
59
+ new TomSelect(this.$el, options)
60
+ })
61
+ },
62
+ computed: {
63
+ hasOptGroups: function() {
64
+ if (this.options && Object.keys(this.options).length > 0) {
65
+ if (typeof (this.options[Object.keys(this.options)[0]]) === 'object') {
66
+ return true
67
+ }
68
+ }
69
+ return false
70
+ }
71
+ },
72
+ methods: {
73
+ }
74
+ }
75
+ </script>
@@ -1,16 +1,18 @@
1
1
  <template>
2
- <div class="mb-3 ccm-context-theme">
3
- <select :name="inputName" data-select="theme-colors" data-width="100%">
4
- <option v-for="color in colorCollection.colors" :selected="selectedColor == color.variable" :data-content="dataContentAttribute(color)" :value="color.variable">{{ color.name }}</option>
2
+ <div class="ccm-context-theme">
3
+ <select :name="inputName" v-model="selectedColor">
4
+ <option v-for="color in colorCollection.colors" :selected="selectedColor == color.variable" :value="color.variable">{{ color.name }}</option>
5
5
  </select>
6
6
  </div>
7
7
  </template>
8
8
 
9
9
  <script>
10
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
11
+ /* globals TomSelect */
10
12
  export default {
11
13
  data() {
12
14
  return {
13
- selectedColor: ''
15
+ selectedColor: this.color
14
16
  }
15
17
  },
16
18
  props: {
@@ -35,18 +37,21 @@ export default {
35
37
  }
36
38
  },
37
39
  mounted() {
38
- if (this.color) {
39
- this.selectedColor = this.color
40
- }
41
-
42
- var $el = this.$el
43
- setTimeout(function() {
44
- $($el.querySelector('select[data-select=theme-colors]')).selectpicker()
45
- }, 5)
40
+ var my = this
41
+ new TomSelect(this.$el.querySelector('select'), {
42
+ render: {
43
+ option: function (data, escape) {
44
+ return my.dataContentAttribute(data)
45
+ },
46
+ item: function (item, escape) {
47
+ return my.dataContentAttribute(item)
48
+ }
49
+ }
50
+ })
46
51
  },
47
52
  methods: {
48
- dataContentAttribute: function(color) {
49
- return "<span style='background-color: var(--bs-" + color.variable + ")' class='btn me-2 p-2'></span> " + color.name
53
+ dataContentAttribute: function(item) {
54
+ return '<div><span style="background-color: var(--bs-' + item.value + ')" class="btn me-2 p-2"></span> ' + item.text + '</div>'
50
55
  }
51
56
  }
52
57
  }
@@ -1,29 +1,29 @@
1
1
  <template>
2
- <div class="ccm-item-selector-group">
3
- <input type="hidden" :name="inputName" :value="selectedUserID" />
4
-
5
- <div class="ccm-item-selector-choose" v-if="!selectedUser && !isLoading">
6
- <button type="button" @click="openChooser" class="btn btn-secondary">
7
- {{chooseText}}
8
- </button>
9
- </div>
2
+ <div :class="cssClasses">
3
+ <input type="hidden" :name="inputName" :value="selectedUserID" v-if="inputName !== ''" />
10
4
 
11
5
  <div v-if="isLoading">
12
6
  <div class="btn-group">
13
7
  <div class="btn btn-secondary"><svg class="ccm-loader-dots"><use xlink:href="#icon-loader-circles" /></svg></div>
14
- <button type="button" @click="reset" class="ccm-item-selector-reset btn btn-secondary">
8
+ <button type="button" @click="reset" :disabled="readonly" class="ccm-item-selector-reset btn btn-secondary">
15
9
  <i class="fa fa-times-circle"></i>
16
10
  </button>
17
11
  </div>
18
12
  </div>
19
13
 
20
- <div class="ccm-item-selector-loaded" v-if="selectedUser !== null">
14
+ <div class="ccm-item-selector-choose" v-else-if="!selectedUser">
15
+ <button type="button" @click="openChooser" :disabled="readonly" class="btn btn-secondary">
16
+ {{chooseText}}
17
+ </button>
18
+ </div>
19
+
20
+ <div class="ccm-item-selector-loaded" v-else="selectedUser !== null">
21
21
  <div class="btn-group">
22
- <div class="btn btn-secondary">
22
+ <div class="btn btn-secondary" :class="{disabled: readonly}">
23
23
  <span v-html="selectedUser.avatar"></span>
24
24
  <span class="ccm-item-selector-title">{{selectedUser.displayName}}</span>
25
25
  </div>
26
- <button type="button" @click="reset" class="ccm-item-selector-reset btn btn-secondary">
26
+ <button type="button" @click="reset" :disabled="readonly" class="ccm-item-selector-reset btn btn-secondary">
27
27
  <i class="fa fa-times-circle"></i>
28
28
  </button>
29
29
  </div>
@@ -35,24 +35,58 @@
35
35
  export default {
36
36
  data() {
37
37
  return {
38
- isLoading: false,
38
+ isLoadingUserID: 0 /* integer */,
39
39
  selectedUser: null /* json object */,
40
40
  selectedUserID: 0 /* integer */
41
41
  }
42
42
  },
43
+ computed: {
44
+ isLoading() {
45
+ return this.isLoadingUserID > 0
46
+ },
47
+ cssClasses() {
48
+ let classes = ['ccm-item-selector-group']
49
+ if (this.cssClass) {
50
+ classes = [...classes, this.cssClass]
51
+ }
52
+ return classes
53
+ }
54
+ },
43
55
  props: {
56
+ cssClass: {
57
+ type: String,
58
+ default: '',
59
+ required: false
60
+ },
44
61
  inputName: {
45
62
  type: String,
46
- required: true
63
+ default: ''
47
64
  },
48
65
  userId: {
49
- type: Number
66
+ type: Number,
67
+ default: 0
50
68
  },
51
69
  chooseText: {
52
- type: String
70
+ type: String,
71
+ default: 'Choose a User'
72
+ },
73
+ readonly: {
74
+ type: Boolean,
75
+ default: false
53
76
  }
54
77
  },
78
+ prop: ['userId'],
79
+ model: {
80
+ prop: 'userId',
81
+ event: 'change'
82
+ },
55
83
  watch: {
84
+ userId: {
85
+ immediate: true,
86
+ handler(value) {
87
+ this.selectedUserID = this.userId
88
+ }
89
+ },
56
90
  selectedUserID: {
57
91
  immediate: true,
58
92
  handler(value) {
@@ -66,31 +100,37 @@ export default {
66
100
  }
67
101
  },
68
102
  mounted() {
69
- if (this.userId) {
70
- this.selectedUserID = this.userId
71
- }
72
103
  },
73
104
  methods: {
74
105
  chooseFile: function(selectedUsers) {
75
106
  this.selectedUserID = selectedUsers[0]
76
107
  },
77
108
  openChooser: function() {
78
- var my = this
79
- window.ConcreteUserManager.launchDialog(function(r) {
80
- my.loadUser(r.id)
109
+ window.ConcreteUserManager.launchDialog((r) => {
110
+ this.loadUser(r.id)
81
111
  })
82
112
  },
83
113
  loadUser(userId) {
84
- var my = this
85
- my.isLoading = true
86
- window.ConcreteUserManager.getUserDetails(userId, function(r) {
87
- my.isLoading = false
88
- my.selectedUser = r.users[0]
89
- my.selectedUserID = userId
114
+ userId = parseInt(userId)
115
+ if (this.isLoadingUserID === userId) {
116
+ return
117
+ }
118
+ this.isLoadingUserID = userId
119
+ window.ConcreteUserManager.getUserDetails(userId, (r) => {
120
+ if (this.isLoadingUserID !== userId) {
121
+ return
122
+ }
123
+ this.selectedUserID = userId
124
+ this.selectedUser = r.users[0]
125
+ this.$nextTick(() => {
126
+ if (this.isLoadingUserID === userId) {
127
+ this.isLoadingUserID = 0
128
+ }
129
+ })
90
130
  })
91
131
  },
92
132
  reset() {
93
- this.isLoading = false
133
+ this.isLoadingUserID = 0
94
134
  this.selectedUserID = null
95
135
  }
96
136
  }