@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,126 @@
1
+ <template>
2
+ <concrete-ajax-select
3
+ :name="inputName"
4
+ :access-token="accessToken"
5
+ :css-classes="['ccm-form-select-user']"
6
+ :data-source-url="dataSourceUrl"
7
+ :selected-options-url="selectedOptionsUrl"
8
+ :value="userId"
9
+ @change="updateSelected"
10
+ :form-data="formData"
11
+ >
12
+ </concrete-ajax-select>
13
+ </template>
14
+
15
+ <script>
16
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
17
+ /* globals TomSelect */
18
+ import ConcreteAjaxSelect from './ConcreteAjaxSelect'
19
+ export default {
20
+ components: { ConcreteAjaxSelect },
21
+ prop: ['userId'],
22
+ model: {
23
+ prop: 'userId',
24
+ event: 'change'
25
+ },
26
+ props: {
27
+ includeAvatar: {
28
+ type: Boolean,
29
+ default: false
30
+ },
31
+ labelFormat: {
32
+ type: String,
33
+ default: 'auto'
34
+ },
35
+ accessToken: {
36
+ type: String,
37
+ required: true
38
+ },
39
+ inputName: {
40
+ type: String
41
+ },
42
+ userId: {
43
+ type: [Number, String, Array],
44
+ required: false
45
+ }
46
+ },
47
+ computed: {
48
+ formData() {
49
+ return {
50
+ labelFormat: this.labelFormat,
51
+ includeAvatar: this.includeAvatar,
52
+ userId: this.userId
53
+ }
54
+ }
55
+ },
56
+ data() {
57
+ return {
58
+ dataSourceUrl: CCM_DISPATCHER_FILENAME + '/ccm/system/user/autocomplete',
59
+ selectedOptionsUrl: CCM_DISPATCHER_FILENAME + '/ccm/system/user/autocomplete/get_selected',
60
+ selectedUserId: null
61
+ }
62
+ },
63
+ watch: {
64
+ userId: {
65
+ immediate: true,
66
+ handler: function(userId) {
67
+ this.selectedUserId = userId
68
+ }
69
+ }
70
+ },
71
+ methods: {
72
+ updateSelected(value) {
73
+ this.selectedUserId = value
74
+ this.$emit('change', this.selectedUserId)
75
+ },
76
+ renderOption(item) {
77
+ var option = '<div>'
78
+
79
+ if (item.avatar) {
80
+ option += `<div class="ccm-form-select-user-avatar">
81
+ <img src="${item.avatar}"/>
82
+ </div>`
83
+ }
84
+
85
+ option += '<div>'
86
+ option += `<div class="ccm-form-select-user-label-primary">
87
+ ${escape(item.primary_label)}
88
+ </div>`
89
+
90
+ if (item.secondary_label) {
91
+ option += `<div class="ccm-form-select-user-label-secondary text-secondary">
92
+ ${escape(item.secondary_label)}
93
+ </div>`
94
+ }
95
+
96
+ option += '</div>'
97
+ option += '</div>'
98
+ return option
99
+ }
100
+ }
101
+ }
102
+ </script>
103
+ <style lang="scss">
104
+ .ccm-form-select-user {
105
+ .item,
106
+ .option {
107
+ align-items: center;
108
+ display: flex;
109
+ }
110
+
111
+ .ccm-form-select-user-label-secondary {
112
+ font-size: 0.8rem;
113
+ }
114
+
115
+ .ccm-form-select-user-avatar {
116
+ flex: 0 0 20px; // Ensure this is at least 30px wide
117
+ margin-right: 12px;
118
+
119
+ img {
120
+ border-radius: 50%;
121
+ height: auto;
122
+ max-width: 100%;
123
+ }
124
+ }
125
+ }
126
+ </style>
@@ -1,10 +1,12 @@
1
1
  <template>
2
- <select class="form-control" :name="name" :title="title" v-model="selectedOption" ref="iconSelector">
3
- <option v-for="icon in icons" :value="icon.value" :data-icon="icon.value + ' fa-fw'">{{ icon.label }}</option>
2
+ <select :name="name" :title="title" v-model="selectedOption" ref="iconSelector">
3
+ <option v-for="icon in icons" :value="icon.value">{{ icon.label }}</option>
4
4
  </select>
5
5
  </template>
6
6
 
7
7
  <script>
8
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
9
+ /* globals TomSelect */
8
10
  import { icons } from '../iconlist'
9
11
 
10
12
  // Export our component definition
@@ -58,9 +60,16 @@ export default {
58
60
  }
59
61
  },
60
62
  mounted() {
61
- $(this.$refs.iconSelector).selectpicker({
62
- liveSearch: true,
63
- width: 'fit'
63
+ new TomSelect(this.$el, {
64
+ maxOptions: null,
65
+ render: {
66
+ option: function (data, escape) {
67
+ return '<div class="d-flex align-items-center"><span class="d-flex align-items-center justify-content-center me-2" style="width: 32px"><i class="' + data.value + '"></i></span><span>' + data.text + '</span></div>'
68
+ },
69
+ item: function (item, escape) {
70
+ return '<div class="d-flex align-items-center"><span class="d-flex align-items-center justify-content-center me-2" style="width: 32px"><i class="' + item.value + '"></i></span><span>' + item.text + '</span></div>'
71
+ }
72
+ }
64
73
  })
65
74
  }
66
75
  }
@@ -1,26 +1,56 @@
1
1
  <template>
2
+ <div class="password-widget">
2
3
  <div class="input-group">
3
- <input
4
- class="form-control"
5
- autocomplete="off"
6
- value=""
7
- :name="name"
8
- :id="name"
9
- :type="inputType"
10
- />
11
- <button v-if="toggler" type="button" class="input-group-icon" @click="toggle()">
12
- <i :class="`fas fa-${iconName}`" aria-hidden="true"></i>
13
- </button>
4
+ <input
5
+ class="form-control"
6
+ autocomplete="off"
7
+ value=""
8
+ :name="name"
9
+ :id="name"
10
+ :type="inputType"
11
+ v-model="enteredPassword"
12
+ />
13
+ <button
14
+ v-if="toggler"
15
+ type="button"
16
+ class="input-group-icon"
17
+ @click="passwordVisible = !passwordVisible"
18
+ >
19
+ <i aria-hidden="true" class="fas" :class="iconClasses"></i>
20
+ </button>
14
21
  </div>
22
+
23
+ <ul
24
+ v-if="strengthMeter"
25
+ class="d-flex align-items-center mt-2 password-strength-meter"
26
+ >
27
+ <li
28
+ v-for="bar in bars"
29
+ class="flex-grow-1 rounded h-100 me-2 bg-light bar"
30
+ :class="strength.id >= bar.id ? 'active' : ''"
31
+ :title="bar.value"
32
+ ></li>
33
+ </ul>
34
+ </div>
15
35
  </template>
16
36
 
17
37
  <script>
38
+ import { passwordStrength } from 'check-password-strength'
39
+
18
40
  export default {
19
- data() {
41
+ data: () => {
20
42
  return {
43
+ i18n: {
44
+ invalid: 'Invalid',
45
+ tooWeak: 'Too Weak',
46
+ weak: 'Weak',
47
+ medium: 'Medium',
48
+ strong: 'Strong',
49
+ veryStrong: 'Very Strong'
50
+ },
51
+ enteredPassword: '',
21
52
  passwordVisible: false,
22
- inputType: 'password',
23
- iconName: 'eye'
53
+ passwordStrengthOptions: []
24
54
  }
25
55
  },
26
56
  props: {
@@ -30,20 +60,107 @@ export default {
30
60
  toggler: {
31
61
  type: Boolean,
32
62
  default: true
63
+ },
64
+ strengthMeter: {
65
+ type: Boolean,
66
+ default: false
33
67
  }
34
68
  },
35
- methods: {
36
- toggle() {
37
- this.passwordVisible = !this.passwordVisible
38
-
39
- if (this.passwordVisible === true) {
40
- this.inputType = 'text'
41
- this.iconName = 'eye-slash'
42
- } else {
43
- this.inputType = 'password'
44
- this.iconName = 'eye'
69
+ computed: {
70
+ inputType() {
71
+ return this.passwordVisible ? 'text' : 'password'
72
+ },
73
+ iconClasses() {
74
+ return {
75
+ 'fa-eye': !this.passwordVisible,
76
+ 'fa-eye-slash': this.passwordVisible
45
77
  }
78
+ },
79
+ strength() {
80
+ return passwordStrength(
81
+ this.enteredPassword,
82
+ this.passwordStrengthOptions
83
+ )
84
+ },
85
+ bars() {
86
+ return this.passwordStrengthOptions.filter(
87
+ (option) => option.id >= 0
88
+ )
46
89
  }
90
+ },
91
+ mounted() {
92
+ if (window.ccmi18n_passwordInput) {
93
+ for (const key in this.i18n) {
94
+ if (window.ccmi18n_passwordInput[key]) {
95
+ this.i18n[key] = window.ccmi18n_passwordInput[key]
96
+ }
97
+ }
98
+ }
99
+
100
+ this.passwordStrengthOptions = [
101
+ {
102
+ id: -1,
103
+ value: this.i18n.invalid, // concretecms requirement: min 5 character
104
+ minDiversity: 0,
105
+ minLength: 0
106
+ },
107
+ {
108
+ id: 0,
109
+ value: this.i18n.tooWeak,
110
+ minDiversity: 1,
111
+ minLength: 5
112
+ },
113
+ {
114
+ id: 1,
115
+ value: this.i18n.weak,
116
+ minDiversity: 2,
117
+ minLength: 6
118
+ },
119
+ {
120
+ id: 2,
121
+ value: this.i18n.medium,
122
+ minDiversity: 4,
123
+ minLength: 8
124
+ },
125
+ {
126
+ id: 3,
127
+ value: this.i18n.strong,
128
+ minDiversity: 4,
129
+ minLength: 12
130
+ },
131
+ {
132
+ id: 4,
133
+ value: this.i18n.veryStrong,
134
+ minDiversity: 4,
135
+ minLength: 16
136
+ }
137
+ ]
47
138
  }
48
139
  }
49
140
  </script>
141
+
142
+ <style lang="scss" scoped>
143
+ * {
144
+ --var-active-color: #b8d935;
145
+ }
146
+
147
+ .password-strength-meter {
148
+ height: 3px;
149
+ list-style: none;
150
+ padding: 0;
151
+
152
+ .bar {
153
+ box-shadow: 0 0 0 0 var(--var-active-color) inset;
154
+ cursor: help;
155
+ transition: all ease-in 200ms;
156
+
157
+ &.active {
158
+ box-shadow: 1000px 0 0 0 var(--var-active-color) inset;
159
+ }
160
+
161
+ &:last-child {
162
+ margin-right: 0 !important;
163
+ }
164
+ }
165
+ }
166
+ </style>
@@ -87,7 +87,7 @@ export default {
87
87
  if (my.mode === 'select') {
88
88
  options.onClick = function(node) {
89
89
  if (node.data.gID) {
90
- my.triggerSelect(node.data.gID, node.title)
90
+ my.triggerSelect(node.data.gID, node.data.gName ?? node.title, node.data.gDisplayName ?? node.title)
91
91
  } else {
92
92
  return false
93
93
  }
@@ -122,12 +122,13 @@ export default {
122
122
  window.location.href = CCM_DISPATCHER_FILENAME + '/dashboard/users/groups/edit/' + group.gID
123
123
  }
124
124
  if (this.mode === 'select') {
125
- this.triggerSelect(group.gID, group.gDisplayName)
125
+ this.triggerSelect(group.gID, group.gName, group.gDisplayName)
126
126
  }
127
127
  },
128
- triggerSelect(gID, gName) {
129
- ConcreteEvent.publish('SelectGroup', { gID: gID, gName: gName })
130
- this.$emit('select', { gID: gID, gName: gName })
128
+ triggerSelect(gID, gName, gDisplayName) {
129
+ gID = parseInt(gID) || 0
130
+ ConcreteEvent.publish('SelectGroup', { gID, gName, gDisplayName })
131
+ this.$emit('select', { gID, gName, gDisplayName })
131
132
  },
132
133
  performSearch(event) {
133
134
  this.searchSubmitted = 'searching'
@@ -20,7 +20,19 @@ import ConcreteFileChooser from './file-manager/Chooser'
20
20
  import ConcreteExpressEntrySelector from './express/Selector'
21
21
  import ConcreteUserChooser from './user/Chooser'
22
22
  import ConcreteGroupChooser from './groups/Chooser'
23
+ import ConcreteSelect from './form/ConcreteSelect'
24
+ import ConcreteAjaxSelect from './form/ConcreteAjaxSelect'
25
+ import ConcreteExpressEntrySelect from './form/ConcreteExpressEntrySelect'
26
+ import ConcretePageSelect from './form/ConcretePageSelect'
27
+ import ConcreteUserSelect from './form/ConcreteUserSelect'
28
+ import ConcreteOptionSelect from './form/ConcreteOptionSelect'
29
+ import ConcreteLocaleSelect from './form/ConcreteLocaleSelect'
30
+ import ConcreteToolbarSiteList from './toolbar/ConcreteToolbarSiteList'
31
+ import ConcreteGroupInput from './form/ConcreteGroupInput'
23
32
  import ConcreteFileUploader from './file-manager/Uploader/UploadFromComputer'
33
+ import ConcreteAnnouncementBroadcast from './Announcement/Broadcast'
34
+ import ConcreteThumbnailEditor from './Image/ThumbnailEditor'
35
+ import ConcreteHelpModal from './Help/Modal'
24
36
  import Board from './Board'
25
37
  import BoardSlot from './BoardSlot'
26
38
  import BoardInstanceRule from './BoardInstanceRule'
@@ -52,14 +64,26 @@ export default {
52
64
  ConcreteFileInput,
53
65
  ConcreteThemeColorInput,
54
66
  ConcreteExpressEntryInput,
67
+ ConcreteExpressEntrySelect,
55
68
  ConcreteExpressEntrySelector,
56
69
  ConcreteFileUploader,
57
70
  ConcreteGroupChooser,
71
+ ConcreteGroupInput,
58
72
  ConcretePageChooserSearch,
59
73
  ConcretePageInput,
74
+ ConcreteSelect,
75
+ ConcreteAjaxSelect,
76
+ ConcretePageSelect,
77
+ ConcreteUserSelect,
78
+ ConcreteOptionSelect,
79
+ ConcreteLocaleSelect,
80
+ ConcreteThumbnailEditor,
81
+ ConcreteToolbarSiteList,
60
82
  ConcreteUserInput,
61
83
  ConcreteEventOccurrenceInput,
62
84
  ConcreteFileDirectoryInput,
85
+ ConcreteAnnouncementBroadcast,
86
+ ConcreteHelpModal,
63
87
  Board,
64
88
  BoardSlot,
65
89
  BoardInstanceRule,
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <input />
3
+ </template>
4
+
5
+ <script>
6
+ /* eslint-disable no-new, no-unused-vars, camelcase, eqeqeq */
7
+ /* globals TomSelect */
8
+ export default {
9
+ data() {
10
+ return {
11
+
12
+ }
13
+ },
14
+ props: {
15
+ token: {
16
+ type: String,
17
+ required: true
18
+ },
19
+ uri: {
20
+ type: String,
21
+ required: true
22
+ },
23
+ selectedSite: {
24
+ type: [String, Number],
25
+ required: false
26
+ },
27
+ sites: {
28
+ type: Array,
29
+ required: true
30
+ }
31
+ },
32
+ watch: {
33
+ },
34
+ computed: {
35
+ options: function() {
36
+ const options = []
37
+ this.sites.forEach((site) => {
38
+ options.push({ value: site.id, text: site.name })
39
+ })
40
+ return options
41
+ }
42
+ },
43
+ mounted() {
44
+ var config = {}
45
+ config.maxOptions = null
46
+ config.options = this.options
47
+ config.maxItems = 1
48
+ config.items = [this.selectedSite]
49
+ this.$nextTick(() => {
50
+ const select = new TomSelect(this.$el, config)
51
+ select.on('change', (option) => {
52
+ const url = CCM_DISPATCHER_FILENAME + '/ccm/site/redirect/' + option +
53
+ '?rUri=' + encodeURIComponent(this.uri) +
54
+ '&ccm_token=' + this.token
55
+ window.location.href = url
56
+ })
57
+ })
58
+ },
59
+ methods: {
60
+ }
61
+ }
62
+ </script>
@@ -24,6 +24,7 @@
24
24
  <users v-if="keywords"
25
25
  :selectedUsers.sync="selectedUsers"
26
26
  :multipleSelection="multipleSelection"
27
+ :hideUsername="hideUsername"
27
28
  :routePath="this.routePath + keywords"/>
28
29
  </div>
29
30
  </div>
@@ -57,6 +58,10 @@ export default {
57
58
  multipleSelection: {
58
59
  type: Boolean,
59
60
  default: true
61
+ },
62
+ hideUsername: {
63
+ type: Boolean,
64
+ default: false
60
65
  }
61
66
  },
62
67
  watch: {
@@ -6,7 +6,7 @@
6
6
  <thead>
7
7
  <tr>
8
8
  <th></th>
9
- <th @click="sortBy('name')" :class="getSortColumnClassName('name')"><a href="javascript:void(0)">{{ i18n.username }}</a></th>
9
+ <th v-if="!hideUsername" @click="sortBy('name')" :class="getSortColumnClassName('name')"><a href="javascript:void(0)">{{ i18n.username }}</a></th>
10
10
  <th @click="sortBy('email')" :class="getSortColumnClassName('email')"><a href="javascript:void(0)">{{ i18n.email }}</a></th>
11
11
  <th @click="sortBy('dateAdded')" :class="getSortColumnClassName('dateAdded')"><a href="javascript:void(0)">{{ i18n.date }}</a></th>
12
12
  <th>{{ i18n.status }}</th>
@@ -19,7 +19,7 @@
19
19
  <input type="checkbox" v-if="multipleSelection" v-model="selectedUsers" :id="'user-' + user.id" :value="user">
20
20
  <input type="radio" v-if="!multipleSelection" v-model="selectedUsers" :id="'user-' + user.id" :value="user">
21
21
  </td>
22
- <td>{{user.name}}</td>
22
+ <td v-if="!hideUsername">{{user.name}}</td>
23
23
  <td>{{user.email}}</td>
24
24
  <td>{{user.dateAdded}}</td>
25
25
  <td>{{user.status}}</td>
@@ -58,6 +58,10 @@ export default {
58
58
  multipleSelection: {
59
59
  type: Boolean,
60
60
  default: true
61
+ },
62
+ hideUsername: {
63
+ type: Boolean,
64
+ default: true
61
65
  }
62
66
  },
63
67
  methods: {
@@ -1,6 +1,10 @@
1
1
  <template>
2
2
  <div>
3
- <search :selectedUsers.sync="selectedUsers" :multiple-selection="multipleSelection"/>
3
+ <search
4
+ :selectedUsers.sync="selectedUsers"
5
+ :multiple-selection="multipleSelection"
6
+ :hide-username="hideUsername"
7
+ />
4
8
  <div class="dialog-buttons">
5
9
  <button class="btn btn-secondary" data-dialog-action="cancel">{{ i18n.cancel }}</button>
6
10
  <button type="button" @click="chooseUsers" :disabled="selectedUsers.length === 0" class="btn btn-primary">{{ i18n.choose }}</button>
@@ -9,18 +13,20 @@
9
13
  </template>
10
14
 
11
15
  <script>
12
- import Users from './Chooser/Users'
13
16
  import Search from './Chooser/Search'
14
17
 
15
18
  export default {
16
19
  components: {
17
- Users,
18
20
  Search
19
21
  },
20
22
  props: {
21
23
  multipleSelection: {
22
24
  type: Boolean,
23
25
  default: true
26
+ },
27
+ hideUsername: {
28
+ type: Boolean,
29
+ default: false
24
30
  }
25
31
  },
26
32
  data() {
@@ -49,10 +49,19 @@
49
49
  },
50
50
 
51
51
  error: function(r, my) {
52
- ConcreteEvent.fire('AjaxRequestError', {
53
- response: r
54
- })
55
- ConcreteAlert.dialog(ccmi18n.error, ConcreteAjaxRequest.renderErrorResponse(r, true))
52
+ if (r.readyState !== 0) {
53
+ // This happens in Firefox. I don't know why. It happens when an AJAX request is in process and then
54
+ // the page is navigated away from. I feel like Chrome handles this transparently, or maybe jQuery
55
+ // handles it better behind the scenes and doesn't send the error object on to the 'error' handler
56
+ // of the jquery .ajax() method. Regardless, sometimes incomplete AJAX requests in Firefox
57
+ // trigger the error handler without real data, so they just show "Undefined" as a popup.
58
+ // (e.g. https://github.com/concretecms/concretecms/issues/11135)
59
+ // So let's only pop the dialog if the readyState is NOT 0.
60
+ ConcreteEvent.fire('AjaxRequestError', {
61
+ response: r
62
+ })
63
+ ConcreteAlert.dialog(ccmi18n.error, ConcreteAjaxRequest.renderErrorResponse(r, true))
64
+ }
56
65
  },
57
66
 
58
67
  validateResponse: function(r, callback) {
@@ -98,13 +98,14 @@ class ConcreteAlert {
98
98
  icon: 'check-circle',
99
99
  title: false,
100
100
  message: false,
101
+ plainTextMessage: false,
101
102
  delay: 2000,
102
103
  callback: () => {}
103
104
  }, defaults)
104
105
 
105
106
  const notifyOptions = {
106
107
  text: options.message,
107
- textTrusted: true,
108
+ textTrusted: !options.plainTextMessage,
108
109
  icon: 'fas fa-' + options.icon,
109
110
  type: options.type,
110
111
  delay: options.delay,
@@ -7,10 +7,6 @@ import PNotify from './pnotify'
7
7
  import 'json5'
8
8
  import 'jquery.cookie'
9
9
  import 'jquery-form'
10
- import 'bootstrap-select/js/bootstrap-select'
11
- import './modifiable-bootstrap-select'
12
- import 'ajax-bootstrap-select'
13
- import './modifiable-ajax-bootstrap-select'
14
10
  import 'dropzone/dist/dropzone'
15
11
 
16
12
  // jQuery UI components
@@ -32,8 +28,10 @@ import './concrete'
32
28
  import './panels'
33
29
  import './toolbar'
34
30
  import './legacy-dialog'
31
+ import './modal'
35
32
  import './alert'
36
33
  import './page-notification'
34
+ import './select-combo-box'
37
35
 
38
36
  // Edit Mode
39
37
  import './edit-mode'
@@ -74,17 +72,11 @@ import './users'
74
72
  // Express
75
73
  import './express'
76
74
 
77
- // Style customizer
78
-
79
- // In-page editable fields
80
- // TBD
81
-
82
75
  // File Manager
83
76
  import './file-manager/uploader'
84
77
  import './file-manager/file-manager'
85
78
 
86
79
  // Miscellaneous UI components
87
- import 'selectize'
88
80
  import 'spectrum-colorpicker2'
89
81
  import 'tristate/jquery.tristate'
90
82
  import 'jquery-text-counter/textcounter'
@@ -101,6 +93,7 @@ import './calendar'
101
93
  // Vue components.
102
94
  import components from '@concretecms/bedrock/assets/cms/components/index'
103
95
  import VueManager from '@concretecms/bedrock/assets/cms/js/vue/Manager'
96
+ import './jquery-vue'
104
97
 
105
98
  window.NProgress = NProgress
106
99
  window._ = _