stackpress
Version:
Incept is a content management framework.
250 lines (249 loc) • 8.45 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = detailView;
const ts_morph_1 = require("ts-morph");
function detailView(directory, _registry, model) {
const file = `${model.name}/admin/views/detail.tsx`;
const source = directory.createSourceFile(file, '', { overwrite: true });
const ids = model.ids.map(column => column.name);
const path = ids.map(name => `\${results.${name}}`).join('/');
const link = (action, extras = '') => `\`\${base}/${model.dash}/${action}/${path}${extras}\``;
source.addImportDeclaration({
isTypeOnly: true,
moduleSpecifier: 'stackpress/view/client',
namedImports: ['ServerPageProps', 'SessionPermission']
});
source.addImportDeclaration({
isTypeOnly: true,
moduleSpecifier: 'stackpress/admin/types',
namedImports: ['AdminConfigProps']
});
source.addImportDeclaration({
isTypeOnly: true,
moduleSpecifier: 'stackpress/sql',
namedImports: ['SearchParams']
});
source.addImportDeclaration({
isTypeOnly: true,
moduleSpecifier: '../../types.js',
namedImports: [`${model.title}Extended`]
});
source.addImportDeclaration({
moduleSpecifier: 'r22n',
namedImports: ['useLanguage']
});
source.addImportDeclaration({
moduleSpecifier: 'frui/element/Table',
namedImports: ['Table', 'Trow', 'Tcol']
});
source.addImportDeclaration({
moduleSpecifier: 'stackpress/view/client',
namedImports: ['useServer', 'useStripe', 'Crumbs', 'LayoutAdmin']
});
model.views.forEach(column => {
if (typeof column.view.component !== 'string')
return;
source.addImportDeclaration({
moduleSpecifier: `../../components/views/${column.title}ViewFormat.js`,
defaultImport: `${column.title}ViewFormat`
});
});
source.addFunction({
isExported: true,
name: `Admin${model.title}DetailCrumbs`,
parameters: [{
name: 'props',
type: `{ base: string, results: ${model.title}Extended }`
}],
statements: (`
//props
const { base, results } = props;
//hooks
const { _ } = useLanguage();
//variables
const crumbs = [
{
label: (<span className="admin-crumb">{_('${model.plural}')}</span>),
icon: '${model.icon}',
href: \`\${base}/${model.dash}/search\`
},
{
label: \`${model.transformTemplate('${results?.%s || \'\'}')}\`,
icon: '${model.icon}'
}
];
return (<Crumbs crumbs={crumbs} />);
`)
});
source.addFunction({
isExported: true,
name: `Admin${model.title}DetailActions`,
parameters: [{
name: 'props',
type: `{
base: string,
results: ${model.title}Extended,
can: (...permits: SessionPermission[]) => boolean,
}`
}],
statements: (`
const { base, results, can } = props;
const { _ } = useLanguage();
const routes = {
update: {
method: 'GET',
route: ${link('update')}
},
remove: {
method: 'GET',
route: ${link('remove')}
},
restore: {
method: 'GET',
route: ${link('restore')}
},
};
return (
<div className="actions">
{can(routes.update) && (
<a className="action update" href={routes.update.route}>
<i className="icon fas fa-edit"></i>
{_('Update')}
</a>
)}
{results.active && can(routes.remove) && (
<a className="action remove" href={routes.remove.route}>
<i className="icon fas fa-trash"></i>
{_('Remove')}
</a>
)}
{!results.active && can(routes.restore) && (
<a className="action restore" href={routes.restore.route}>
<i className="icon fas fa-check-circle"></i>
{_('Restore')}
</a>
)}
</div>
);
`)
});
source.addFunction({
isExported: true,
name: `Admin${model.title}DetailResults`,
parameters: [{
name: 'props',
type: `{ results: ${model.title}Extended }`
}],
statements: (`
const { results } = props;
const { _ } = useLanguage();
const stripe = useStripe('results-row-1', 'results-row-2');
return (
<Table>
${model.views.filter(column => column.view.method !== 'hide').map(column => {
return (`
<Trow>
<Tcol noWrap className={\`results-label \${stripe(true)}\`}>
{_('${column.label}')}
</Tcol>
<Tcol noWrap className={\`results-value \${stripe()}\`}>
${column.required && !column.view.component
? `{results.${column.name}.toString()}`
: column.required && column.view.component
? `<${column.title}ViewFormat data={results} value={results.${column.name}} />`
: !column.required && !column.view.component
? `{results.${column.name} ? results.${column.name}.toString() : ''}`
: `{results.${column.name} ? (<${column.title}ViewFormat data={results} value={results.${column.name}} />) : ''}`}
</Tcol>
</Trow>
`);
})}
</Table>
);
`)
});
source.addFunction({
isExported: true,
name: `Admin${model.title}DetailBody`,
statements: (`
const { config, session, response } = useServer<${[
`AdminConfigProps`,
'Partial<SearchParams>',
`${model.title}Extended`
].join(', ')}>();
const can = session.can.bind(session);
const base = config.path('admin.base', '/admin');
const results = response.results as ${model.title}Extended;
//render
return (
<main className="admin-detail-page admin-page">
<div className="admin-crumbs">
<Admin${model.title}DetailCrumbs base={base} results={results} />
</div>
<div className="admin-actions">
<Admin${model.title}DetailActions
can={can}
base={base}
results={results}
/>
</div>
<div className="admin-results">
<Admin${model.title}DetailResults results={results} />
</div>
</main>
);
`)
});
source.addFunction({
isExported: true,
name: `Admin${model.title}DetailHead`,
parameters: [{
name: 'props',
type: 'ServerPageProps<AdminConfigProps>'
}],
statements: (`
const { data, styles = [] } = props;
const { favicon = '/favicon.ico' } = data?.brand || {};
const { _ } = useLanguage();
const mimetype = favicon.endsWith('.png')
? 'image/png'
: favicon.endsWith('.svg')
? 'image/svg+xml'
: 'image/x-icon';
return (
<>
<title>{_('${model.singular} Detail')}</title>
{favicon && <link rel="icon" type={mimetype} href={favicon} />}
<link rel="stylesheet" type="text/css" href="/styles/global.css" />
{styles.map((href, index) => (
<link key={index} rel="stylesheet" type="text/css" href={href} />
))}
</>
);
`)
});
source.addFunction({
isExported: true,
name: `Admin${model.title}DetailPage`,
parameters: [{
name: 'props',
type: 'ServerPageProps<AdminConfigProps>'
}],
statements: (`
return (
<LayoutAdmin {...props}>
<Admin${model.title}DetailBody />
</LayoutAdmin>
);
`)
});
source.addVariableStatement({
isExported: true,
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [{
name: 'Head',
initializer: `Admin${model.title}DetailHead`
}]
});
source.addStatements(`export default Admin${model.title}DetailPage;`);
}