@contentful/field-editor-shared 2.4.2 → 2.5.1
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.
- package/dist/cjs/ReleaseEntityStatusBadge/Banner.js +44 -0
- package/dist/cjs/ReleaseEntityStatusBadge/ReleaseEntityStatusBadge.js +39 -0
- package/dist/cjs/ReleaseEntityStatusBadge/ReleaseEntityStatusLocale.js +49 -0
- package/dist/cjs/ReleaseEntityStatusBadge/ReleaseEntityStatusLocalesList.js +85 -0
- package/dist/cjs/ReleaseEntityStatusBadge/ReleaseEntityStatusPopover.js +277 -0
- package/dist/cjs/ReleaseEntityStatusBadge/constants.js +46 -0
- package/dist/cjs/ReleaseEntityStatusBadge/index.js +20 -0
- package/dist/cjs/ReleaseEntityStatusBadge/types.js +4 -0
- package/dist/cjs/index.js +1 -0
- package/dist/esm/ReleaseEntityStatusBadge/Banner.js +29 -0
- package/dist/esm/ReleaseEntityStatusBadge/ReleaseEntityStatusBadge.js +24 -0
- package/dist/esm/ReleaseEntityStatusBadge/ReleaseEntityStatusLocale.js +34 -0
- package/dist/esm/ReleaseEntityStatusBadge/ReleaseEntityStatusLocalesList.js +70 -0
- package/dist/esm/ReleaseEntityStatusBadge/ReleaseEntityStatusPopover.js +221 -0
- package/dist/esm/ReleaseEntityStatusBadge/constants.js +31 -0
- package/dist/esm/ReleaseEntityStatusBadge/index.js +3 -0
- package/dist/esm/ReleaseEntityStatusBadge/types.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/types/ReleaseEntityStatusBadge/Banner.d.ts +5 -0
- package/dist/types/ReleaseEntityStatusBadge/ReleaseEntityStatusBadge.d.ts +8 -0
- package/dist/types/ReleaseEntityStatusBadge/ReleaseEntityStatusLocale.d.ts +10 -0
- package/dist/types/ReleaseEntityStatusBadge/ReleaseEntityStatusLocalesList.d.ts +9 -0
- package/dist/types/ReleaseEntityStatusBadge/ReleaseEntityStatusPopover.d.ts +10 -0
- package/dist/types/ReleaseEntityStatusBadge/constants.d.ts +30 -0
- package/dist/types/ReleaseEntityStatusBadge/index.d.ts +3 -0
- package/dist/types/ReleaseEntityStatusBadge/types.d.ts +11 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "Banner", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return Banner;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = /*#__PURE__*/ _interop_require_default(require("react"));
|
|
12
|
+
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
|
|
14
|
+
const _emotion = require("emotion");
|
|
15
|
+
function _interop_require_default(obj) {
|
|
16
|
+
return obj && obj.__esModule ? obj : {
|
|
17
|
+
default: obj
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const styles = {
|
|
21
|
+
content: (0, _emotion.css)({
|
|
22
|
+
display: 'block'
|
|
23
|
+
}),
|
|
24
|
+
banner: (0, _emotion.css)({
|
|
25
|
+
background: _f36tokens.default.gray100,
|
|
26
|
+
padding: _f36tokens.default.spacingXs,
|
|
27
|
+
margin: `${_f36tokens.default.spacingXs} ${_f36tokens.default.spacingS}`,
|
|
28
|
+
borderRadius: _f36tokens.default.borderRadiusSmall
|
|
29
|
+
})
|
|
30
|
+
};
|
|
31
|
+
function Banner({ content, highlight }) {
|
|
32
|
+
return _react.default.createElement("div", {
|
|
33
|
+
className: styles.banner
|
|
34
|
+
}, _react.default.createElement(_f36components.Text, {
|
|
35
|
+
fontSize: "fontSizeS",
|
|
36
|
+
fontColor: "gray700",
|
|
37
|
+
className: styles.content
|
|
38
|
+
}, content), highlight && _react.default.createElement(_f36components.Text, {
|
|
39
|
+
fontSize: "fontSizeS",
|
|
40
|
+
fontColor: "gray700",
|
|
41
|
+
as: "strong",
|
|
42
|
+
fontWeight: "fontWeightDemiBold"
|
|
43
|
+
}, highlight));
|
|
44
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ReleaseEntityStatusBadge", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ReleaseEntityStatusBadge;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = /*#__PURE__*/ _interop_require_default(require("react"));
|
|
12
|
+
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
function _interop_require_default(obj) {
|
|
14
|
+
return obj && obj.__esModule ? obj : {
|
|
15
|
+
default: obj
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const config = {
|
|
19
|
+
publish: {
|
|
20
|
+
label: 'Will publish',
|
|
21
|
+
variant: 'positive'
|
|
22
|
+
},
|
|
23
|
+
unpublish: {
|
|
24
|
+
label: 'Becomes draft',
|
|
25
|
+
variant: 'warning'
|
|
26
|
+
},
|
|
27
|
+
'not-in-release': {
|
|
28
|
+
label: 'Not in release',
|
|
29
|
+
variant: 'secondary'
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function ReleaseEntityStatusBadge({ className, action }) {
|
|
33
|
+
const badgeConfig = config[action];
|
|
34
|
+
return _react.default.createElement(_f36components.Badge, {
|
|
35
|
+
testId: "release-entity-action-status",
|
|
36
|
+
className: className,
|
|
37
|
+
variant: badgeConfig.variant
|
|
38
|
+
}, badgeConfig.label);
|
|
39
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ReleaseEntityStatusLocale", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ReleaseEntityStatusLocale;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = /*#__PURE__*/ _interop_require_default(require("react"));
|
|
12
|
+
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
|
|
14
|
+
const _emotion = require("emotion");
|
|
15
|
+
function _interop_require_default(obj) {
|
|
16
|
+
return obj && obj.__esModule ? obj : {
|
|
17
|
+
default: obj
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const styles = {
|
|
21
|
+
locale: (0, _emotion.css)({
|
|
22
|
+
textOverflow: 'ellipsis',
|
|
23
|
+
overflow: 'hidden',
|
|
24
|
+
whiteSpace: 'nowrap'
|
|
25
|
+
}),
|
|
26
|
+
status: (0, _emotion.css)({
|
|
27
|
+
flexShrink: 0
|
|
28
|
+
}),
|
|
29
|
+
localePublishStatus: (0, _emotion.css)({
|
|
30
|
+
display: 'flex',
|
|
31
|
+
gap: _f36tokens.default.spacingXs,
|
|
32
|
+
justifyContent: 'space-between',
|
|
33
|
+
padding: `${_f36tokens.default.spacingXs} ${_f36tokens.default.spacingS}`
|
|
34
|
+
})
|
|
35
|
+
};
|
|
36
|
+
function ReleaseEntityStatusLocale({ locale, label, variant }) {
|
|
37
|
+
return _react.default.createElement("div", {
|
|
38
|
+
className: styles.localePublishStatus,
|
|
39
|
+
"data-test-id": "locale-publishing-status"
|
|
40
|
+
}, _react.default.createElement(_f36components.Text, {
|
|
41
|
+
className: styles.locale,
|
|
42
|
+
fontColor: "gray700"
|
|
43
|
+
}, locale.name, ' ', _react.default.createElement(_f36components.Text, {
|
|
44
|
+
fontColor: "gray500"
|
|
45
|
+
}, "(", locale.code, ")", locale.default && ', Default')), _react.default.createElement(_f36components.Badge, {
|
|
46
|
+
className: styles.status,
|
|
47
|
+
variant: variant
|
|
48
|
+
}, label));
|
|
49
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ReleaseEntityStatusLocalesList", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ReleaseEntityStatusLocalesList;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = /*#__PURE__*/ _interop_require_default(require("react"));
|
|
12
|
+
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
const _lodash = require("lodash");
|
|
14
|
+
const _Banner = require("./Banner");
|
|
15
|
+
const _ReleaseEntityStatusLocale = require("./ReleaseEntityStatusLocale");
|
|
16
|
+
function _interop_require_default(obj) {
|
|
17
|
+
return obj && obj.__esModule ? obj : {
|
|
18
|
+
default: obj
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function groupAndSortLocales(entries, activeLocales) {
|
|
22
|
+
const { selected, nonSelected } = entries.reduce((prev, [localeCode, localeStatusType])=>{
|
|
23
|
+
return activeLocales?.some((sl)=>sl.code === localeCode) ? {
|
|
24
|
+
...prev,
|
|
25
|
+
selected: [
|
|
26
|
+
...prev.selected,
|
|
27
|
+
localeStatusType
|
|
28
|
+
]
|
|
29
|
+
} : {
|
|
30
|
+
...prev,
|
|
31
|
+
nonSelected: [
|
|
32
|
+
...prev.nonSelected,
|
|
33
|
+
localeStatusType
|
|
34
|
+
]
|
|
35
|
+
};
|
|
36
|
+
}, {
|
|
37
|
+
selected: [],
|
|
38
|
+
nonSelected: []
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
selected: (0, _lodash.sortBy)(selected, 'locale.name'),
|
|
42
|
+
nonSelected: nonSelected.sort((a, b)=>{
|
|
43
|
+
if (a.status === b.status) {
|
|
44
|
+
return a.locale.name.localeCompare(b.locale.name);
|
|
45
|
+
}
|
|
46
|
+
if (a.status === 'becomesDraft' || a.status === 'willPublish' && b.status === 'remainsDraft') {
|
|
47
|
+
return -1;
|
|
48
|
+
}
|
|
49
|
+
return 1;
|
|
50
|
+
})
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function ReleaseEntityStatusLocalesList({ statusMap, activeLocales }) {
|
|
54
|
+
const entries = [
|
|
55
|
+
...statusMap.entries()
|
|
56
|
+
];
|
|
57
|
+
const counters = entries.reduce((prev, [, { status }])=>({
|
|
58
|
+
becomesDraft: prev.becomesDraft + (status === 'becomesDraft' ? 1 : 0),
|
|
59
|
+
willPublish: prev.willPublish + (status === 'willPublish' ? 1 : 0),
|
|
60
|
+
remainsDraft: prev.remainsDraft + (status === 'remainsDraft' ? 1 : 0)
|
|
61
|
+
}), {
|
|
62
|
+
willPublish: 0,
|
|
63
|
+
becomesDraft: 0,
|
|
64
|
+
remainsDraft: 0
|
|
65
|
+
});
|
|
66
|
+
const { selected, nonSelected } = groupAndSortLocales(entries, activeLocales);
|
|
67
|
+
return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement(_Banner.Banner, {
|
|
68
|
+
content: "The statuses of the locales for this content:",
|
|
69
|
+
highlight: `${counters.becomesDraft} becomes draft, ${counters.willPublish} will publish, ${counters.remainsDraft} remains draft`
|
|
70
|
+
}), _react.default.createElement("div", {
|
|
71
|
+
"data-test-id": "locale-publishing-selected"
|
|
72
|
+
}, _react.default.createElement(_f36components.MenuSectionTitle, null, "Locales in the entry editor:"), selected.map(({ locale, label, variant })=>_react.default.createElement(_ReleaseEntityStatusLocale.ReleaseEntityStatusLocale, {
|
|
73
|
+
key: `selected-${locale.code}`,
|
|
74
|
+
label: label,
|
|
75
|
+
variant: variant,
|
|
76
|
+
locale: locale
|
|
77
|
+
}))), nonSelected.length > 0 && _react.default.createElement("div", {
|
|
78
|
+
"data-test-id": "locale-publishing-others"
|
|
79
|
+
}, _react.default.createElement(_f36components.MenuSectionTitle, null, "Other locales:"), nonSelected.map(({ locale, label, variant })=>_react.default.createElement(_ReleaseEntityStatusLocale.ReleaseEntityStatusLocale, {
|
|
80
|
+
key: `others-${locale.code}`,
|
|
81
|
+
label: label,
|
|
82
|
+
variant: variant,
|
|
83
|
+
locale: locale
|
|
84
|
+
}))));
|
|
85
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ReleaseEntityStatusPopover", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ReleaseEntityStatusPopover;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
12
|
+
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
|
|
14
|
+
const _emotion = require("emotion");
|
|
15
|
+
const _constants = require("./constants");
|
|
16
|
+
const _ReleaseEntityStatusLocalesList = require("./ReleaseEntityStatusLocalesList");
|
|
17
|
+
function _interop_require_default(obj) {
|
|
18
|
+
return obj && obj.__esModule ? obj : {
|
|
19
|
+
default: obj
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
23
|
+
if (typeof WeakMap !== "function") return null;
|
|
24
|
+
var cacheBabelInterop = new WeakMap();
|
|
25
|
+
var cacheNodeInterop = new WeakMap();
|
|
26
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
27
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
28
|
+
})(nodeInterop);
|
|
29
|
+
}
|
|
30
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
31
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
32
|
+
return obj;
|
|
33
|
+
}
|
|
34
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
35
|
+
return {
|
|
36
|
+
default: obj
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
40
|
+
if (cache && cache.has(obj)) {
|
|
41
|
+
return cache.get(obj);
|
|
42
|
+
}
|
|
43
|
+
var newObj = {
|
|
44
|
+
__proto__: null
|
|
45
|
+
};
|
|
46
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
47
|
+
for(var key in obj){
|
|
48
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
49
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
50
|
+
if (desc && (desc.get || desc.set)) {
|
|
51
|
+
Object.defineProperty(newObj, key, desc);
|
|
52
|
+
} else {
|
|
53
|
+
newObj[key] = obj[key];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
newObj.default = obj;
|
|
58
|
+
if (cache) {
|
|
59
|
+
cache.set(obj, newObj);
|
|
60
|
+
}
|
|
61
|
+
return newObj;
|
|
62
|
+
}
|
|
63
|
+
const getColor = ({ secondary, tertiary, isHover })=>{
|
|
64
|
+
const status = secondary || tertiary;
|
|
65
|
+
return isHover ? _constants.RELEASE_BADGES[status]?.hover : _constants.RELEASE_BADGES[status]?.default;
|
|
66
|
+
};
|
|
67
|
+
const generateDynamicStyles = (status)=>{
|
|
68
|
+
const wrapperClass = (0, _emotion.css)({
|
|
69
|
+
'& svg[data-status="secondary"]': {
|
|
70
|
+
fill: getColor({
|
|
71
|
+
secondary: status?.secondary,
|
|
72
|
+
isHover: false
|
|
73
|
+
})
|
|
74
|
+
},
|
|
75
|
+
'& svg[data-status="tertiary"]': {
|
|
76
|
+
fill: getColor({
|
|
77
|
+
tertiary: status?.tertiary,
|
|
78
|
+
isHover: false
|
|
79
|
+
})
|
|
80
|
+
},
|
|
81
|
+
'&:hover svg[data-status="secondary"]': {
|
|
82
|
+
fill: getColor({
|
|
83
|
+
secondary: status?.secondary,
|
|
84
|
+
isHover: true
|
|
85
|
+
})
|
|
86
|
+
},
|
|
87
|
+
'&:hover svg[data-status="tertiary"]': {
|
|
88
|
+
fill: getColor({
|
|
89
|
+
tertiary: status?.tertiary,
|
|
90
|
+
isHover: true
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return wrapperClass;
|
|
95
|
+
};
|
|
96
|
+
const styles = {
|
|
97
|
+
badge: (0, _emotion.css)({
|
|
98
|
+
'&:focus': {
|
|
99
|
+
outline: 'none',
|
|
100
|
+
boxShadow: `inset ${_f36tokens.default.glowPrimary}`
|
|
101
|
+
}
|
|
102
|
+
}),
|
|
103
|
+
wrapper: (0, _emotion.css)({
|
|
104
|
+
'& svg': {
|
|
105
|
+
transition: 'fill 0.2s ease-in-out'
|
|
106
|
+
},
|
|
107
|
+
'& svg[data-status="tertiary"]': {
|
|
108
|
+
marginLeft: '-1px'
|
|
109
|
+
}
|
|
110
|
+
}),
|
|
111
|
+
popoverContent: (0, _emotion.css)({
|
|
112
|
+
maxWidth: '336px',
|
|
113
|
+
maxHeight: '368px',
|
|
114
|
+
overflowY: 'auto',
|
|
115
|
+
padding: `${_f36tokens.default.spacing2Xs} 0`
|
|
116
|
+
}),
|
|
117
|
+
skeletonBadge: (0, _emotion.css)({
|
|
118
|
+
flexShrink: 0,
|
|
119
|
+
display: 'block',
|
|
120
|
+
height: '20px',
|
|
121
|
+
width: '65px'
|
|
122
|
+
})
|
|
123
|
+
};
|
|
124
|
+
const determineBadgeStatus = (localesStatusMap, activeLocales)=>{
|
|
125
|
+
if (activeLocales && activeLocales.length === 1) {
|
|
126
|
+
const activeLocale = activeLocales.find((locale)=>localesStatusMap.has(locale.code));
|
|
127
|
+
return {
|
|
128
|
+
primary: localesStatusMap.get(activeLocale.code).status
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
let becomesDraftCount = 0, willPublishCount = 0, remainsDraftCount = 0;
|
|
132
|
+
for (const [localeCode, localeStatus] of localesStatusMap.entries()){
|
|
133
|
+
if (!activeLocales || activeLocales.find((selectedLocale)=>selectedLocale.code === localeCode)) {
|
|
134
|
+
switch(localeStatus.status){
|
|
135
|
+
case 'remainsDraft':
|
|
136
|
+
remainsDraftCount += 1;
|
|
137
|
+
break;
|
|
138
|
+
case 'becomesDraft':
|
|
139
|
+
becomesDraftCount += 1;
|
|
140
|
+
break;
|
|
141
|
+
case 'willPublish':
|
|
142
|
+
willPublishCount += 1;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const hasRemainsDraft = remainsDraftCount > 0;
|
|
148
|
+
const hasWillPublish = willPublishCount > 0;
|
|
149
|
+
const hasBecomesDraft = becomesDraftCount > 0;
|
|
150
|
+
switch(true){
|
|
151
|
+
case hasRemainsDraft && hasWillPublish && hasBecomesDraft:
|
|
152
|
+
return {
|
|
153
|
+
primary: 'becomesDraft',
|
|
154
|
+
secondary: 'willPublish',
|
|
155
|
+
tertiary: 'remainsDraft'
|
|
156
|
+
};
|
|
157
|
+
case hasRemainsDraft && hasWillPublish:
|
|
158
|
+
return {
|
|
159
|
+
primary: 'willPublish',
|
|
160
|
+
secondary: 'remainsDraft'
|
|
161
|
+
};
|
|
162
|
+
case hasRemainsDraft && hasBecomesDraft:
|
|
163
|
+
return {
|
|
164
|
+
primary: 'becomesDraft',
|
|
165
|
+
secondary: 'remainsDraft'
|
|
166
|
+
};
|
|
167
|
+
case hasWillPublish && hasBecomesDraft:
|
|
168
|
+
return {
|
|
169
|
+
primary: 'becomesDraft',
|
|
170
|
+
secondary: 'willPublish'
|
|
171
|
+
};
|
|
172
|
+
case hasWillPublish:
|
|
173
|
+
return {
|
|
174
|
+
primary: 'willPublish',
|
|
175
|
+
secondary: 'willPublish'
|
|
176
|
+
};
|
|
177
|
+
case hasBecomesDraft:
|
|
178
|
+
return {
|
|
179
|
+
primary: 'becomesDraft',
|
|
180
|
+
secondary: 'becomesDraft'
|
|
181
|
+
};
|
|
182
|
+
case hasRemainsDraft:
|
|
183
|
+
return {
|
|
184
|
+
primary: 'remainsDraft',
|
|
185
|
+
secondary: 'remainsDraft'
|
|
186
|
+
};
|
|
187
|
+
default:
|
|
188
|
+
return {
|
|
189
|
+
primary: 'notInRelease',
|
|
190
|
+
secondary: 'notInRelease'
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
function ReleaseEntityStatusPopover({ releaseLocalesStatusMap, activeLocales, isLoading = false }) {
|
|
195
|
+
const [isOpen, setIsOpen] = (0, _react.useState)(false);
|
|
196
|
+
const timeoutRef = (0, _react.useRef)();
|
|
197
|
+
const onMouseEnter = (0, _react.useCallback)(()=>{
|
|
198
|
+
clearTimeout(timeoutRef.current);
|
|
199
|
+
timeoutRef.current = setTimeout(()=>{
|
|
200
|
+
setIsOpen(true);
|
|
201
|
+
}, 300);
|
|
202
|
+
}, []);
|
|
203
|
+
const onMouseLeave = (0, _react.useCallback)(()=>{
|
|
204
|
+
clearTimeout(timeoutRef.current);
|
|
205
|
+
timeoutRef.current = setTimeout(()=>{
|
|
206
|
+
setIsOpen(false);
|
|
207
|
+
}, 300);
|
|
208
|
+
}, []);
|
|
209
|
+
const status = determineBadgeStatus(releaseLocalesStatusMap, activeLocales);
|
|
210
|
+
const ariaLabel = status.secondary ? 'Multiple statuses' : status.primary;
|
|
211
|
+
const wrapperClass = generateDynamicStyles(status);
|
|
212
|
+
const ArrowDownIcon = (0, _f36components.generateIcon)({
|
|
213
|
+
name: 'ArrowDownIcon',
|
|
214
|
+
viewBox: '0 0 12 20',
|
|
215
|
+
path: _react.default.createElement("path", {
|
|
216
|
+
d: "M3.03076 8C2.20109 8 1.73228 8.95209 2.23814 9.60971L5.20727 13.4696C5.60757 13.99 6.39223 13.99 6.79252 13.4696L9.76166 9.60971C10.2675 8.95209 9.79871 8 8.96904 8L3.03076 8Z",
|
|
217
|
+
fill: "currentColor"
|
|
218
|
+
})
|
|
219
|
+
});
|
|
220
|
+
if (isLoading) {
|
|
221
|
+
return _react.default.createElement(_f36components.Skeleton.Container, {
|
|
222
|
+
className: styles.skeletonBadge
|
|
223
|
+
}, _react.default.createElement(_f36components.Skeleton.Image, {
|
|
224
|
+
testId: `Release-entity-locale-status-badge-skeleton`,
|
|
225
|
+
width: "65px",
|
|
226
|
+
height: "20px"
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
return _react.default.createElement(_f36components.Popover, {
|
|
230
|
+
isOpen: releaseLocalesStatusMap && isOpen,
|
|
231
|
+
onClose: ()=>setIsOpen(false),
|
|
232
|
+
autoFocus: false,
|
|
233
|
+
placement: "bottom-end"
|
|
234
|
+
}, _react.default.createElement(_f36components.Popover.Trigger, null, _react.default.createElement(_f36components.Flex, {
|
|
235
|
+
"aria-label": ariaLabel,
|
|
236
|
+
alignItems: "center",
|
|
237
|
+
className: (0, _emotion.cx)(styles.wrapper, wrapperClass)
|
|
238
|
+
}, _react.default.createElement(_f36components.Badge, {
|
|
239
|
+
tabIndex: 0,
|
|
240
|
+
variant: _constants.RELEASE_BADGES[status.primary].variant,
|
|
241
|
+
onFocus: ()=>setIsOpen(true),
|
|
242
|
+
onBlur: ()=>setIsOpen(false),
|
|
243
|
+
endIcon: _react.default.createElement(ArrowDownIcon, {
|
|
244
|
+
color: _constants.RELEASE_BADGES[status.primary].icon
|
|
245
|
+
}),
|
|
246
|
+
onMouseOver: onMouseEnter,
|
|
247
|
+
onMouseEnter: onMouseEnter,
|
|
248
|
+
onMouseLeave: onMouseLeave
|
|
249
|
+
}, _constants.RELEASE_BADGES[status.primary].label), status.secondary && _react.default.createElement("svg", {
|
|
250
|
+
"data-status": "secondary",
|
|
251
|
+
"aria-hidden": "true",
|
|
252
|
+
width: "4",
|
|
253
|
+
height: "18",
|
|
254
|
+
viewBox: "0 0 4 18"
|
|
255
|
+
}, _react.default.createElement("path", {
|
|
256
|
+
fillRule: "evenodd",
|
|
257
|
+
clipRule: "evenodd",
|
|
258
|
+
d: "M1.45942e-06 18H0.00296171C2.2121 18 4.00296 16.2091 4.00296 14V4C4.00296 1.79086 2.2121 0 0.00295914 0H0C0.830421 0.732944 1.35418 1.80531 1.35418 3V15C1.35418 16.1947 0.830422 17.2671 1.45942e-06 18Z"
|
|
259
|
+
})), status.tertiary && _react.default.createElement("svg", {
|
|
260
|
+
"data-status": "tertiary",
|
|
261
|
+
"aria-hidden": "true",
|
|
262
|
+
width: "5",
|
|
263
|
+
height: "16",
|
|
264
|
+
viewBox: "0 0 5 16"
|
|
265
|
+
}, _react.default.createElement("path", {
|
|
266
|
+
fillRule: "evenodd",
|
|
267
|
+
clipRule: "evenodd",
|
|
268
|
+
d: "M0.673828 16.0055H0.675391C2.88453 16.0055 4.67539 14.2146 4.67539 12.0055V3.9955C4.67539 1.88216 3.03648 0.151608 0.960312 0.00549316C1.78382 0.738158 2.30257 1.80597 2.30257 2.99493V12.7838C2.30257 14.1053 1.66172 15.2771 0.673828 16.0055Z"
|
|
269
|
+
})))), _react.default.createElement(_f36components.Popover.Content, {
|
|
270
|
+
className: styles.popoverContent,
|
|
271
|
+
onMouseEnter: onMouseEnter,
|
|
272
|
+
onMouseLeave: onMouseLeave
|
|
273
|
+
}, !!releaseLocalesStatusMap && _react.default.createElement(_react.default.Fragment, null, _react.default.createElement(_ReleaseEntityStatusLocalesList.ReleaseEntityStatusLocalesList, {
|
|
274
|
+
statusMap: releaseLocalesStatusMap,
|
|
275
|
+
activeLocales: activeLocales
|
|
276
|
+
}))));
|
|
277
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "RELEASE_BADGES", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return RELEASE_BADGES;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _f36tokens = /*#__PURE__*/ _interop_require_default(require("@contentful/f36-tokens"));
|
|
12
|
+
function _interop_require_default(obj) {
|
|
13
|
+
return obj && obj.__esModule ? obj : {
|
|
14
|
+
default: obj
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const RELEASE_BADGES = {
|
|
18
|
+
willPublish: {
|
|
19
|
+
label: 'Will publish',
|
|
20
|
+
variant: 'positive',
|
|
21
|
+
default: _f36tokens.default.green300,
|
|
22
|
+
hover: _f36tokens.default.green400,
|
|
23
|
+
icon: _f36tokens.default.green400
|
|
24
|
+
},
|
|
25
|
+
becomesDraft: {
|
|
26
|
+
label: 'Becomes draft',
|
|
27
|
+
variant: 'warning',
|
|
28
|
+
default: _f36tokens.default.orange300,
|
|
29
|
+
hover: _f36tokens.default.orange400,
|
|
30
|
+
icon: _f36tokens.default.orange400
|
|
31
|
+
},
|
|
32
|
+
remainsDraft: {
|
|
33
|
+
label: 'Remains draft',
|
|
34
|
+
variant: 'secondary',
|
|
35
|
+
default: _f36tokens.default.gray300,
|
|
36
|
+
hover: _f36tokens.default.gray400,
|
|
37
|
+
icon: _f36tokens.default.gray400
|
|
38
|
+
},
|
|
39
|
+
notInRelease: {
|
|
40
|
+
label: 'Not in release',
|
|
41
|
+
variant: 'secondary',
|
|
42
|
+
default: _f36tokens.default.gray300,
|
|
43
|
+
hover: _f36tokens.default.gray400,
|
|
44
|
+
icon: _f36tokens.default.gray400
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
_export_star(require("./ReleaseEntityStatusPopover"), exports);
|
|
6
|
+
_export_star(require("./ReleaseEntityStatusBadge"), exports);
|
|
7
|
+
_export_star(require("./types"), exports);
|
|
8
|
+
function _export_star(from, to) {
|
|
9
|
+
Object.keys(from).forEach(function(k) {
|
|
10
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
11
|
+
Object.defineProperty(to, k, {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function() {
|
|
14
|
+
return from[k];
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return from;
|
|
20
|
+
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -114,6 +114,7 @@ const _shortenStorageUnit = require("./utils/shortenStorageUnit");
|
|
|
114
114
|
_export_star(require("./hooks/useLocalePublishStatus"), exports);
|
|
115
115
|
_export_star(require("./hooks/useActiveLocales"), exports);
|
|
116
116
|
_export_star(require("./LocalePublishingEntityStatusBadge"), exports);
|
|
117
|
+
_export_star(require("./ReleaseEntityStatusBadge"), exports);
|
|
117
118
|
const _ModalDialogLauncher = /*#__PURE__*/ _interop_require_wildcard(require("./ModalDialogLauncher"));
|
|
118
119
|
const _constraints = /*#__PURE__*/ _interop_require_wildcard(require("./utils/constraints"));
|
|
119
120
|
const _entityHelpers = /*#__PURE__*/ _interop_require_wildcard(require("./utils/entityHelpers"));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text } from '@contentful/f36-components';
|
|
3
|
+
import tokens from '@contentful/f36-tokens';
|
|
4
|
+
import { css } from 'emotion';
|
|
5
|
+
const styles = {
|
|
6
|
+
content: css({
|
|
7
|
+
display: 'block'
|
|
8
|
+
}),
|
|
9
|
+
banner: css({
|
|
10
|
+
background: tokens.gray100,
|
|
11
|
+
padding: tokens.spacingXs,
|
|
12
|
+
margin: `${tokens.spacingXs} ${tokens.spacingS}`,
|
|
13
|
+
borderRadius: tokens.borderRadiusSmall
|
|
14
|
+
})
|
|
15
|
+
};
|
|
16
|
+
export function Banner({ content, highlight }) {
|
|
17
|
+
return React.createElement("div", {
|
|
18
|
+
className: styles.banner
|
|
19
|
+
}, React.createElement(Text, {
|
|
20
|
+
fontSize: "fontSizeS",
|
|
21
|
+
fontColor: "gray700",
|
|
22
|
+
className: styles.content
|
|
23
|
+
}, content), highlight && React.createElement(Text, {
|
|
24
|
+
fontSize: "fontSizeS",
|
|
25
|
+
fontColor: "gray700",
|
|
26
|
+
as: "strong",
|
|
27
|
+
fontWeight: "fontWeightDemiBold"
|
|
28
|
+
}, highlight));
|
|
29
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Badge } from '@contentful/f36-components';
|
|
3
|
+
const config = {
|
|
4
|
+
publish: {
|
|
5
|
+
label: 'Will publish',
|
|
6
|
+
variant: 'positive'
|
|
7
|
+
},
|
|
8
|
+
unpublish: {
|
|
9
|
+
label: 'Becomes draft',
|
|
10
|
+
variant: 'warning'
|
|
11
|
+
},
|
|
12
|
+
'not-in-release': {
|
|
13
|
+
label: 'Not in release',
|
|
14
|
+
variant: 'secondary'
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export function ReleaseEntityStatusBadge({ className, action }) {
|
|
18
|
+
const badgeConfig = config[action];
|
|
19
|
+
return React.createElement(Badge, {
|
|
20
|
+
testId: "release-entity-action-status",
|
|
21
|
+
className: className,
|
|
22
|
+
variant: badgeConfig.variant
|
|
23
|
+
}, badgeConfig.label);
|
|
24
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Badge, Text } from '@contentful/f36-components';
|
|
3
|
+
import tokens from '@contentful/f36-tokens';
|
|
4
|
+
import { css } from 'emotion';
|
|
5
|
+
const styles = {
|
|
6
|
+
locale: css({
|
|
7
|
+
textOverflow: 'ellipsis',
|
|
8
|
+
overflow: 'hidden',
|
|
9
|
+
whiteSpace: 'nowrap'
|
|
10
|
+
}),
|
|
11
|
+
status: css({
|
|
12
|
+
flexShrink: 0
|
|
13
|
+
}),
|
|
14
|
+
localePublishStatus: css({
|
|
15
|
+
display: 'flex',
|
|
16
|
+
gap: tokens.spacingXs,
|
|
17
|
+
justifyContent: 'space-between',
|
|
18
|
+
padding: `${tokens.spacingXs} ${tokens.spacingS}`
|
|
19
|
+
})
|
|
20
|
+
};
|
|
21
|
+
export function ReleaseEntityStatusLocale({ locale, label, variant }) {
|
|
22
|
+
return React.createElement("div", {
|
|
23
|
+
className: styles.localePublishStatus,
|
|
24
|
+
"data-test-id": "locale-publishing-status"
|
|
25
|
+
}, React.createElement(Text, {
|
|
26
|
+
className: styles.locale,
|
|
27
|
+
fontColor: "gray700"
|
|
28
|
+
}, locale.name, ' ', React.createElement(Text, {
|
|
29
|
+
fontColor: "gray500"
|
|
30
|
+
}, "(", locale.code, ")", locale.default && ', Default')), React.createElement(Badge, {
|
|
31
|
+
className: styles.status,
|
|
32
|
+
variant: variant
|
|
33
|
+
}, label));
|
|
34
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MenuSectionTitle } from '@contentful/f36-components';
|
|
3
|
+
import { sortBy } from 'lodash';
|
|
4
|
+
import { Banner } from './Banner';
|
|
5
|
+
import { ReleaseEntityStatusLocale } from './ReleaseEntityStatusLocale';
|
|
6
|
+
function groupAndSortLocales(entries, activeLocales) {
|
|
7
|
+
const { selected, nonSelected } = entries.reduce((prev, [localeCode, localeStatusType])=>{
|
|
8
|
+
return activeLocales?.some((sl)=>sl.code === localeCode) ? {
|
|
9
|
+
...prev,
|
|
10
|
+
selected: [
|
|
11
|
+
...prev.selected,
|
|
12
|
+
localeStatusType
|
|
13
|
+
]
|
|
14
|
+
} : {
|
|
15
|
+
...prev,
|
|
16
|
+
nonSelected: [
|
|
17
|
+
...prev.nonSelected,
|
|
18
|
+
localeStatusType
|
|
19
|
+
]
|
|
20
|
+
};
|
|
21
|
+
}, {
|
|
22
|
+
selected: [],
|
|
23
|
+
nonSelected: []
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
selected: sortBy(selected, 'locale.name'),
|
|
27
|
+
nonSelected: nonSelected.sort((a, b)=>{
|
|
28
|
+
if (a.status === b.status) {
|
|
29
|
+
return a.locale.name.localeCompare(b.locale.name);
|
|
30
|
+
}
|
|
31
|
+
if (a.status === 'becomesDraft' || a.status === 'willPublish' && b.status === 'remainsDraft') {
|
|
32
|
+
return -1;
|
|
33
|
+
}
|
|
34
|
+
return 1;
|
|
35
|
+
})
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function ReleaseEntityStatusLocalesList({ statusMap, activeLocales }) {
|
|
39
|
+
const entries = [
|
|
40
|
+
...statusMap.entries()
|
|
41
|
+
];
|
|
42
|
+
const counters = entries.reduce((prev, [, { status }])=>({
|
|
43
|
+
becomesDraft: prev.becomesDraft + (status === 'becomesDraft' ? 1 : 0),
|
|
44
|
+
willPublish: prev.willPublish + (status === 'willPublish' ? 1 : 0),
|
|
45
|
+
remainsDraft: prev.remainsDraft + (status === 'remainsDraft' ? 1 : 0)
|
|
46
|
+
}), {
|
|
47
|
+
willPublish: 0,
|
|
48
|
+
becomesDraft: 0,
|
|
49
|
+
remainsDraft: 0
|
|
50
|
+
});
|
|
51
|
+
const { selected, nonSelected } = groupAndSortLocales(entries, activeLocales);
|
|
52
|
+
return React.createElement(React.Fragment, null, React.createElement(Banner, {
|
|
53
|
+
content: "The statuses of the locales for this content:",
|
|
54
|
+
highlight: `${counters.becomesDraft} becomes draft, ${counters.willPublish} will publish, ${counters.remainsDraft} remains draft`
|
|
55
|
+
}), React.createElement("div", {
|
|
56
|
+
"data-test-id": "locale-publishing-selected"
|
|
57
|
+
}, React.createElement(MenuSectionTitle, null, "Locales in the entry editor:"), selected.map(({ locale, label, variant })=>React.createElement(ReleaseEntityStatusLocale, {
|
|
58
|
+
key: `selected-${locale.code}`,
|
|
59
|
+
label: label,
|
|
60
|
+
variant: variant,
|
|
61
|
+
locale: locale
|
|
62
|
+
}))), nonSelected.length > 0 && React.createElement("div", {
|
|
63
|
+
"data-test-id": "locale-publishing-others"
|
|
64
|
+
}, React.createElement(MenuSectionTitle, null, "Other locales:"), nonSelected.map(({ locale, label, variant })=>React.createElement(ReleaseEntityStatusLocale, {
|
|
65
|
+
key: `others-${locale.code}`,
|
|
66
|
+
label: label,
|
|
67
|
+
variant: variant,
|
|
68
|
+
locale: locale
|
|
69
|
+
}))));
|
|
70
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import React, { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { Badge, Flex, generateIcon, Popover, Skeleton } from '@contentful/f36-components';
|
|
3
|
+
import tokens from '@contentful/f36-tokens';
|
|
4
|
+
import { cx, css } from 'emotion';
|
|
5
|
+
import { RELEASE_BADGES } from './constants';
|
|
6
|
+
import { ReleaseEntityStatusLocalesList } from './ReleaseEntityStatusLocalesList';
|
|
7
|
+
const getColor = ({ secondary, tertiary, isHover })=>{
|
|
8
|
+
const status = secondary || tertiary;
|
|
9
|
+
return isHover ? RELEASE_BADGES[status]?.hover : RELEASE_BADGES[status]?.default;
|
|
10
|
+
};
|
|
11
|
+
const generateDynamicStyles = (status)=>{
|
|
12
|
+
const wrapperClass = css({
|
|
13
|
+
'& svg[data-status="secondary"]': {
|
|
14
|
+
fill: getColor({
|
|
15
|
+
secondary: status?.secondary,
|
|
16
|
+
isHover: false
|
|
17
|
+
})
|
|
18
|
+
},
|
|
19
|
+
'& svg[data-status="tertiary"]': {
|
|
20
|
+
fill: getColor({
|
|
21
|
+
tertiary: status?.tertiary,
|
|
22
|
+
isHover: false
|
|
23
|
+
})
|
|
24
|
+
},
|
|
25
|
+
'&:hover svg[data-status="secondary"]': {
|
|
26
|
+
fill: getColor({
|
|
27
|
+
secondary: status?.secondary,
|
|
28
|
+
isHover: true
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
'&:hover svg[data-status="tertiary"]': {
|
|
32
|
+
fill: getColor({
|
|
33
|
+
tertiary: status?.tertiary,
|
|
34
|
+
isHover: true
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return wrapperClass;
|
|
39
|
+
};
|
|
40
|
+
const styles = {
|
|
41
|
+
badge: css({
|
|
42
|
+
'&:focus': {
|
|
43
|
+
outline: 'none',
|
|
44
|
+
boxShadow: `inset ${tokens.glowPrimary}`
|
|
45
|
+
}
|
|
46
|
+
}),
|
|
47
|
+
wrapper: css({
|
|
48
|
+
'& svg': {
|
|
49
|
+
transition: 'fill 0.2s ease-in-out'
|
|
50
|
+
},
|
|
51
|
+
'& svg[data-status="tertiary"]': {
|
|
52
|
+
marginLeft: '-1px'
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
popoverContent: css({
|
|
56
|
+
maxWidth: '336px',
|
|
57
|
+
maxHeight: '368px',
|
|
58
|
+
overflowY: 'auto',
|
|
59
|
+
padding: `${tokens.spacing2Xs} 0`
|
|
60
|
+
}),
|
|
61
|
+
skeletonBadge: css({
|
|
62
|
+
flexShrink: 0,
|
|
63
|
+
display: 'block',
|
|
64
|
+
height: '20px',
|
|
65
|
+
width: '65px'
|
|
66
|
+
})
|
|
67
|
+
};
|
|
68
|
+
const determineBadgeStatus = (localesStatusMap, activeLocales)=>{
|
|
69
|
+
if (activeLocales && activeLocales.length === 1) {
|
|
70
|
+
const activeLocale = activeLocales.find((locale)=>localesStatusMap.has(locale.code));
|
|
71
|
+
return {
|
|
72
|
+
primary: localesStatusMap.get(activeLocale.code).status
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
let becomesDraftCount = 0, willPublishCount = 0, remainsDraftCount = 0;
|
|
76
|
+
for (const [localeCode, localeStatus] of localesStatusMap.entries()){
|
|
77
|
+
if (!activeLocales || activeLocales.find((selectedLocale)=>selectedLocale.code === localeCode)) {
|
|
78
|
+
switch(localeStatus.status){
|
|
79
|
+
case 'remainsDraft':
|
|
80
|
+
remainsDraftCount += 1;
|
|
81
|
+
break;
|
|
82
|
+
case 'becomesDraft':
|
|
83
|
+
becomesDraftCount += 1;
|
|
84
|
+
break;
|
|
85
|
+
case 'willPublish':
|
|
86
|
+
willPublishCount += 1;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const hasRemainsDraft = remainsDraftCount > 0;
|
|
92
|
+
const hasWillPublish = willPublishCount > 0;
|
|
93
|
+
const hasBecomesDraft = becomesDraftCount > 0;
|
|
94
|
+
switch(true){
|
|
95
|
+
case hasRemainsDraft && hasWillPublish && hasBecomesDraft:
|
|
96
|
+
return {
|
|
97
|
+
primary: 'becomesDraft',
|
|
98
|
+
secondary: 'willPublish',
|
|
99
|
+
tertiary: 'remainsDraft'
|
|
100
|
+
};
|
|
101
|
+
case hasRemainsDraft && hasWillPublish:
|
|
102
|
+
return {
|
|
103
|
+
primary: 'willPublish',
|
|
104
|
+
secondary: 'remainsDraft'
|
|
105
|
+
};
|
|
106
|
+
case hasRemainsDraft && hasBecomesDraft:
|
|
107
|
+
return {
|
|
108
|
+
primary: 'becomesDraft',
|
|
109
|
+
secondary: 'remainsDraft'
|
|
110
|
+
};
|
|
111
|
+
case hasWillPublish && hasBecomesDraft:
|
|
112
|
+
return {
|
|
113
|
+
primary: 'becomesDraft',
|
|
114
|
+
secondary: 'willPublish'
|
|
115
|
+
};
|
|
116
|
+
case hasWillPublish:
|
|
117
|
+
return {
|
|
118
|
+
primary: 'willPublish',
|
|
119
|
+
secondary: 'willPublish'
|
|
120
|
+
};
|
|
121
|
+
case hasBecomesDraft:
|
|
122
|
+
return {
|
|
123
|
+
primary: 'becomesDraft',
|
|
124
|
+
secondary: 'becomesDraft'
|
|
125
|
+
};
|
|
126
|
+
case hasRemainsDraft:
|
|
127
|
+
return {
|
|
128
|
+
primary: 'remainsDraft',
|
|
129
|
+
secondary: 'remainsDraft'
|
|
130
|
+
};
|
|
131
|
+
default:
|
|
132
|
+
return {
|
|
133
|
+
primary: 'notInRelease',
|
|
134
|
+
secondary: 'notInRelease'
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
export function ReleaseEntityStatusPopover({ releaseLocalesStatusMap, activeLocales, isLoading = false }) {
|
|
139
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
140
|
+
const timeoutRef = useRef();
|
|
141
|
+
const onMouseEnter = useCallback(()=>{
|
|
142
|
+
clearTimeout(timeoutRef.current);
|
|
143
|
+
timeoutRef.current = setTimeout(()=>{
|
|
144
|
+
setIsOpen(true);
|
|
145
|
+
}, 300);
|
|
146
|
+
}, []);
|
|
147
|
+
const onMouseLeave = useCallback(()=>{
|
|
148
|
+
clearTimeout(timeoutRef.current);
|
|
149
|
+
timeoutRef.current = setTimeout(()=>{
|
|
150
|
+
setIsOpen(false);
|
|
151
|
+
}, 300);
|
|
152
|
+
}, []);
|
|
153
|
+
const status = determineBadgeStatus(releaseLocalesStatusMap, activeLocales);
|
|
154
|
+
const ariaLabel = status.secondary ? 'Multiple statuses' : status.primary;
|
|
155
|
+
const wrapperClass = generateDynamicStyles(status);
|
|
156
|
+
const ArrowDownIcon = generateIcon({
|
|
157
|
+
name: 'ArrowDownIcon',
|
|
158
|
+
viewBox: '0 0 12 20',
|
|
159
|
+
path: React.createElement("path", {
|
|
160
|
+
d: "M3.03076 8C2.20109 8 1.73228 8.95209 2.23814 9.60971L5.20727 13.4696C5.60757 13.99 6.39223 13.99 6.79252 13.4696L9.76166 9.60971C10.2675 8.95209 9.79871 8 8.96904 8L3.03076 8Z",
|
|
161
|
+
fill: "currentColor"
|
|
162
|
+
})
|
|
163
|
+
});
|
|
164
|
+
if (isLoading) {
|
|
165
|
+
return React.createElement(Skeleton.Container, {
|
|
166
|
+
className: styles.skeletonBadge
|
|
167
|
+
}, React.createElement(Skeleton.Image, {
|
|
168
|
+
testId: `Release-entity-locale-status-badge-skeleton`,
|
|
169
|
+
width: "65px",
|
|
170
|
+
height: "20px"
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
return React.createElement(Popover, {
|
|
174
|
+
isOpen: releaseLocalesStatusMap && isOpen,
|
|
175
|
+
onClose: ()=>setIsOpen(false),
|
|
176
|
+
autoFocus: false,
|
|
177
|
+
placement: "bottom-end"
|
|
178
|
+
}, React.createElement(Popover.Trigger, null, React.createElement(Flex, {
|
|
179
|
+
"aria-label": ariaLabel,
|
|
180
|
+
alignItems: "center",
|
|
181
|
+
className: cx(styles.wrapper, wrapperClass)
|
|
182
|
+
}, React.createElement(Badge, {
|
|
183
|
+
tabIndex: 0,
|
|
184
|
+
variant: RELEASE_BADGES[status.primary].variant,
|
|
185
|
+
onFocus: ()=>setIsOpen(true),
|
|
186
|
+
onBlur: ()=>setIsOpen(false),
|
|
187
|
+
endIcon: React.createElement(ArrowDownIcon, {
|
|
188
|
+
color: RELEASE_BADGES[status.primary].icon
|
|
189
|
+
}),
|
|
190
|
+
onMouseOver: onMouseEnter,
|
|
191
|
+
onMouseEnter: onMouseEnter,
|
|
192
|
+
onMouseLeave: onMouseLeave
|
|
193
|
+
}, RELEASE_BADGES[status.primary].label), status.secondary && React.createElement("svg", {
|
|
194
|
+
"data-status": "secondary",
|
|
195
|
+
"aria-hidden": "true",
|
|
196
|
+
width: "4",
|
|
197
|
+
height: "18",
|
|
198
|
+
viewBox: "0 0 4 18"
|
|
199
|
+
}, React.createElement("path", {
|
|
200
|
+
fillRule: "evenodd",
|
|
201
|
+
clipRule: "evenodd",
|
|
202
|
+
d: "M1.45942e-06 18H0.00296171C2.2121 18 4.00296 16.2091 4.00296 14V4C4.00296 1.79086 2.2121 0 0.00295914 0H0C0.830421 0.732944 1.35418 1.80531 1.35418 3V15C1.35418 16.1947 0.830422 17.2671 1.45942e-06 18Z"
|
|
203
|
+
})), status.tertiary && React.createElement("svg", {
|
|
204
|
+
"data-status": "tertiary",
|
|
205
|
+
"aria-hidden": "true",
|
|
206
|
+
width: "5",
|
|
207
|
+
height: "16",
|
|
208
|
+
viewBox: "0 0 5 16"
|
|
209
|
+
}, React.createElement("path", {
|
|
210
|
+
fillRule: "evenodd",
|
|
211
|
+
clipRule: "evenodd",
|
|
212
|
+
d: "M0.673828 16.0055H0.675391C2.88453 16.0055 4.67539 14.2146 4.67539 12.0055V3.9955C4.67539 1.88216 3.03648 0.151608 0.960312 0.00549316C1.78382 0.738158 2.30257 1.80597 2.30257 2.99493V12.7838C2.30257 14.1053 1.66172 15.2771 0.673828 16.0055Z"
|
|
213
|
+
})))), React.createElement(Popover.Content, {
|
|
214
|
+
className: styles.popoverContent,
|
|
215
|
+
onMouseEnter: onMouseEnter,
|
|
216
|
+
onMouseLeave: onMouseLeave
|
|
217
|
+
}, !!releaseLocalesStatusMap && React.createElement(React.Fragment, null, React.createElement(ReleaseEntityStatusLocalesList, {
|
|
218
|
+
statusMap: releaseLocalesStatusMap,
|
|
219
|
+
activeLocales: activeLocales
|
|
220
|
+
}))));
|
|
221
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import tokens from '@contentful/f36-tokens';
|
|
2
|
+
export const RELEASE_BADGES = {
|
|
3
|
+
willPublish: {
|
|
4
|
+
label: 'Will publish',
|
|
5
|
+
variant: 'positive',
|
|
6
|
+
default: tokens.green300,
|
|
7
|
+
hover: tokens.green400,
|
|
8
|
+
icon: tokens.green400
|
|
9
|
+
},
|
|
10
|
+
becomesDraft: {
|
|
11
|
+
label: 'Becomes draft',
|
|
12
|
+
variant: 'warning',
|
|
13
|
+
default: tokens.orange300,
|
|
14
|
+
hover: tokens.orange400,
|
|
15
|
+
icon: tokens.orange400
|
|
16
|
+
},
|
|
17
|
+
remainsDraft: {
|
|
18
|
+
label: 'Remains draft',
|
|
19
|
+
variant: 'secondary',
|
|
20
|
+
default: tokens.gray300,
|
|
21
|
+
hover: tokens.gray400,
|
|
22
|
+
icon: tokens.gray400
|
|
23
|
+
},
|
|
24
|
+
notInRelease: {
|
|
25
|
+
label: 'Not in release',
|
|
26
|
+
variant: 'secondary',
|
|
27
|
+
default: tokens.gray300,
|
|
28
|
+
hover: tokens.gray400,
|
|
29
|
+
icon: tokens.gray400
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/esm/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { ModalDialogLauncher };
|
|
|
12
12
|
export { entityHelpers };
|
|
13
13
|
export { ConstraintsUtils };
|
|
14
14
|
export * from './LocalePublishingEntityStatusBadge';
|
|
15
|
+
export * from './ReleaseEntityStatusBadge';
|
|
15
16
|
import * as ModalDialogLauncher from './ModalDialogLauncher';
|
|
16
17
|
import * as ConstraintsUtils from './utils/constraints';
|
|
17
18
|
import * as entityHelpers from './utils/entityHelpers';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ReleaseAction } from './types';
|
|
3
|
+
type ReleaseEntityActionBadgeProps = {
|
|
4
|
+
action: ReleaseAction;
|
|
5
|
+
className?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function ReleaseEntityStatusBadge({ className, action }: ReleaseEntityActionBadgeProps): React.JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BadgeVariant } from '@contentful/f36-components';
|
|
3
|
+
import type { LocaleProps } from 'contentful-management';
|
|
4
|
+
type ReleaseEntityStatusLocaleProps = {
|
|
5
|
+
locale: Pick<LocaleProps, 'code' | 'default' | 'name'>;
|
|
6
|
+
label: string;
|
|
7
|
+
variant: BadgeVariant;
|
|
8
|
+
};
|
|
9
|
+
export declare function ReleaseEntityStatusLocale({ locale, label, variant, }: ReleaseEntityStatusLocaleProps): React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { LocaleProps } from 'contentful-management';
|
|
3
|
+
import { ReleaseLocalesStatusMap } from './types';
|
|
4
|
+
type ReleaseEntityStatusLocalesListProps = {
|
|
5
|
+
statusMap: ReleaseLocalesStatusMap;
|
|
6
|
+
activeLocales?: Pick<LocaleProps, 'code'>[];
|
|
7
|
+
};
|
|
8
|
+
export declare function ReleaseEntityStatusLocalesList({ statusMap, activeLocales, }: ReleaseEntityStatusLocalesListProps): React.JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { LocaleProps } from 'contentful-management';
|
|
3
|
+
import type { ReleaseLocalesStatusMap } from './types';
|
|
4
|
+
type ReleaseLocalePublishingPopoverProps = {
|
|
5
|
+
releaseLocalesStatusMap: ReleaseLocalesStatusMap;
|
|
6
|
+
activeLocales: Pick<LocaleProps, 'code'>[];
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function ReleaseEntityStatusPopover({ releaseLocalesStatusMap, activeLocales, isLoading, }: ReleaseLocalePublishingPopoverProps): React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const RELEASE_BADGES: {
|
|
2
|
+
readonly willPublish: {
|
|
3
|
+
readonly label: "Will publish";
|
|
4
|
+
readonly variant: "positive";
|
|
5
|
+
readonly default: string;
|
|
6
|
+
readonly hover: string;
|
|
7
|
+
readonly icon: string;
|
|
8
|
+
};
|
|
9
|
+
readonly becomesDraft: {
|
|
10
|
+
readonly label: "Becomes draft";
|
|
11
|
+
readonly variant: "warning";
|
|
12
|
+
readonly default: string;
|
|
13
|
+
readonly hover: string;
|
|
14
|
+
readonly icon: string;
|
|
15
|
+
};
|
|
16
|
+
readonly remainsDraft: {
|
|
17
|
+
readonly label: "Remains draft";
|
|
18
|
+
readonly variant: "secondary";
|
|
19
|
+
readonly default: string;
|
|
20
|
+
readonly hover: string;
|
|
21
|
+
readonly icon: string;
|
|
22
|
+
};
|
|
23
|
+
readonly notInRelease: {
|
|
24
|
+
readonly label: "Not in release";
|
|
25
|
+
readonly variant: "secondary";
|
|
26
|
+
readonly default: string;
|
|
27
|
+
readonly hover: string;
|
|
28
|
+
readonly icon: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BadgeVariant } from '@contentful/f36-components';
|
|
2
|
+
import { LocaleProps } from 'contentful-management/types';
|
|
3
|
+
export type ReleaseAction = 'publish' | 'unpublish' | 'not-in-release';
|
|
4
|
+
export type ReleaseEntityStatus = 'willPublish' | 'becomesDraft' | 'remainsDraft' | 'notInRelease';
|
|
5
|
+
export type ReleaseLocalesStatus = {
|
|
6
|
+
status: ReleaseEntityStatus;
|
|
7
|
+
variant: BadgeVariant;
|
|
8
|
+
label: string;
|
|
9
|
+
locale: LocaleProps;
|
|
10
|
+
};
|
|
11
|
+
export type ReleaseLocalesStatusMap = Map<string, ReleaseLocalesStatus>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { ModalDialogLauncher };
|
|
|
13
13
|
export { entityHelpers };
|
|
14
14
|
export { ConstraintsUtils };
|
|
15
15
|
export * from './LocalePublishingEntityStatusBadge';
|
|
16
|
+
export * from './ReleaseEntityStatusBadge';
|
|
16
17
|
import * as ModalDialogLauncher from './ModalDialogLauncher';
|
|
17
18
|
import * as ConstraintsUtils from './utils/constraints';
|
|
18
19
|
import * as entityHelpers from './utils/entityHelpers';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/field-editor-shared",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"registry": "https://npm.pkg.github.com/"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "5228c3bb1871807c1832459f03d17477e8beb75b"
|
|
59
59
|
}
|