adapt-authoring-ui 2.0.6 → 3.0.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.
- package/.github/workflows/releases.yml +9 -24
- package/app/modules/editor/article/index.js +1 -0
- package/app/modules/editor/block/index.js +1 -0
- package/app/modules/editor/component/index.js +1 -0
- package/app/modules/editor/config/index.js +1 -0
- package/app/modules/editor/contentObject/index.js +1 -0
- package/app/modules/editor/contentObject/views/editorMenuView.js +13 -2
- package/app/modules/editor/course/index.js +1 -0
- package/app/modules/editor/global/editorDataLoader.js +71 -28
- package/app/modules/editor/global/views/editorView.js +6 -13
- package/app/modules/editor/menuSettings/index.js +0 -1
- package/app/modules/editor/themeEditor/index.js +5 -1
- package/app/modules/frameworkImport/views/frameworkImportView.js +1 -1
- package/lib/UiModule.js +13 -0
- package/package.json +6 -30
|
@@ -1,32 +1,17 @@
|
|
|
1
1
|
name: Release
|
|
2
|
+
|
|
2
3
|
on:
|
|
3
4
|
push:
|
|
4
5
|
branches:
|
|
5
6
|
- master
|
|
6
7
|
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
issues: write
|
|
11
|
+
pull-requests: write
|
|
12
|
+
id-token: write
|
|
13
|
+
packages: write
|
|
14
|
+
|
|
7
15
|
jobs:
|
|
8
16
|
release:
|
|
9
|
-
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
permissions:
|
|
12
|
-
contents: write # to be able to publish a GitHub release
|
|
13
|
-
issues: write # to be able to comment on released issues
|
|
14
|
-
pull-requests: write # to be able to comment on released pull requests
|
|
15
|
-
id-token: write # to enable use of OIDC for trusted publishing and npm provenance
|
|
16
|
-
steps:
|
|
17
|
-
- name: Checkout
|
|
18
|
-
uses: actions/checkout@v3
|
|
19
|
-
with:
|
|
20
|
-
fetch-depth: 0
|
|
21
|
-
- name: Setup Node.js
|
|
22
|
-
uses: actions/setup-node@v3
|
|
23
|
-
with:
|
|
24
|
-
node-version: 'lts/*'
|
|
25
|
-
- name: Update npm
|
|
26
|
-
run: npm install -g npm@latest
|
|
27
|
-
- name: Install dependencies
|
|
28
|
-
run: npm install
|
|
29
|
-
- name: Release
|
|
30
|
-
env:
|
|
31
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
32
|
-
run: npx semantic-release
|
|
17
|
+
uses: adaptlearning/semantic-release-config/.github/workflows/release.yml@master
|
|
@@ -10,6 +10,7 @@ define(function(require) {
|
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
var model = Origin.editor.data.content.findWhere({ _id: data.id });
|
|
13
|
+
await model.fetch();
|
|
13
14
|
var form = await Origin.scaffold.buildForm({ model });
|
|
14
15
|
Helpers.setPageTitle(model);
|
|
15
16
|
Origin.sidebar.addView(new EditorArticleEditSidebarView({ model, form }).$el);
|
|
@@ -10,6 +10,7 @@ define(function(require) {
|
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
var model = Origin.editor.data.content.findWhere({ _id: data.id });
|
|
13
|
+
await model.fetch();
|
|
13
14
|
var form = await Origin.scaffold.buildForm({ model });
|
|
14
15
|
Helpers.setPageTitle(model);
|
|
15
16
|
Origin.sidebar.addView(new EditorBlockEditSidebarView({ model, form }).$el);
|
|
@@ -14,6 +14,7 @@ define(function(require) {
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
const model = _id === 'new' ? Origin.editor.data.newcomponent : Origin.editor.data.content.findWhere({ _id });
|
|
17
|
+
if (_id !== 'new') await model.fetch();
|
|
17
18
|
const form = await Origin.scaffold.buildForm({ model });
|
|
18
19
|
Helpers.setPageTitle(model);
|
|
19
20
|
Origin.sidebar.addView(new EditorComponentEditSidebarView({ model, form }).$el);
|
|
@@ -7,6 +7,7 @@ define(function(require) {
|
|
|
7
7
|
|
|
8
8
|
Origin.on('editor:config', async function(data) {
|
|
9
9
|
var model = Origin.editor.data.config;
|
|
10
|
+
await model.fetch();
|
|
10
11
|
var form = await Origin.scaffold.buildForm({ model });
|
|
11
12
|
Helpers.setPageTitle(model);
|
|
12
13
|
Origin.sidebar.addView(new EditorConfigEditSidebarView({ form }).$el);
|
|
@@ -30,6 +30,7 @@ define(function(require) {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
async function renderContentObjectEdit(data) {
|
|
33
|
+
await data.model.fetch();
|
|
33
34
|
Helpers.setPageTitle(data.model);
|
|
34
35
|
var form = await Origin.scaffold.buildForm({ model: data.model });
|
|
35
36
|
Origin.sidebar.addView(new EditorPageEditSidebarView({ form: form }).$el);
|
|
@@ -199,8 +199,19 @@ define(function(require){
|
|
|
199
199
|
this.contentobjects.add(newModel);
|
|
200
200
|
},
|
|
201
201
|
|
|
202
|
-
onItemDeleted:
|
|
203
|
-
|
|
202
|
+
onItemDeleted: function(oldModel) {
|
|
203
|
+
var content = Origin.editor.data.content;
|
|
204
|
+
var removeDescendants = function(parentId) {
|
|
205
|
+
content.where({ _parentId: parentId }).forEach(function(child) {
|
|
206
|
+
removeDescendants(child.get('_id'));
|
|
207
|
+
content.remove(child);
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
removeDescendants(oldModel.get('_id'));
|
|
211
|
+
content.remove(oldModel);
|
|
212
|
+
this.contentobjects = new Backbone.Collection(content.filter(function(c) {
|
|
213
|
+
return c.get('_type') === 'menu' || c.get('_type') === 'page';
|
|
214
|
+
}));
|
|
204
215
|
Origin.trigger('editorView:menuView:updateSelectedItem', this.contentobjects.findWhere({ _id: oldModel.get('_parentId') }));
|
|
205
216
|
}
|
|
206
217
|
}, {
|
|
@@ -10,6 +10,7 @@ define(function(require) {
|
|
|
10
10
|
Origin.on('editor:course', renderCourseEdit);
|
|
11
11
|
|
|
12
12
|
async function renderCourseEdit() {
|
|
13
|
+
await Origin.editor.data.course.fetch();
|
|
13
14
|
EditorHelpers.setPageTitle(Origin.editor.data.course);
|
|
14
15
|
var form = await Origin.scaffold.buildForm({ model: Origin.editor.data.course });
|
|
15
16
|
Origin.contentPane.setView(EditorCourseEditView, { model: Origin.editor.data.course, form });
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// LICENCE https://github.com/adaptlearning/adapt_authoring/blob/master/LICENSE
|
|
2
2
|
define(function(require) {
|
|
3
3
|
var _ = require('underscore');
|
|
4
|
-
var
|
|
4
|
+
var Backbone = require('backbone');
|
|
5
|
+
var ContentModel = require('core/models/contentModel');
|
|
5
6
|
var ContentPluginCollection = require('core/collections/contentPluginCollection');
|
|
6
7
|
var Origin = require('core/origin');
|
|
7
8
|
|
|
8
9
|
var isLoaded;
|
|
10
|
+
var lastModified;
|
|
9
11
|
|
|
10
12
|
var Preloader = {
|
|
11
13
|
/**
|
|
@@ -21,35 +23,19 @@ define(function(require) {
|
|
|
21
23
|
|
|
22
24
|
isLoaded = false;
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
try {
|
|
27
|
+
var treeData = await isOutdated();
|
|
28
|
+
if(treeData) {
|
|
26
29
|
await Promise.all([
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
content.queryOptions = { limit: 0 };
|
|
30
|
-
await content.fetch();
|
|
31
|
-
Origin.editor.data.content = content;
|
|
32
|
-
Origin.editor.data.course = content.findWhere({ _type: 'course' });
|
|
33
|
-
Origin.editor.data.config = content.findWhere({ _type: 'config' });
|
|
34
|
-
if(!Origin.editor.data.course || !Origin.editor.data.config) {
|
|
35
|
-
return handleError();
|
|
36
|
-
}
|
|
37
|
-
resolve()
|
|
38
|
-
}),
|
|
39
|
-
new Promise (async (resolve) => {
|
|
40
|
-
const componentTypes = new ContentPluginCollection(undefined, { type: 'component' });
|
|
41
|
-
await componentTypes.fetch();
|
|
42
|
-
Origin.editor.data.componentTypes = componentTypes;
|
|
43
|
-
resolve()
|
|
44
|
-
})
|
|
30
|
+
loadTree(treeData),
|
|
31
|
+
loadComponentTypes()
|
|
45
32
|
]);
|
|
46
|
-
} catch(e) {
|
|
47
|
-
return handleError();
|
|
48
33
|
}
|
|
34
|
+
} catch(e) {
|
|
35
|
+
return handleError();
|
|
49
36
|
}
|
|
50
37
|
isLoaded = true;
|
|
51
38
|
|
|
52
|
-
Origin.editor.data.lastFetch = new Date().toISOString();
|
|
53
39
|
if(_.isFunction(callback)) {
|
|
54
40
|
callback();
|
|
55
41
|
}
|
|
@@ -60,6 +46,7 @@ define(function(require) {
|
|
|
60
46
|
Origin.editor.data.course = undefined;
|
|
61
47
|
Origin.editor.data.config = undefined;
|
|
62
48
|
}
|
|
49
|
+
lastModified = undefined;
|
|
63
50
|
},
|
|
64
51
|
/**
|
|
65
52
|
* Makes sure all data has been loaded and calls callback
|
|
@@ -69,18 +56,74 @@ define(function(require) {
|
|
|
69
56
|
}
|
|
70
57
|
};
|
|
71
58
|
|
|
59
|
+
async function loadTree(treeData) {
|
|
60
|
+
var items, resLastModified;
|
|
61
|
+
if(treeData && treeData.items) {
|
|
62
|
+
items = treeData.items;
|
|
63
|
+
resLastModified = treeData.lastModified;
|
|
64
|
+
} else {
|
|
65
|
+
var courseId = Origin.location.route1;
|
|
66
|
+
await new Promise(function(resolve, reject) {
|
|
67
|
+
$.ajax({
|
|
68
|
+
url: '/api/content/tree/' + courseId,
|
|
69
|
+
success: function(data, textStatus, jqXHR) {
|
|
70
|
+
items = data;
|
|
71
|
+
resLastModified = jqXHR.getResponseHeader('Last-Modified');
|
|
72
|
+
resolve();
|
|
73
|
+
},
|
|
74
|
+
error: function() { reject(new Error('Failed to fetch content tree')); }
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
lastModified = resLastModified;
|
|
79
|
+
var content = new Backbone.Collection(items.map(function(item) {
|
|
80
|
+
return new ContentModel(item);
|
|
81
|
+
}), {
|
|
82
|
+
model: ContentModel,
|
|
83
|
+
comparator: '_sortOrder'
|
|
84
|
+
});
|
|
85
|
+
Origin.editor.data.content = content;
|
|
86
|
+
Origin.editor.data.course = content.findWhere({ _type: 'course' });
|
|
87
|
+
Origin.editor.data.config = content.findWhere({ _type: 'config' });
|
|
88
|
+
if(!Origin.editor.data.course || !Origin.editor.data.config) {
|
|
89
|
+
return handleError();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function loadComponentTypes() {
|
|
94
|
+
var componentTypes = new ContentPluginCollection(undefined, { type: 'component' });
|
|
95
|
+
await componentTypes.fetch();
|
|
96
|
+
Origin.editor.data.componentTypes = componentTypes;
|
|
97
|
+
}
|
|
98
|
+
|
|
72
99
|
async function isOutdated() {
|
|
73
100
|
try {
|
|
74
101
|
if(Origin.editor.data.course.get('_id') !== Origin.location.route1) {
|
|
75
|
-
|
|
102
|
+
lastModified = undefined;
|
|
76
103
|
return true;
|
|
77
104
|
}
|
|
78
105
|
} catch(e) {
|
|
79
|
-
|
|
106
|
+
lastModified = undefined;
|
|
80
107
|
return true;
|
|
81
108
|
}
|
|
82
|
-
|
|
83
|
-
|
|
109
|
+
if(!lastModified) return true;
|
|
110
|
+
var courseId = Origin.editor.data.course.get('_id');
|
|
111
|
+
return new Promise(function(resolve, reject) {
|
|
112
|
+
$.ajax({
|
|
113
|
+
url: '/api/content/tree/' + courseId,
|
|
114
|
+
headers: { 'If-Modified-Since': lastModified },
|
|
115
|
+
complete: function(jqXHR) {
|
|
116
|
+
if(jqXHR.status === 304) return resolve(false);
|
|
117
|
+
if(jqXHR.status === 200) {
|
|
118
|
+
return resolve({
|
|
119
|
+
items: jqXHR.responseJSON,
|
|
120
|
+
lastModified: jqXHR.getResponseHeader('Last-Modified')
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
reject(new Error('Failed to check content staleness'));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
});
|
|
84
127
|
}
|
|
85
128
|
|
|
86
129
|
function handleError() {
|
|
@@ -195,19 +195,12 @@ define(function(require) {
|
|
|
195
195
|
},
|
|
196
196
|
|
|
197
197
|
copyIdToClipboard: function(model) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
});
|
|
205
|
-
} else {
|
|
206
|
-
Origin.Notify.alert({
|
|
207
|
-
type: 'warning',
|
|
208
|
-
text: Origin.l10n.t('app.copyidtoclipboarderror', { id: id })
|
|
209
|
-
});
|
|
210
|
-
}
|
|
198
|
+
const id = model.get('_friendlyId') || model.get('_id');
|
|
199
|
+
const isSuccess = helpers.copyStringToClipboard(id)
|
|
200
|
+
Origin.Notify.alert({
|
|
201
|
+
type: isSuccess ? 'info' : 'warning',
|
|
202
|
+
text: Origin.l10n.t(isSuccess ? 'app.copyidtoclipboardsuccess' : 'app.copyidtoclipboarderror', { id })
|
|
203
|
+
});
|
|
211
204
|
},
|
|
212
205
|
|
|
213
206
|
pasteFromClipboard: function(_parentId, _sortOrder, _layout) {
|
|
@@ -8,7 +8,11 @@ define(function(require) {
|
|
|
8
8
|
Origin.router.navigate(`#/editor/${Origin.editor.data.course.get('_id')}/${ROUTE}`, { trigger: true });
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
Origin.on('editor:selecttheme', () => {
|
|
11
|
+
Origin.on('editor:selecttheme', async () => {
|
|
12
|
+
await Promise.all([
|
|
13
|
+
Origin.editor.data.course.fetch(),
|
|
14
|
+
Origin.editor.data.config.fetch()
|
|
15
|
+
]);
|
|
12
16
|
Origin.sidebar.addView(new EditorThemingSidebarView().$el);
|
|
13
17
|
Origin.contentPane.setView(EditorThemingView);
|
|
14
18
|
});
|
|
@@ -76,7 +76,7 @@ define(function(require){
|
|
|
76
76
|
this.$('#tags').val(this.model.get('tags').map(t => t.title));
|
|
77
77
|
}
|
|
78
78
|
const data = await Helpers.submitForm(this.$('form.frameworkImport'), { data: { dryRun } })
|
|
79
|
-
return Object.assign(data, { canImport: data.statusReport.error
|
|
79
|
+
return Object.assign(data, { canImport: !data.statusReport.error?.length });
|
|
80
80
|
},
|
|
81
81
|
|
|
82
82
|
onAddTag: function (tag) {
|
package/lib/UiModule.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { AbstractModule, Hook } from 'adapt-authoring-core'
|
|
2
2
|
import path from 'path'
|
|
3
3
|
import UiBuild from './UiBuild.js'
|
|
4
|
+
|
|
5
|
+
const CSP_POLICY = [
|
|
6
|
+
"default-src 'self'",
|
|
7
|
+
"frame-ancestors 'self'",
|
|
8
|
+
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com https://cdn.ckeditor.com",
|
|
9
|
+
"style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.ckeditor.com",
|
|
10
|
+
"font-src 'self' data: https://cdnjs.cloudflare.com",
|
|
11
|
+
"img-src 'self' data: blob:",
|
|
12
|
+
"worker-src 'self' blob:",
|
|
13
|
+
"connect-src 'self' https://cdnjs.cloudflare.com https://cdn.ckeditor.com",
|
|
14
|
+
'upgrade-insecure-requests'
|
|
15
|
+
].join('; ')
|
|
4
16
|
/**
|
|
5
17
|
* The main entry-point for the Adapt authoring tool web-app/front-end
|
|
6
18
|
* @memberof ui
|
|
@@ -96,6 +108,7 @@ class UiModule extends AbstractModule {
|
|
|
96
108
|
servePage (pageName) {
|
|
97
109
|
return async (req, res, next) => {
|
|
98
110
|
const framework = await this.app.waitForModule('adaptframework')
|
|
111
|
+
res.setHeader('Content-Security-Policy', CSP_POLICY)
|
|
99
112
|
res.render(path.resolve(this.buildDir, pageName), {
|
|
100
113
|
buildType: this.isProduction ? 'production' : 'development',
|
|
101
114
|
versions: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adapt-authoring-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Front-end application for the Adapt authoring tool",
|
|
5
5
|
"homepage": "https://github.com/adapt-security/adapt-authoring-ui",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@rollup/plugin-babel": "^6.0.3",
|
|
21
21
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
22
22
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
23
|
-
"@rollup/plugin-terser": "^0.
|
|
23
|
+
"@rollup/plugin-terser": "^1.0.0",
|
|
24
24
|
"adapt-authoring-core": "^2.0.0",
|
|
25
25
|
"babel-plugin-transform-amd-to-es6": "^1.0.2",
|
|
26
26
|
"cpy": "^13.0.0",
|
|
@@ -38,40 +38,16 @@
|
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"adapt-authoring-adaptframework": "^2.0.0",
|
|
41
|
+
"adapt-authoring-authored": "^1.4.0",
|
|
42
|
+
"adapt-authoring-content": "^3.0.0",
|
|
41
43
|
"adapt-authoring-server": "^2.0.0"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
|
-
"@semantic-release
|
|
45
|
-
"conventional-changelog-eslint": "^6.0.0",
|
|
46
|
-
"semantic-release": "^25.0.2",
|
|
46
|
+
"@adaptlearning/semantic-release-config": "^1.0.0",
|
|
47
47
|
"standard": "^17.1.0"
|
|
48
48
|
},
|
|
49
49
|
"release": {
|
|
50
|
-
"
|
|
51
|
-
[
|
|
52
|
-
"@semantic-release/commit-analyzer",
|
|
53
|
-
{
|
|
54
|
-
"preset": "eslint"
|
|
55
|
-
}
|
|
56
|
-
],
|
|
57
|
-
[
|
|
58
|
-
"@semantic-release/release-notes-generator",
|
|
59
|
-
{
|
|
60
|
-
"preset": "eslint"
|
|
61
|
-
}
|
|
62
|
-
],
|
|
63
|
-
"@semantic-release/npm",
|
|
64
|
-
"@semantic-release/github",
|
|
65
|
-
[
|
|
66
|
-
"@semantic-release/git",
|
|
67
|
-
{
|
|
68
|
-
"assets": [
|
|
69
|
-
"package.json"
|
|
70
|
-
],
|
|
71
|
-
"message": "Chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
72
|
-
}
|
|
73
|
-
]
|
|
74
|
-
]
|
|
50
|
+
"extends": "@adaptlearning/semantic-release-config"
|
|
75
51
|
},
|
|
76
52
|
"standard": {
|
|
77
53
|
"ignore": [
|