@tanglemedia/directus-collection-testimonial 0.0.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/README.md +29 -0
- package/dist/index.js +34 -0
- package/migrations/20260301A-tngl_testimonial-~-add-testimonial-table.mjs +39 -0
- package/migrations/20260301B-tngl_testimonial-~-register-testimonial-collection-and-fields.mjs +128 -0
- package/migrations/20260301C-tngl_testimonial-~-set-permissions.mjs +10 -0
- package/migrations/20260301D-tngl_testimonial-~-set-default-presets.mjs +47 -0
- package/migrations/20260301E-tngl_testimonial-~-add-initial-content.mjs +33 -0
- package/package.json +47 -0
- package/src/index.js +8 -0
- package/src/shared/utility/migrations.js +30 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const COLLECTION_NAME = "tngl_testimonial";
|
|
2
|
+
|
|
3
|
+
export async function up(knex) {
|
|
4
|
+
// if table exists, do not proceed with migration
|
|
5
|
+
if (await knex.schema.hasTable(COLLECTION_NAME)) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// create table
|
|
10
|
+
await knex.schema.createTable(COLLECTION_NAME, (table) => {
|
|
11
|
+
table.increments("id").unsigned().notNullable();
|
|
12
|
+
|
|
13
|
+
// default fields
|
|
14
|
+
table.integer("sort").nullable();
|
|
15
|
+
table.string("status", 255).notNullable().defaultTo("draft");
|
|
16
|
+
|
|
17
|
+
// accountability fields
|
|
18
|
+
table.specificType("user_created", "char(36)").nullable();
|
|
19
|
+
table.specificType("user_updated", "char(36)").nullable();
|
|
20
|
+
table.timestamp("date_created").nullable();
|
|
21
|
+
table.timestamp("date_updated").nullable();
|
|
22
|
+
|
|
23
|
+
// custom fields
|
|
24
|
+
table.string("author", 255).nullable();
|
|
25
|
+
table.text("comment").nullable();
|
|
26
|
+
table.date("comment_date").nullable();
|
|
27
|
+
|
|
28
|
+
table.primary(["id"]);
|
|
29
|
+
|
|
30
|
+
// relationships
|
|
31
|
+
table.foreign("user_created").references("id").inTable("directus_users");
|
|
32
|
+
table.foreign("user_updated").references("id").inTable("directus_users");
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function down(knex) {
|
|
37
|
+
// drop table
|
|
38
|
+
await knex.schema.dropTableIfExists(COLLECTION_NAME);
|
|
39
|
+
}
|
package/migrations/20260301B-tngl_testimonial-~-register-testimonial-collection-and-fields.mjs
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { getBasicCollectionFields } from "./helpers/fields.mjs";
|
|
2
|
+
|
|
3
|
+
const COLLECTION_NAME = "tngl_testimonial";
|
|
4
|
+
|
|
5
|
+
const COLLECTION_INSERTS = [
|
|
6
|
+
{
|
|
7
|
+
accountability: "all",
|
|
8
|
+
archive_app_filter: true,
|
|
9
|
+
archive_field: "status",
|
|
10
|
+
archive_value: "archived",
|
|
11
|
+
collapse: "open",
|
|
12
|
+
collection: COLLECTION_NAME,
|
|
13
|
+
color: null,
|
|
14
|
+
display_template: "{{status}} {{comment}}",
|
|
15
|
+
group: null,
|
|
16
|
+
hidden: false,
|
|
17
|
+
icon: "comment",
|
|
18
|
+
item_duplication_fields: null,
|
|
19
|
+
note: null,
|
|
20
|
+
preview_url: null,
|
|
21
|
+
singleton: false,
|
|
22
|
+
sort: null,
|
|
23
|
+
sort_field: "sort",
|
|
24
|
+
unarchive_value: "draft",
|
|
25
|
+
versioning: false,
|
|
26
|
+
translations: JSON.stringify([
|
|
27
|
+
{
|
|
28
|
+
language: "en-US",
|
|
29
|
+
translation: "Testimonials",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
language: "en-CA",
|
|
33
|
+
translation: "Testimonials",
|
|
34
|
+
},
|
|
35
|
+
]),
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
const FIELD_INSERTS = [
|
|
39
|
+
...getBasicCollectionFields(COLLECTION_NAME),
|
|
40
|
+
{
|
|
41
|
+
collection: COLLECTION_NAME,
|
|
42
|
+
conditions: null,
|
|
43
|
+
display: null,
|
|
44
|
+
display_options: null,
|
|
45
|
+
field: "author",
|
|
46
|
+
group: null,
|
|
47
|
+
hidden: false,
|
|
48
|
+
interface: "input",
|
|
49
|
+
note: null,
|
|
50
|
+
options: null,
|
|
51
|
+
readonly: false,
|
|
52
|
+
required: false,
|
|
53
|
+
sort: 8,
|
|
54
|
+
special: null,
|
|
55
|
+
translations: null,
|
|
56
|
+
validation: null,
|
|
57
|
+
validation_message: null,
|
|
58
|
+
width: "full",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
collection: COLLECTION_NAME,
|
|
62
|
+
conditions: null,
|
|
63
|
+
display: null,
|
|
64
|
+
display_options: null,
|
|
65
|
+
field: "comment",
|
|
66
|
+
group: null,
|
|
67
|
+
hidden: false,
|
|
68
|
+
interface: "input-multiline",
|
|
69
|
+
note: null,
|
|
70
|
+
options: null,
|
|
71
|
+
readonly: false,
|
|
72
|
+
required: false,
|
|
73
|
+
sort: 9,
|
|
74
|
+
special: null,
|
|
75
|
+
translations: null,
|
|
76
|
+
validation: null,
|
|
77
|
+
validation_message: null,
|
|
78
|
+
width: "full",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
collection: COLLECTION_NAME,
|
|
82
|
+
conditions: null,
|
|
83
|
+
display: "datetime",
|
|
84
|
+
display_options: JSON.stringify({}),
|
|
85
|
+
field: "comment_date",
|
|
86
|
+
group: null,
|
|
87
|
+
hidden: false,
|
|
88
|
+
interface: "datetime",
|
|
89
|
+
note: null,
|
|
90
|
+
options: JSON.stringify({
|
|
91
|
+
use24: false,
|
|
92
|
+
}),
|
|
93
|
+
readonly: false,
|
|
94
|
+
required: false,
|
|
95
|
+
sort: 10,
|
|
96
|
+
special: null,
|
|
97
|
+
translations: null,
|
|
98
|
+
validation: null,
|
|
99
|
+
validation_message: null,
|
|
100
|
+
width: "full",
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
export async function up(knex) {
|
|
105
|
+
// if row exists in directus_collections table, do not proceed with migration
|
|
106
|
+
const collectionExists = await knex("directus_collections")
|
|
107
|
+
.select("collection")
|
|
108
|
+
.where("collection", COLLECTION_NAME)
|
|
109
|
+
.first();
|
|
110
|
+
|
|
111
|
+
// register table into `directus_collections` table
|
|
112
|
+
// for full list of directus_collections properties, refer to: https://docs.directus.io/reference/system/collections.html
|
|
113
|
+
if (!collectionExists) {
|
|
114
|
+
await knex("directus_collections").insert(COLLECTION_INSERTS);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// register fields into `directus_fields` table
|
|
118
|
+
// for full list of directus_fields properties, refer to: https://docs.directus.io/reference/system/fields.html
|
|
119
|
+
await knex("directus_fields").insert(FIELD_INSERTS);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function down(knex) {
|
|
123
|
+
// remove associated data from directus_fields table
|
|
124
|
+
await knex("directus_fields").where("collection", COLLECTION_NAME).del();
|
|
125
|
+
|
|
126
|
+
// remove associated data from directus_collections table
|
|
127
|
+
await knex("directus_collections").where("collection", COLLECTION_NAME).del();
|
|
128
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createPermission } from "./helpers/permission.mjs";
|
|
2
|
+
|
|
3
|
+
export async function up(knex) {
|
|
4
|
+
await createPermission(knex, "tngl_testimonial", "Website", ["read"]);
|
|
5
|
+
await createPermission(knex, "tngl_testimonial", "Staff", ["create", "read", "update", "delete"]);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function down(knex) {
|
|
9
|
+
// No rollback needed
|
|
10
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const COLLECTION_NAME = "tngl_testimonial";
|
|
2
|
+
|
|
3
|
+
// preset that applies to any user or role
|
|
4
|
+
const PRESETS = [
|
|
5
|
+
{
|
|
6
|
+
bookmark: null,
|
|
7
|
+
collection: "tngl_testimonial",
|
|
8
|
+
color: null,
|
|
9
|
+
filter: null,
|
|
10
|
+
icon: "bookmark",
|
|
11
|
+
layout: null,
|
|
12
|
+
layout_options: JSON.stringify({
|
|
13
|
+
tabular: {
|
|
14
|
+
widths: {
|
|
15
|
+
author: 192.6171875,
|
|
16
|
+
status: 107.09375,
|
|
17
|
+
comment: 492.5572509765625,
|
|
18
|
+
comment_date: 209.22393798828125,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
layout_query: JSON.stringify({
|
|
23
|
+
tabular: {
|
|
24
|
+
page: 1,
|
|
25
|
+
fields: ["status", "comment_date", "author", "comment"],
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
refresh_interval: null,
|
|
29
|
+
role: null,
|
|
30
|
+
search: null,
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export async function up(knex) {
|
|
35
|
+
await knex("directus_presets").insert(PRESETS);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function down(knex) {
|
|
39
|
+
await knex("directus_presets")
|
|
40
|
+
.where({
|
|
41
|
+
user: null,
|
|
42
|
+
role: null,
|
|
43
|
+
bookmark: null,
|
|
44
|
+
collection: COLLECTION_NAME,
|
|
45
|
+
})
|
|
46
|
+
.del();
|
|
47
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export async function up(knex) {
|
|
2
|
+
await knex("tngl_testimonial").insert([
|
|
3
|
+
{
|
|
4
|
+
sort: 1,
|
|
5
|
+
status: "published",
|
|
6
|
+
date_created: knex.fn.now(3),
|
|
7
|
+
date_updated: knex.fn.now(3),
|
|
8
|
+
author: "John Smith",
|
|
9
|
+
comment: "We had a great experience from beginning to end. Communication was clear, deadlines were met, and the attention to detail really stood out. It’s rare to find a team that combines professionalism with such a genuine commitment to delivering great results. We would gladly work with them again.",
|
|
10
|
+
comment_date: knex.fn.now(3),
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
sort: 2,
|
|
14
|
+
status: "published",
|
|
15
|
+
date_created: knex.fn.now(3),
|
|
16
|
+
date_updated: knex.fn.now(3),
|
|
17
|
+
author: "Jane Smith",
|
|
18
|
+
comment: "Working with this team was a fantastic experience. They were professional, responsive, and truly understood what we needed. The final result exceeded our expectations, and the entire process was smooth from start to finish. I would absolutely recommend their services to anyone looking for quality work and reliable support.",
|
|
19
|
+
comment_date: knex.fn.now(3),
|
|
20
|
+
},
|
|
21
|
+
]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function down(knex) {
|
|
25
|
+
await knex("directus_presets")
|
|
26
|
+
.where({
|
|
27
|
+
user: null,
|
|
28
|
+
role: null,
|
|
29
|
+
bookmark: null,
|
|
30
|
+
collection: COLLECTION_NAME,
|
|
31
|
+
})
|
|
32
|
+
.del();
|
|
33
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tanglemedia/directus-collection-testimonial",
|
|
3
|
+
"description": "Installs the Testimonial Collection to your Directus project.",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "Tangle Media, Inc."
|
|
6
|
+
},
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"icon": "extension",
|
|
9
|
+
"version": "0.0.1",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"directus",
|
|
12
|
+
"directus-extension",
|
|
13
|
+
"directus-extension-hook",
|
|
14
|
+
"testimonial-collection",
|
|
15
|
+
"directus-collection",
|
|
16
|
+
"collection"
|
|
17
|
+
],
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src",
|
|
21
|
+
"migrations",
|
|
22
|
+
"scripts",
|
|
23
|
+
"docs"
|
|
24
|
+
],
|
|
25
|
+
"directus:extension": {
|
|
26
|
+
"type": "hook",
|
|
27
|
+
"path": "dist/index.js",
|
|
28
|
+
"source": "src/index.js",
|
|
29
|
+
"host": "^10.10.1 || ^11.0.0",
|
|
30
|
+
"sandbox": {
|
|
31
|
+
"enabled": false,
|
|
32
|
+
"requestedScopes": {
|
|
33
|
+
"log": {}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@directus/extensions-sdk": "13.0.0",
|
|
39
|
+
"@types/node": "^22.13.0",
|
|
40
|
+
"typescript": "^5.7.3"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "directus-extension build",
|
|
44
|
+
"dev": "directus-extension build -w --no-minify",
|
|
45
|
+
"link": "directus-extension link"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const { defineHook } = require("@directus/extensions-sdk");
|
|
2
|
+
const moveMigrationScripts = require("./shared/utility/migrations");
|
|
3
|
+
|
|
4
|
+
module.exports = defineHook(
|
|
5
|
+
async ({ action, init }, { services, database, getSchema, logger }) => {
|
|
6
|
+
await moveMigrationScripts(logger);
|
|
7
|
+
},
|
|
8
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const { exec } = require("child_process");
|
|
2
|
+
const { promisify } = require("util");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const execPromise = promisify(exec);
|
|
5
|
+
|
|
6
|
+
const moveMigrationScripts = async (logger) => {
|
|
7
|
+
const ROOT = process.cwd();
|
|
8
|
+
const EXTENSION_PATH = __dirname;
|
|
9
|
+
|
|
10
|
+
let migrationSrcPath = EXTENSION_PATH.split("/");
|
|
11
|
+
migrationSrcPath.pop();
|
|
12
|
+
migrationSrcPath.push("migrations");
|
|
13
|
+
migrationSrcPath = path.join("/", ...migrationSrcPath);
|
|
14
|
+
|
|
15
|
+
let migrationDestPath = ROOT.split("/");
|
|
16
|
+
migrationDestPath.push("migrations");
|
|
17
|
+
migrationDestPath = path.join("/", ...migrationDestPath);
|
|
18
|
+
|
|
19
|
+
// create destination folder
|
|
20
|
+
let { stdout, stderr } = await execPromise(`mkdir -p ${migrationDestPath}`);
|
|
21
|
+
if (stderr) return;
|
|
22
|
+
|
|
23
|
+
// copy files
|
|
24
|
+
({ stdout, stderr } = await execPromise(
|
|
25
|
+
`cp -r ${migrationSrcPath}/* ${migrationDestPath}`,
|
|
26
|
+
));
|
|
27
|
+
if (stderr) return;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports = moveMigrationScripts;
|