Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion AppBuilder/ABFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ import Network from "../resources/Network.js";
import Storage from "../resources/Storage.js";
// Storage: manages our interface for local storage

import ABViewManager from "./core/ABViewManagerCore";
// Use platform ABViewManager so Class.ABViewManager.viewClass() resolves
// plugin-registered views (e.g. dataview) via ClassManager, not only core AllViews.
import ABViewManager from "./platform/ABViewManager.js";

import Tenant from "../resources/Tenant.js";
// Tenant: manages the Tenant information of the current instance
Expand Down
2 changes: 1 addition & 1 deletion AppBuilder/core
Submodule core updated from a7b2f3 to 6d31c4
17 changes: 10 additions & 7 deletions AppBuilder/platform/ABClassManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import ABViewRuleListFormRecordRules from "../rules/ABViewRuleListFormRecordRule
import ABViewRuleListFormSubmitRules from "../rules/ABViewRuleListFormSubmitRules";

// MIGRATION: ABViewManager is depreciated. Use ABClassManager instead.
import ABViewManager from "./ABViewManager.js";
// Resolve legacy-only views via core AllViews hash (not platform ABViewManager,
// which would recurse back into ClassManager.viewClass).
import ABViewManagerCore from "../core/ABViewManagerCore.js";

const classRegistry = {
ObjectTypes: new Map(),
Expand Down Expand Up @@ -108,13 +110,14 @@ export function allObjectProperties() {

export function viewClass(type) {
var ViewClass = classRegistry.ViewTypes.get(type);
if (!ViewClass) {
ViewClass = ABViewManager.viewClass(type, false);
if (!ViewClass) {
throw new Error(`Unknown View type: ${type}`);
}
if (ViewClass) {
return ViewClass;
}
return ViewClass;
ViewClass = ABViewManagerCore.viewClass(type);
if (ViewClass) {
return ViewClass;
}
throw new Error(`Unknown View type: ${type}`);
}

export function viewCreate(type, config, application, parent) {
Expand Down
2 changes: 2 additions & 0 deletions AppBuilder/platform/plugins/included/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import viewComment from "./view_comment/FNAbviewcomment.js";
import viewCsvExporter from "./view_csvExporter/FNAbviewcsvexporter.js";
import viewCsvImporter from "./view_csvImporter/FNAbviewcsvimporter.js";
import viewDataSelect from "./view_data-select/FNAbviewdataselect.js";
import viewDataview from "./view_dataview/FNAbviewdataview.js";
import viewDetail from "./view_detail/FNAbviewdetail.js";
import viewImage from "./view_image/FNAbviewimage.js";
import viewLabel from "./view_label/FNAbviewlabel.js";
Expand All @@ -19,6 +20,7 @@ const AllPlugins = [
viewCsvImporter,
viewCsvImporter,
viewDataSelect,
viewDataview,
viewDetail,
viewImage,
viewLabel,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Local copy of link-page helper logic so the plugin remains self-contained.
class ABViewPropertyLinkPageComponentLocal {
constructor() {
this.view = null;
this.datacollection = null;
}

ui() {
return {};
}

init(options = {}) {
if (options.view) this.view = options.view;
if (options.datacollection) this.datacollection = options.datacollection;
}

changePage(pageId, rowId) {
if (this.datacollection) {
const dc = this.datacollection;
const cur = dc.getCursor();
const same =
cur &&
(String(cur.id) === String(rowId) ||
String(cur.uuid) === String(rowId));
// If cursor is already on this row, changeCursor may not fire; navigate immediately
// so Cypress and slow CI do not hang waiting for a one-time listener.
if (same) {
this.view?.changePage(pageId);
return;
}
dc.once("changeCursor", () => {
this.view?.changePage(pageId);
});
dc.setCursor(rowId);
} else {
this.view?.changePage(pageId);
}
}
}

export default class ABViewPropertyLinkPageLocal {
component(v1App = false) {
const component = new ABViewPropertyLinkPageComponentLocal();

if (!v1App) return component;

return {
ui: component.ui(),
init: (...params) => component.init(...params),
onShow: (...params) => component.onShow?.(...params),
changePage: (...params) => component.changePage(...params),
};
}
}
156 changes: 156 additions & 0 deletions AppBuilder/platform/plugins/included/view_dataview/FNAbviewdataview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import FNAbviewdataviewComponent from "./FNAbviewdataviewComponent.js";

// Dataview plugin: replaces ABViewDataviewCore + ABViewDataview.
// All runtime logic is kept in this plugin module.
export default function FNAbviewdataview({
ABViewContainer,
ABViewComponentPlugin,
}) {
const ABAbviewdataviewComponent = FNAbviewdataviewComponent({
ABViewComponentPlugin,
});

const ABViewDataviewPropertyComponentDefaults = {
xCount: 1, // Number of columns per row (must be >= 1).
detailsPage: "",
detailsTab: "",
editPage: "",
editTab: "",
dataviewID: null,
showLabel: true,
labelPosition: "left",
labelWidth: 120,
height: 0,
};

const ABViewDataviewDefaults = {
key: "dataview",
icon: "th",
labelKey: "Data view(plugin)",
};

return class ABViewDataviewPlugin extends ABViewContainer {
constructor(values, application, parent, defaultValues) {
super(
values,
application,
parent,
defaultValues ?? ABViewDataviewDefaults
);
}

static getPluginType() {
return "view";
}

static getPluginKey() {
return this.common().key;
}

static common() {
return ABViewDataviewDefaults;
}

static defaultValues() {
return ABViewDataviewPropertyComponentDefaults;
}

fromValues(values) {
super.fromValues(values);

this.settings.xCount = parseInt(
this.settings.xCount || ABViewDataviewPropertyComponentDefaults.xCount
);

this.settings.detailsPage =
this.settings.detailsPage ??
ABViewDataviewPropertyComponentDefaults.detailsPage;
this.settings.editPage =
this.settings.editPage ??
ABViewDataviewPropertyComponentDefaults.editPage;
this.settings.detailsTab =
this.settings.detailsTab ??
ABViewDataviewPropertyComponentDefaults.detailsTab;
this.settings.editTab =
this.settings.editTab ?? ABViewDataviewPropertyComponentDefaults.editTab;

this.settings.labelPosition =
this.settings.labelPosition ||
ABViewDataviewPropertyComponentDefaults.labelPosition;
this.settings.showLabel = JSON.parse(
this.settings.showLabel != null
? this.settings.showLabel
: ABViewDataviewPropertyComponentDefaults.showLabel
);
this.settings.labelWidth = parseInt(
this.settings.labelWidth ||
ABViewDataviewPropertyComponentDefaults.labelWidth
);
this.settings.height = parseInt(
this.settings.height ??
ABViewDataviewPropertyComponentDefaults.height
);
}

component(parentId) {
return new ABAbviewdataviewComponent(this, parentId);
}

// Dataview behaves like Detail and allows detail field views.
componentList() {
const viewsToAllow = ["label", "text"];
const allComponents = this.application.viewAll();
return allComponents.filter((c) =>
viewsToAllow.includes(c.common().key)
);
}

addFieldToDetail(field, yPosition) {
if (field == null) return;

const newView = field.detailComponent().newInstance(this.application, this);
if (newView == null) return;

// Keep the same field wiring behavior as Detail so ABDesigner can
// auto-build field cards after a Data Source is selected.
newView.settings = newView.settings ?? {};
newView.settings.fieldId = field.id;
newView.settings.labelWidth =
this.settings.labelWidth ||
ABViewDataviewPropertyComponentDefaults.labelWidth;

// Preserve alias support for query-based sources: [alias].[columnName].
newView.settings.alias = field.alias;
newView.position.y = yPosition;

this._views.push(newView);
return newView;
}

parentDetailComponent() {
let dataview = null;
let curr = this;

while (curr.key != "dataview" && !curr.isRoot() && curr.parent) {
curr = curr.parent;
}

if (curr.key == "dataview") {
dataview = curr;
}

return dataview;
}

warningsEval() {
super.warningsEval();

const DC = this.datacollection;
if (!DC) {
this.warningsMessage(
`can't resolve it's datacollection[${this.settings.dataviewID}]`
);
}
}
};
}
Loading
Loading