Skip to content

Commit eb9913d

Browse files
authored
Merge branch 'main' into feature/identifier-base-type-data-model
2 parents 309a299 + 39d3c7e commit eb9913d

17 files changed

Lines changed: 611 additions & 55 deletions

File tree

.github/workflows/WORKFLOW_ARCHITECTURE.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -727,13 +727,13 @@ Navigate to: https://github.com/dotCMS/core/actions → **"-6 Release Process"**
727727

728728
### Optional Configurations
729729

730-
| Option | Default | Purpose |
731-
|--------|---------|---------|
732-
| **Deploy Artifact** | ✅ Enabled | Deploy to Artifactory (repo.dotcms.com)<br/>**Required for successful release** |
733-
| **Update Plugins** | ✅ Enabled | Triggers plugin-seeds repo update<br/>**Note**: Currently requires manual execution at [plugin-seeds/release-target.yml](https://github.com/dotCMS/plugin-seeds/actions/workflows/release-target.yml) |
734-
| **Upload Javadocs** | ✅ Enabled | Generate and upload to S3 static bucket<br/>Creates HTML documentation bundle |
735-
| **Update GitHub Labels** | ✅ Enabled | Replaces "Next Release" with "Release vX.X.X"<br/>Enables filtering issues by release |
736-
| **Notify Slack** | ✅ Enabled | Posts announcement to general channel<br/>Can disable for testing |
730+
| Option | Default | Purpose |
731+
|--------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
732+
| **Deploy Artifact** | ✅ Enabled | Deploy to Artifactory (repo.dotcms.com)<br/>**Required for successful release** |
733+
| **Update Plugins** | ✅ Enabled | Triggers plugin-examples repo update<br/>**Note**: Currently requires manual execution at [dotcms-community/plugin-examples/release-target.yml](https://github.com/dotcms-community/plugin-examples/actions/workflows/release-target.yml) |
734+
| **Upload Javadocs** | ✅ Enabled | Generate and upload to S3 static bucket<br/>Creates HTML documentation bundle |
735+
| **Update GitHub Labels** | ✅ Enabled | Replaces "Next Release" with "Release vX.X.X"<br/>Enables filtering issues by release |
736+
| **Notify Slack** | ✅ Enabled | Posts announcement to general channel<br/>Can disable for testing |
737737

738738
### Process Overview
739739

@@ -1055,4 +1055,3 @@ Our CI/CD architecture delivers significant benefits over traditional monolithic
10551055
**Last Updated**: December 2024
10561056
**Maintained By**: dotCMS DevOps Team
10571057
**Questions?** Contact #guild-dev-pipeline on Slack
1058-

.github/workflows/cicd_comp_release-phase.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ jobs:
219219
-H "Accept: application/vnd.github+json" \
220220
-H "Authorization: Bearer ${CI_MACHINE_TOKEN}" \
221221
-H "X-GitHub-Api-Version: 2022-11-28" \
222-
https://api.github.com/repos/dotCMS/plugin-seeds/dispatches \
222+
https://api.github.com/repos/dotcms-community/plugin-examples/dispatches \
223223
-d "{\"event_type\": \"on-plugins-release\", \"client_payload\": {\"release_version\": \"${release_version}\"}}" \
224224
-w "\n%{http_code}" \
225225
-s)
@@ -284,4 +284,4 @@ jobs:
284284
new_label: 'Release : ${{ inputs.release_version }}'
285285
rename_label: 'Next Release'
286286
secrets:
287-
CI_MACHINE_TOKEN: ${{ secrets.CI_MACHINE_TOKEN }}
287+
CI_MACHINE_TOKEN: ${{ secrets.CI_MACHINE_TOKEN }}

.github/workflows/legacy-release_maven-release-process.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ jobs:
357357
-H "Accept: application/vnd.github+json" \
358358
-H "Authorization: Bearer ${{ secrets.CI_MACHINE_TOKEN }}" \
359359
-H "X-GitHub-Api-Version: 2022-11-28" \
360-
https://api.github.com/repos/dotCMS/plugin-seeds/dispatches \
360+
https://api.github.com/repos/dotcms-community/plugin-examples/dispatches \
361361
-d "{\"event_type\": \"on-plugins-release\", \"client_payload\": {\"release_version\": \"$release_version\"}}" \
362362
-w "\n%{http_code}" \
363363
-s)

.github/workflows/maven-release-process.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ This checkbox is enabled by default and the function is to deploy all the depend
4646

4747
Update plugins (default enabled):
4848

49-
Same thing here, by default is enabled and the function is to create a plugins version for the release that will be generated by the job. Currently this does not happen in an automated way, therefore this step should be manually run by executing the plugin-seeds repo workflow at [https://github.com/dotCMS/plugin-seeds/actions/workflows/release-target.yml](https://github.com/dotCMS/plugin-seeds/actions/workflows/release-target.yml) matching the same release version value.
49+
Same thing here, by default is enabled and the function is to create a plugins version for the release that will be generated by the job. Currently this does not happen in an automated way, therefore this step should be manually run by executing the plugin-examples repo workflow at [https://github.com/dotcms-community/plugin-examples/actions/workflows/release-target.yml](https://github.com/dotcms-community/plugin-examples/actions/workflows/release-target.yml) matching the same release version value.
5050

5151

5252

@@ -74,4 +74,4 @@ This field is related to generating a notification in the general slack channel
7474

7575
Finally once you set all the parameters, we are ready to release, just click on the “Run Workflow” button and it will start a process in the background in order to deploy everything and finally generate the release version. After some minutes, you will receive a notification on the general slack channel about the new version.
7676

77-
Also, you can track one by one all the stages and see more details about the process in the page redirected after firing the action.
77+
Also, you can track one by one all the stages and see more details about the process in the page redirected after firing the action.

core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-palette/components/dot-uve-palette-list/dot-uve-palette-list.component.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
effect,
1010
inject,
1111
input,
12-
linkedSignal,
1312
OnInit,
1413
signal,
1514
untracked,
@@ -132,6 +131,7 @@ export class DotUvePaletteListComponent implements OnInit {
132131
protected readonly $skipNextSearch = signal(false);
133132
protected readonly $contextMenuItems = signal<MenuItem[]>([]);
134133
protected readonly $isSearching = signal<boolean>(false);
134+
protected readonly $shouldHideControls = signal<boolean>(true);
135135
protected readonly $siteId = this.#globalStore.currentSiteId;
136136
protected readonly $contenttypes = this.#paletteListStore.contenttypes;
137137
protected readonly $contentlets = this.#paletteListStore.contentlets;
@@ -146,11 +146,6 @@ export class DotUvePaletteListComponent implements OnInit {
146146
protected readonly $isFavoritesList = this.#paletteListStore.$isFavoritesList;
147147
protected readonly status$ = toObservable(this.#paletteListStore.status);
148148

149-
protected readonly $shouldHideControls = linkedSignal({
150-
source: this.$contenttypes,
151-
computation: (contenttypes) => contenttypes.length === 0
152-
});
153-
154149
/**
155150
* Computed signal to determine the start index for the pagination.
156151
* @returns The start index for the pagination.
@@ -292,7 +287,7 @@ export class DotUvePaletteListComponent implements OnInit {
292287
* Handles the selection of a content type to view its contentlets.
293288
* Store handles query building, filter reset, and page reset automatically.
294289
*
295-
* @param contentTypeName - The name of the content type to drill into
290+
* @param selectedContentType - The name of the content type to drill into
296291
*/
297292
protected onSelectContentType(selectedContentType: string) {
298293
this.#paletteListStore.getContentlets({ ...EMPTY_SEARCH_PARAMS, selectedContentType });
@@ -421,6 +416,7 @@ export class DotUvePaletteListComponent implements OnInit {
421416
* @private
422417
*/
423418
#updateControlsVisibility() {
419+
this.$shouldHideControls.set(false);
424420
this.status$
425421
.pipe(
426422
filter(

core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-palette/models.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export const DEFAULT_PER_PAGE = 30;
153153

154154
/**
155155
* Base content types included in the Content tab.
156+
* Filter excludes DotCMSBaseTypesContentTypes FORMs and HTMLPAGEs to keep the Palette UI focused on standard content.
156157
*/
157158
export const BASETYPES_FOR_CONTENT = [
158159
DotCMSBaseTypesContentTypes.CONTENT,

core-web/libs/portlets/edit-ema/portlet/src/lib/services/inline-edit/inline-edit.service.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,30 @@ describe('InlineEditService', () => {
1212

1313
beforeEach(() => (spectator = createService()));
1414

15+
it.each([
16+
{ mode: 'minimal', label: 'minimal' },
17+
{ mode: 'full', label: 'full' },
18+
{ mode: '', label: 'default (minimal)' }
19+
])('should pass convert_urls: false to tinymce.init ($label)', ({ mode }) => {
20+
const initMock = jest.fn().mockResolvedValue([]);
21+
const iframeWindow = {
22+
tinymce: { init: initMock }
23+
} as unknown as Window;
24+
25+
spectator.service.setIframeWindow(iframeWindow);
26+
spectator.service.setTargetInlineMCEDataset({
27+
inode: '1',
28+
fieldName: 'body',
29+
language: 'en',
30+
mode
31+
});
32+
33+
spectator.service.initEditor();
34+
35+
expect(initMock).toHaveBeenCalledTimes(1);
36+
expect(initMock.mock.calls[0][0].convert_urls).toBe(false);
37+
});
38+
1539
it('should inject inline edit', () => {
1640
const iframe = document.createElement('iframe');
1741
document.body.appendChild(iframe);

core-web/libs/portlets/edit-ema/portlet/src/lib/services/inline-edit/inline-edit.service.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ export const INLINE_CONTENT_STYLES = `
3030
}
3131
`;
3232

33+
/** Shared TinyMCE options for EMA inline editing (excluding per-instance `setup`). */
34+
export const INLINE_EDIT_TINYMCE_BASE_OPTIONS = {
35+
menubar: false,
36+
inline: true,
37+
// Avoid rewriting root-relative URLs (e.g. /dA/...) to ../... on serialize; iframe base differs from site root.
38+
convert_urls: false,
39+
valid_styles: {
40+
'*': 'font-size,font-family,color,text-decoration,text-align'
41+
},
42+
powerpaste_word_import: 'clean',
43+
powerpaste_html_import: 'clean'
44+
} as const;
45+
3346
@Injectable({
3447
providedIn: 'root'
3548
})
@@ -39,17 +52,11 @@ export class InlineEditService {
3952
private $inlineEditingTargetDataset = signal<InlineEditingContentletDataset | null>(null);
4053

4154
private readonly DEFAULT_TINYMCE_CONFIG = {
42-
menubar: false,
43-
inline: true,
44-
valid_styles: {
45-
'*': 'font-size,font-family,color,text-decoration,text-align'
46-
},
47-
powerpaste_word_import: 'clean',
48-
powerpaste_html_import: 'clean',
55+
...INLINE_EDIT_TINYMCE_BASE_OPTIONS,
4956
setup: this.#handleInlineEditEvents
5057
};
5158

52-
private readonly TINYCME_CONFIG = {
59+
private readonly TINYMCE_CONFIG = {
5360
minimal: {
5461
plugins: ['link', 'autolink'],
5562
toolbar: 'bold italic underline | link',
@@ -162,7 +169,7 @@ export class InlineEditService {
162169

163170
this.$iframeWindow()
164171
.tinymce.init({
165-
...this.TINYCME_CONFIG[dataset.mode || 'minimal'],
172+
...this.TINYMCE_CONFIG[dataset.mode || 'minimal'],
166173
selector: dataSelector
167174
})
168175
.then(([ed]) => {

docs/README.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ for developers looking to begin developing plugins for dotCMS.
33

44
Note: the samples has been moved to:
55

6-
https://github.com/dotCMS/plugin-seeds
6+
https://github.com/dotcms-community/plugin-examples
77

88
For other documentation, refer to:
99

10-
http://dotcms.com/
10+
http://dev.dotcms.com/

dotCMS/src/main/java/com/dotcms/contenttype/transform/contenttype/DetailPageTransformerImpl.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.dotcms.contenttype.transform.contenttype;
22

33
import com.dotcms.api.web.HttpServletRequestThreadLocal;
4+
import com.dotcms.contenttype.model.type.BaseContentType;
45
import com.dotcms.contenttype.model.type.ContentType;
56
import com.dotcms.rest.api.v1.contenttype.ContentTypeHelper;
67
import com.dotmarketing.beans.Host;
@@ -20,7 +21,6 @@
2021

2122
public class DetailPageTransformerImpl implements DetailPageTransformer {
2223

23-
private static final String PAGE_SUBTYPE = "htmlpageasset";
2424

2525
private final ContentType contentType;
2626
private final User user;
@@ -123,25 +123,26 @@ public Optional<String> idToUri() throws DotDataException, DotSecurityException
123123
* @throws IllegalArgumentException if the identifier is invalid.
124124
*/
125125
private Optional<String> validateIdentifier(
126-
String detailPage, Identifier foundDetailPageIdentifier) {
127-
128-
if (null != foundDetailPageIdentifier &&
129-
foundDetailPageIdentifier.exists() &&
130-
foundDetailPageIdentifier.getAssetSubType().equals(PAGE_SUBTYPE)) {
131-
return Optional.of(foundDetailPageIdentifier.getId());
132-
} else {
133-
if (null != foundDetailPageIdentifier &&
134-
foundDetailPageIdentifier.exists() &&
135-
!foundDetailPageIdentifier.getAssetSubType().equals(PAGE_SUBTYPE)) {
136-
throw new IllegalArgumentException(
137-
String.format("[%s] in Content Type [%s] is not a valid detail page.",
138-
detailPage, contentType.name()));
126+
String detailPage, Identifier foundDetailPageIdentifier)
127+
throws DotDataException, DotSecurityException {
128+
129+
if (null != foundDetailPageIdentifier && foundDetailPageIdentifier.exists()) {
130+
final String assetSubType = foundDetailPageIdentifier.getAssetSubType();
131+
if (UtilMethods.isSet(assetSubType)) {
132+
final ContentType detailPageType = APILocator.getContentTypeAPI(
133+
APILocator.getUserAPI().getSystemUser()).find(assetSubType);
134+
if (null != detailPageType && BaseContentType.HTMLPAGE == detailPageType.baseType()) {
135+
return Optional.of(foundDetailPageIdentifier.getId());
136+
}
139137
}
140-
141138
throw new IllegalArgumentException(
142-
String.format("Detail page [%s] in Content Type [%s] does not exist.",
139+
String.format("[%s] in Content Type [%s] is not a valid detail page.",
143140
detailPage, contentType.name()));
144141
}
142+
143+
throw new IllegalArgumentException(
144+
String.format("Detail page [%s] in Content Type [%s] does not exist.",
145+
detailPage, contentType.name()));
145146
}
146147

147148
}

0 commit comments

Comments
 (0)