diff --git a/CHANGELOG.md b/CHANGELOG.md index 51be06ba5..3d1f3bdcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ ## Changelog -### 1.4.7 build 43 +### 1.4.8 build 1 +* Add Static Properties to Custom Models + +### 1.4.7 * Fix Issues in Checkbox Inputs, Range Slider and Gallery Widgets * Fix Range Input Bugs with Values diff --git a/altrpnjs/app/Controllers/Http/admin/ModelsController.ts b/altrpnjs/app/Controllers/Http/admin/ModelsController.ts index fa485b4bc..920632017 100644 --- a/altrpnjs/app/Controllers/Http/admin/ModelsController.ts +++ b/altrpnjs/app/Controllers/Http/admin/ModelsController.ts @@ -17,7 +17,7 @@ import SourceRole from 'App/Models/SourceRole' import guid from '../../../../helpers/guid' import SQLEditor from 'App/Models/SQLEditor' import {schema, rules} from '@ioc:Adonis/Core/Validator' -import {parseInt} from 'lodash' +import _, {parseInt} from 'lodash' import {ModelPaginatorContract} from "@ioc:Adonis/Lucid/Orm" import Logger from "@ioc:Adonis/Core/Logger"; import keys from "lodash/keys" @@ -84,15 +84,15 @@ export default class ModelsController { } static modelSchema = schema.create({ - title: schema.string({trim: true},[]), - }) + title: schema.string({trim: true}, []), + }) - async updateModel({response, params, request, auth}: HttpContextContract) { + async updateModel({response, params, request, auth}: HttpContextContract) { - let model = await Model.find(params.id) - if (!model) { - response.status(404) - return response.json({ + let model = await Model.find(params.id) + if (!model) { + response.status(404) + return response.json({ success: false, message: 'Model not found' }) @@ -118,6 +118,7 @@ export default class ModelsController { soft_deletes: modelData.soft_deletes, time_stamps: modelData.time_stamps, parent_model_id: modelData.parent_model_id || null, + settings: modelData.settings || null, }) if (modelData.time_stamps) { @@ -153,8 +154,8 @@ export default class ModelsController { const client = Database.connection(Env.get('DB_CONNECTION')) try { await client.schema.table(model.table.name, table => { - table.timestamp('created_at') - table.timestamp('updated_at') + table.timestamp('created_at') + table.timestamp('updated_at') }) } catch (e) { console.error(e) @@ -165,7 +166,7 @@ export default class ModelsController { const created_at_column = await Column.query().where('name', '=', 'created_at').andWhere('model_id', '=', model.id) const updated_at_column = await Column.query().where('name', '=', 'updated_at').andWhere('model_id', '=', model.id) - if(created_at_column?.length && updated_at_column?.length) { + if (created_at_column?.length && updated_at_column?.length) { const client = Database.connection(Env.get('DB_CONNECTION')) try { await client.schema.table(model.table.name, table => { @@ -485,6 +486,7 @@ export default class ModelsController { } })) } + async storeModel({request, response, auth}: HttpContextContract) { let modelData = request.all() let model = new Model() @@ -506,6 +508,7 @@ export default class ModelsController { time_stamps: modelData.time_stamps, id: modelData.id, parent_model_id: modelData.parent_model_id || null, + settings: modelData.settings || null, table_id: table.id, }) await model.save() @@ -574,7 +577,7 @@ export default class ModelsController { await controller.save() - await Model.createDefaultCustomizers( modelData, model) + await Model.createDefaultCustomizers(modelData, model) let sources = [ (new Source()).fill({ @@ -784,9 +787,11 @@ export default class ModelsController { } try { if (relationship[i].type === "belongsTo") { - let deleteQuery = `ALTER TABLE ${model.table.name} DROP FOREIGN KEY ${model.table.name}_${relationship[i].local_key}_foreign` + let deleteQuery = `ALTER TABLE ${model.table.name} + DROP FOREIGN KEY ${model.table.name}_${relationship[i].local_key}_foreign` await Database.rawQuery(deleteQuery) - deleteQuery = `ALTER TABLE ${model.table.name} DROP INDEX ${model.table.name}_${relationship[i].foreign_key}_foreign` + deleteQuery = `ALTER TABLE ${model.table.name} + DROP INDEX ${model.table.name}_${relationship[i].foreign_key}_foreign` await Database.rawQuery(deleteQuery) } } catch (e) { @@ -837,7 +842,7 @@ export default class ModelsController { }) if (table) { await Column.query().where('table_id', table.id).delete() - if(controller){ + if (controller) { await controller.delete() } @@ -966,7 +971,7 @@ export default class ModelsController { delete dataSource.permissions if (sourceRoles) { for (let sourceRole of sourceRoles) { - data['access']['roles'].push(sourceRole['id']) + data['access']['roles'].push(sourceRole['id']) } } @@ -994,8 +999,7 @@ export default class ModelsController { await request.validate({schema: dataSourceSchema}) - - let dataSource = await Source.query().where('id', params.id).preload("roles").first() + let dataSource = await Source.query().where('id', params.id).preload("roles").first() if (!dataSource) { response.status(404) return response.json({ @@ -1006,41 +1010,41 @@ export default class ModelsController { let data = request.all() - delete data.notice_settings - delete data.web_url - delete data.bodies - delete data.headers + delete data.notice_settings + delete data.web_url + delete data.bodies + delete data.headers if (data['access']['roles'].lenght <= 1) { data['need_all_roles'] = 0 } - for (const key of keys(data)) { - switch (key) { - case "roles": - continue - case "access": - if(data.access) { - if(data.access.roles) { - //@ts-ignore - if(dataSource.roles.length > 0) { - await dataSource.related('roles').detach() - } - - if(data.access.roles.length > 0) { - await dataSource.related('roles').attach(data.access.roles.map(role => role.value)) - } + for (const key of keys(data)) { + switch (key) { + case "roles": + continue + case "access": + if (data.access) { + if (data.access.roles) { + //@ts-ignore + if (dataSource.roles.length > 0) { + await dataSource.related('roles').detach() + } + + if (data.access.roles.length > 0) { + await dataSource.related('roles').attach(data.access.roles.map(role => role.value)) } } - default: - //@ts-ignore - dataSource[key] = data[key] - } + } + default: + //@ts-ignore + dataSource[key] = data[key] } + } await dataSource.save() return response.json({ - success: false, + success: false, data: dataSource }) } @@ -1105,4 +1109,100 @@ export default class ModelsController { let data_sources = await Source.query().where('model_id', params.model_id).select(['title as label', 'id as value']) return response.json(data_sources) } + + async getSettingsValue({response, params}: HttpContextContract) { + const {model_id, setting_name} = params + const model = await Model.find(model_id) + let _default: any = null + switch (setting_name) { + case 'static_props': { + _default = [] + } + break + } + + return response.json({ + success: true, + data: _.get(model, `settings.${setting_name}`, _default) + }) + + } + + async updateSettingValue({response, params, request}: HttpContextContract) { + + const {model_id, setting_name, prop_name} = params + const model = await Model.findOrFail(model_id) + if(! model.settings){ + model.settings = {} + } + switch (setting_name) { + case 'static_props': { + let static_props = _.get(model, 'settings.static_props', []) + let current_value = static_props.find(i=>i.prop_name === prop_name) + static_props = [...static_props] + if(! current_value){ + current_value = { + prop_name, + prop_value: request.input('prop_value') + } + static_props.push(current_value) + } else { + current_value.prop_value = request.input('prop_value') + } + model.settings.static_props = static_props + await model.save() + let data = static_props.find(i => i.prop_name === prop_name)?.prop_value || null + return response.json({ + success: true, + data + }) + } + } + } + + async deleteSettingValue({response, params}: HttpContextContract) { + + const {model_id, setting_name, prop_name} = params + const model = await Model.findOrFail(model_id) + if(! model.settings){ + model.settings = {} + } + switch (setting_name) { + case 'static_props': { + let static_props = _.get(model, 'settings.static_props', []) + static_props = static_props.filter(i=>i.prop_name !== prop_name) + model.settings.static_props = static_props + await model.save() + let data = static_props.find(i => i.prop_name === prop_name)?.prop_value || null + return response.json({ + success: true, + data + }) + } + } + } + + async getSettingValue({response, params}: HttpContextContract) { + + const {model_id, setting_name, prop_name} = params + const model = await Model.findOrFail(model_id) + + let _default: any = null + switch (setting_name) { + case 'static_props': { + let static_props = _.get(model, 'settings.static_props', []) + let data = static_props.find(i => i.prop_name === prop_name)?.prop_value || null + + return response.json({ + success: true, + data + }) + } + } + + return response.json({ + success: true, + data: _default + }) + } } diff --git a/altrpnjs/app/Generators/ModelGenerator.ts b/altrpnjs/app/Generators/ModelGenerator.ts index 31ac0de83..e3388e6b2 100644 --- a/altrpnjs/app/Generators/ModelGenerator.ts +++ b/altrpnjs/app/Generators/ModelGenerator.ts @@ -146,12 +146,53 @@ import {softDeleteQuery, softDelete} from "../../helpers/delete"; } private _getProdPropertiesContent(): string { - return `` + + const {settings = {}} = this.model + + const {static_props = []} = settings + return ` + ${static_props.map(({ + // @ts-ignore + prop_value, + // @ts-ignore + prop_name,})=>{ + if(!prop_name || !prop_value){ + return '' + } + return ` + static get ${prop_name}(){ + return \`${prop_value}\` + }` + } + ).join('\n')} + + ` } private _getDevPropertiesContent(): string { + const {settings = {}} = this.model + + const {static_props = []} = settings + + return ` public static table = '${this.table.name}' + ${static_props.map(({ + // @ts-ignore + prop_value, + // @ts-ignore + prop_name, + })=>{ + if(!prop_name || !prop_value){ + return '' + } + return ` + static get ${prop_name}(){ + return \`${prop_value}\` + }` + } + ).join('\n')} + ` } diff --git a/altrpnjs/app/Listeners/Model.ts b/altrpnjs/app/Listeners/Model.ts index 7f811f3f7..a514c3816 100644 --- a/altrpnjs/app/Listeners/Model.ts +++ b/altrpnjs/app/Listeners/Model.ts @@ -1,15 +1,15 @@ -import { EventsList } from '@ioc:Adonis/Core/Event' import base_path from '../../helpers/base_path' import exec from '../../helpers/exec' +import ORMModel from '../Models/Model' export default class Model { - public async updating(model: EventsList['model:updating']){ - model.id - } - public async updated(model: EventsList['model:updated']){ + // public async updating(model: EventsList['model:updating']){ + // model.id + // } + public async updated(model: ORMModel){ await model.load('altrp_controller') const controller = model.altrp_controller - await exec(`node ${base_path('ace')} generator:model --id=${model.id}`) + console.log(await exec(`node ${base_path('ace')} generator:model --id=${model.id}`)) await exec(`node ${base_path('ace')} generator:controller --id=${controller.id}`) await exec(`node ${base_path('ace')} generator:router`) // Promise.all([controllerGenerator.run(controller), modelGenerator.run(model)]) diff --git a/altrpnjs/app/Models/Model.ts b/altrpnjs/app/Models/Model.ts index fe1ddc0a8..81d269a70 100644 --- a/altrpnjs/app/Models/Model.ts +++ b/altrpnjs/app/Models/Model.ts @@ -2,7 +2,7 @@ import * as _ from 'lodash' import {string} from '@ioc:Adonis/Core/Helpers' import {DateTime} from 'luxon' import { - + afterUpdate, afterFind, BaseModel, BelongsTo, @@ -30,10 +30,20 @@ import * as mustache from 'mustache' import base_path from "../../helpers/path/base_path"; import fs from "fs"; import LIKE from "../../helpers/const/LIKE"; +import exec from "../../helpers/exec"; export default class Model extends BaseModel { public static table = 'altrp_models' private static defaultCustomizersName: string = 'default'; + @afterUpdate() + public static async afterUpdate(model){ + + exec(`node ${base_path('ace')} generator:model --id=${model.id}`) + .then(()=>{ + return exec(`node ${base_path('ace')} generator:router`) + }) + + } @afterFind() public static async createController(model:Model) { @@ -54,6 +64,9 @@ export default class Model extends BaseModel { @column() public soft_deletes: boolean + @column() + public settings: { static_props?: {}[] } + @column() public time_stamps: boolean diff --git a/altrpnjs/database/migrations/1675016912825_model_settings.ts b/altrpnjs/database/migrations/1675016912825_model_settings.ts new file mode 100644 index 000000000..cbf9735d6 --- /dev/null +++ b/altrpnjs/database/migrations/1675016912825_model_settings.ts @@ -0,0 +1,18 @@ +import BaseSchema from '@ioc:Adonis/Lucid/Schema' + +export default class extends BaseSchema { + protected tableName = 'altrp_models' + + public async up () { + this.schema.table(this.tableName, (table) => { + table.json('settings').nullable() + + }) + } + + public async down () { + this.schema.table(this.tableName, (table) => { + table.dropColumn('settings') + }) + } +} diff --git a/altrpnjs/database/pg_migrations/1675016912825_model_settings.ts b/altrpnjs/database/pg_migrations/1675016912825_model_settings.ts new file mode 100644 index 000000000..cbf9735d6 --- /dev/null +++ b/altrpnjs/database/pg_migrations/1675016912825_model_settings.ts @@ -0,0 +1,18 @@ +import BaseSchema from '@ioc:Adonis/Lucid/Schema' + +export default class extends BaseSchema { + protected tableName = 'altrp_models' + + public async up () { + this.schema.table(this.tableName, (table) => { + table.json('settings').nullable() + + }) + } + + public async down () { + this.schema.table(this.tableName, (table) => { + table.dropColumn('settings') + }) + } +} diff --git a/altrpnjs/start/routes/admin.ts b/altrpnjs/start/routes/admin.ts index 745f1e2ca..36f033775 100644 --- a/altrpnjs/start/routes/admin.ts +++ b/altrpnjs/start/routes/admin.ts @@ -110,6 +110,11 @@ Route.group(() => { Route.delete('/data_sources/:id', 'admin/ModelsController.destroyDataSource'); Route.get('/models/:model_id/data_source_options', 'admin/ModelsController.getDataSourcesByModel'); + Route.get('/models/:model_id/settings/:setting_name', 'admin/ModelsController.getSettingsValue'); + Route.put('/models/:model_id/settings/:setting_name/:prop_name', 'admin/ModelsController.updateSettingValue'); + Route.get('/models/:model_id/settings/:setting_name/:prop_name', 'admin/ModelsController.getSettingValue'); + Route.delete('/models/:model_id/settings/:setting_name/:prop_name', 'admin/ModelsController.deleteSettingValue'); + Route.resource('global_template_styles', 'GlobalTemplateStylesController') Route.get('/reports_options', () => { diff --git a/resources/modules/admin/src/components/ModalPropWindow.js b/resources/modules/admin/src/components/ModalPropWindow.js new file mode 100644 index 000000000..06d67ddfb --- /dev/null +++ b/resources/modules/admin/src/components/ModalPropWindow.js @@ -0,0 +1,28 @@ +import CloseModal from "../svgs/clear_black.svg"; +import React from "react"; +import AddRelationForm from "./models/AddRelationForm"; +import "./../sass/components/ModalRelationWindow.scss"; +import PropForm from "./models/PropForm"; + + +class ModalPropWindow extends React.Component { + + + render() { + return ( +