Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | 1103x 148x 526x 526x 526x 185x 341x 451x 451x 312x 262x 262x 14x 7x 7x 7x 7x 7x 7x 5x 5x 5x 2x 2x 2x 2x 2x 2x 2x 2x 4052x 4001x 51x 51x 4x 47x 47x 47x 2x 2x 10x 10x | import Controller from "sap/ui/core/mvc/Controller";
import UIComponent from "sap/ui/core/UIComponent";
import AppComponent from "../Component";
import Model from "sap/ui/model/Model";
import JSONModel from "sap/ui/model/json/JSONModel";
import ResourceModel from "sap/ui/model/resource/ResourceModel";
import Router from "sap/ui/core/routing/Router";
import Event from "sap/ui/base/Event";
import ColumnListItem from "sap/m/ColumnListItem";
import Dialog from "sap/m/Dialog";
import { SegmentedButton$SelectionChangeEvent } from "sap/m/SegmentedButton";
import { parseGermanDate } from "../model/germanDate";
import { getSupportEndState } from "../model/supportEndThresholds";
/**
* @namespace de.itsfullofstars.sap.pam.controller
*/
export default abstract class BaseController extends Controller {
/**
* Convenience method for accessing the component of the controller's view.
* @returns The component of the controller's view
*/
public getOwnerComponent(): AppComponent {
return super.getOwnerComponent() as AppComponent;
}
/**
* Convenience method to get the components' router instance.
* @returns The router instance
*/
public getRouter(): Router {
return UIComponent.getRouterFor(this);
}
/**
* Convenience method for synchronously resolving an i18n text from controller
* code (formatters, alerts, JSONModel properties, ...).
*
* Deliberately goes through `ResourceModel#getProperty` rather than
* `ResourceModel#getResourceBundle()`: with `async: true` (see manifest.json),
* the latter always returns a Promise, even long after the bundle has finished loading.
* `getProperty` is the same synchronous path XML property bindings
* (`{i18n>key}`) use internally, and is safe to call from anywhere after view
* creation because the Component declares `sap.ui.core.IAsyncContentCreation`,
* which guarantees the i18n ResourceModel is already loaded before any
* view/controller is instantiated.
* @param sKey The i18n resource bundle key
* @param aArgs Optional placeholder values ({0}, {1}, ...) for the text
* @returns The resolved, localized text
*/
public getText(sKey: string, aArgs?: Array<string | number>): string {
const oModel = this.getOwnerComponent().getModel("i18n") as ResourceModel;
const sText = oModel.getProperty(sKey) ?? sKey;
if (!aArgs || aArgs.length === 0) {
return sText;
}
return sText.replace(/\{(\d+)\}/g, (sMatch, sIndex: string) => {
const vValue = aArgs[Number(sIndex)];
return vValue === undefined ? sMatch : String(vValue);
});
}
/**
* Convenience method for getting the view model by name in every controller of the application.
* @param [sName] The model name
* @returns The model instance
*/
public getModel(sName?: string): Model {
return this.getView().getModel(sName);
}
/**
* Convenience method for setting the view model in every controller of the application.
* @param oModel The model instance
* @param [sName] The model name
* @returns The current base controller instance
*/
public setModel(oModel: Model, sName?: string): BaseController {
this.getView().setModel(oModel, sName);
return this;
}
/**
* Convenience method for triggering the navigation to a specific target.
* @public
* @param sName Target name
* @param [oParameters] Navigation parameters
* @param [bReplace] Defines if the hash should be replaced (no browser history entry) or set (browser history entry)
*/
public navTo(sName: string, oParameters?: object, bReplace?: boolean): void {
this.getRouter().navTo(sName, oParameters, undefined, bReplace);
}
/**
* Convenience event handler for a pressed table row that is bound to the
* "pam" model. Navigates to the product detail page for that row's entry.
* @param oEvent The press event of the pressed ColumnListItem
*/
public onProductRowPress(oEvent: Event): void {
const oItem = oEvent.getSource<ColumnListItem>();
const oContext = oItem.getBindingContext("pam");
Iif (!oContext) {
return;
}
const sIndex = oContext.getPath().split("/").pop();
Iif (!sIndex) {
return;
}
this.navTo("productdetail", { index: sIndex });
}
/**
* Shared handler for the "show/hide advanced filters" toggle on the Main
* and SupportStatus views. Both views set up an identical "view"
* JSONModel (showAdvancedFilters, supportEndHighlightDate) in onInit.
*/
public onToggleAdvancedFilters(): void {
const oViewModel = this.getModel("view") as JSONModel;
const bShowAdvancedFilters = oViewModel.getProperty("/showAdvancedFilters") as boolean;
oViewModel.setProperty("/showAdvancedFilters", !bShowAdvancedFilters);
}
/**
* Shared handler for the "support end approaching" SegmentedButton on the
* Main and SupportStatus views, storing the chosen highlight horizon (or
* `null` for "off") on the "view" model's /supportEndHighlightDate.
* @param oEvent The selectionChange event of the SegmentedButton
*/
protected onSupportEndHighlightChange(oEvent: SegmentedButton$SelectionChangeEvent): void {
const sKey = oEvent.getParameter("selectedKey");
const oViewModel = this.getModel("view") as JSONModel;
Iif (!sKey || sKey === "none") {
oViewModel.setProperty("/supportEndHighlightDate", null);
return;
}
const iMonths = parseInt(sKey, 10); // "3M" -> 3, "24M" -> 24
const oLimit = new Date();
oLimit.setHours(23, 59, 59, 999);
oLimit.setMonth(oLimit.getMonth() + iMonths);
oViewModel.setProperty("/supportEndHighlightDate", oLimit);
}
/**
* Shared formatter for the "support end approaching" row highlighting on
* the Main and SupportStatus tables.
* @param vSupportEnd The raw (dd.mm.yyyy) support end date value
* @param oLimit The highlight horizon chosen via the SegmentedButton, or null if off
* @returns A sap.ui.core.ValueState name ("Error"/"Warning"/"None")
*/
public supportEndHighlight(
vSupportEnd: unknown,
oLimit: Date | null
): string {
if (!oLimit) {
return "None";
}
const oEnd = parseGermanDate(vSupportEnd);
/*
* The period chosen via the SegmentedButton determines up to when
* highlighting happens at all; the color itself then follows the
* central, configurable red/yellow threshold from
* model/supportEndThresholds.ts (default: red within 6 months,
* yellow within 12 months). A date that has already passed is
* always the most urgent case.
*/
if (oEnd === null || oEnd.getTime() > oLimit.getTime()) {
return "None";
}
const today = new Date();
today.setHours(0, 0, 0, 0);
return getSupportEndState(oEnd, today);
}
/**
* Shared handler for the "chart analysis" dialog opened from the Main
* and SupportStatus tables (both views use the same control id,
* `chartAnalysisDialog`, so this works regardless of which view it is
* called from).
*/
public onCloseChartAnalysis(): void {
const oDialog = this.byId("chartAnalysisDialog") as Dialog;
oDialog.close();
}
/**
* Formatter for a bar's width in the "chart analysis" dialog's bar
* chart, scaled against the chart's largest value so the longest bar
* fills the full track.
* @param iCount The bar's own value
* @param iMaxCount The largest value among the chart's bars
* @returns A CSS percentage width (e.g. "42%")
*/
public formatBarWidth(iCount: number, iMaxCount: number): string {
Iif (!iMaxCount) {
return "0%";
}
return `${(iCount / iMaxCount) * 100}%`;
}
}
|