blob: 809ed075c1698063f308bdf84f2f0b84b1710547 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
import { isEmpty } from 'lodash';
import { hasContent } from '~/lib/utils/text_utility';
/**
* @returns {Boolean} `true` if the app is editing an existing release.
* `false` if the app is creating a new release.
*/
export const isExistingRelease = state => {
return Boolean(state.tagName);
};
/**
* @param {Object} link The link to test
* @returns {Boolean} `true` if the release link is empty, i.e. it has
* empty (or whitespace-only) values for both `url` and `name`.
* Otherwise, `false`.
*/
const isEmptyReleaseLink = link => !hasContent(link.url) && !hasContent(link.name);
/** Returns all release links that aren't empty */
export const releaseLinksToCreate = state => {
if (!state.release) {
return [];
}
return state.release.assets.links.filter(l => !isEmptyReleaseLink(l));
};
/** Returns all release links that should be deleted */
export const releaseLinksToDelete = state => {
if (!state.originalRelease) {
return [];
}
return state.originalRelease.assets.links;
};
/** Returns all validation errors on the release object */
export const validationErrors = state => {
const errors = {
assets: {
links: {},
},
};
if (!state.release) {
return errors;
}
if (!state.release.tagName?.trim?.().length) {
errors.isTagNameEmpty = true;
}
// Each key of this object is a URL, and the value is an
// array of Release link objects that share this URL.
// This is used for detecting duplicate URLs.
const urlToLinksMap = new Map();
state.release.assets.links.forEach(link => {
errors.assets.links[link.id] = {};
// Only validate non-empty URLs
if (isEmptyReleaseLink(link)) {
return;
}
if (!hasContent(link.url)) {
errors.assets.links[link.id].isUrlEmpty = true;
}
if (!hasContent(link.name)) {
errors.assets.links[link.id].isNameEmpty = true;
}
const normalizedUrl = link.url.trim().toLowerCase();
// Compare each URL to every other URL and flag any duplicates
if (urlToLinksMap.has(normalizedUrl)) {
// a duplicate URL was found!
// add a validation error for each link that shares this URL
const duplicates = urlToLinksMap.get(normalizedUrl);
duplicates.push(link);
duplicates.forEach(duplicateLink => {
errors.assets.links[duplicateLink.id].isDuplicate = true;
});
} else {
// no duplicate URL was found
urlToLinksMap.set(normalizedUrl, [link]);
}
if (!/^(http|https|ftp):\/\//.test(normalizedUrl)) {
errors.assets.links[link.id].isBadFormat = true;
}
});
return errors;
};
/** Returns whether or not the release object is valid */
export const isValid = (_state, getters) => {
const errors = getters.validationErrors;
return Object.values(errors.assets.links).every(isEmpty) && !errors.isTagNameEmpty;
};
|