@apvee/spfx-react-toolkit 1.3.0 → 2.0.0
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/lib/core/atoms.internal.js +1 -1
- package/lib/core/atoms.internal.js.map +1 -1
- package/lib/core/context.internal.js +2 -2
- package/lib/core/context.internal.js.map +1 -1
- package/lib/core/provider-base.internal.js +29 -29
- package/lib/core/provider-base.internal.js.map +1 -1
- package/lib/extensions/spFxReactToolkitTest/SpFxReactToolkitTestApplicationCustomizer.js +8 -29
- package/lib/extensions/spFxReactToolkitTest/SpFxReactToolkitTestApplicationCustomizer.js.map +1 -1
- package/lib/hooks/index.d.ts +1 -0
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/useAppCatalogUrl.internal.d.ts +26 -0
- package/lib/hooks/useAppCatalogUrl.internal.d.ts.map +1 -0
- package/lib/hooks/useAppCatalogUrl.internal.js +72 -0
- package/lib/hooks/useAppCatalogUrl.internal.js.map +1 -0
- package/lib/hooks/useAsyncInvoke.internal.js +27 -75
- package/lib/hooks/useAsyncInvoke.internal.js.map +1 -1
- package/lib/hooks/useSPFxAadHttpClient.js +27 -27
- package/lib/hooks/useSPFxAadHttpClient.js.map +1 -1
- package/lib/hooks/useSPFxContainerInfo.js +5 -5
- package/lib/hooks/useSPFxContainerInfo.js.map +1 -1
- package/lib/hooks/useSPFxContainerSize.js +9 -10
- package/lib/hooks/useSPFxContainerSize.js.map +1 -1
- package/lib/hooks/useSPFxCorrelationInfo.js +6 -7
- package/lib/hooks/useSPFxCorrelationInfo.js.map +1 -1
- package/lib/hooks/useSPFxCrossSitePermissions.js +48 -58
- package/lib/hooks/useSPFxCrossSitePermissions.js.map +1 -1
- package/lib/hooks/useSPFxDisplayMode.js +8 -8
- package/lib/hooks/useSPFxDisplayMode.js.map +1 -1
- package/lib/hooks/useSPFxEnvironmentInfo.js +17 -18
- package/lib/hooks/useSPFxEnvironmentInfo.js.map +1 -1
- package/lib/hooks/useSPFxFluent9ThemeInfo.js +4 -4
- package/lib/hooks/useSPFxFluent9ThemeInfo.js.map +1 -1
- package/lib/hooks/useSPFxHttpClient.js +10 -10
- package/lib/hooks/useSPFxHttpClient.js.map +1 -1
- package/lib/hooks/useSPFxHubSiteInfo.js +21 -24
- package/lib/hooks/useSPFxHubSiteInfo.js.map +1 -1
- package/lib/hooks/useSPFxInstanceInfo.js +2 -2
- package/lib/hooks/useSPFxInstanceInfo.js.map +1 -1
- package/lib/hooks/useSPFxListInfo.js +8 -9
- package/lib/hooks/useSPFxListInfo.js.map +1 -1
- package/lib/hooks/useSPFxLocaleInfo.js +10 -10
- package/lib/hooks/useSPFxLocaleInfo.js.map +1 -1
- package/lib/hooks/useSPFxLogger.js +26 -26
- package/lib/hooks/useSPFxLogger.js.map +1 -1
- package/lib/hooks/useSPFxMSGraphClient.js +25 -25
- package/lib/hooks/useSPFxMSGraphClient.js.map +1 -1
- package/lib/hooks/useSPFxOneDriveAppData.js +148 -209
- package/lib/hooks/useSPFxOneDriveAppData.js.map +1 -1
- package/lib/hooks/useSPFxPageContext.js +2 -2
- package/lib/hooks/useSPFxPageContext.js.map +1 -1
- package/lib/hooks/useSPFxPageType.js +19 -20
- package/lib/hooks/useSPFxPageType.js.map +1 -1
- package/lib/hooks/useSPFxPerformance.js +33 -87
- package/lib/hooks/useSPFxPerformance.js.map +1 -1
- package/lib/hooks/useSPFxPermissions.js +14 -15
- package/lib/hooks/useSPFxPermissions.js.map +1 -1
- package/lib/hooks/useSPFxPnP.js +62 -119
- package/lib/hooks/useSPFxPnP.js.map +1 -1
- package/lib/hooks/useSPFxPnPContext.js +22 -25
- package/lib/hooks/useSPFxPnPContext.js.map +1 -1
- package/lib/hooks/useSPFxPnPList.js +307 -451
- package/lib/hooks/useSPFxPnPList.js.map +1 -1
- package/lib/hooks/useSPFxPnPSearch.js +262 -353
- package/lib/hooks/useSPFxPnPSearch.js.map +1 -1
- package/lib/hooks/useSPFxProperties.js +12 -20
- package/lib/hooks/useSPFxProperties.js.map +1 -1
- package/lib/hooks/useSPFxSPHttpClient.js +19 -19
- package/lib/hooks/useSPFxSPHttpClient.js.map +1 -1
- package/lib/hooks/useSPFxServiceScope.js +6 -6
- package/lib/hooks/useSPFxServiceScope.js.map +1 -1
- package/lib/hooks/useSPFxSiteInfo.js +7 -8
- package/lib/hooks/useSPFxSiteInfo.js.map +1 -1
- package/lib/hooks/useSPFxStorage.js +22 -22
- package/lib/hooks/useSPFxStorage.js.map +1 -1
- package/lib/hooks/useSPFxTeams.js +37 -92
- package/lib/hooks/useSPFxTeams.js.map +1 -1
- package/lib/hooks/useSPFxTenantKeyValueStore.d.ts +252 -0
- package/lib/hooks/useSPFxTenantKeyValueStore.d.ts.map +1 -0
- package/lib/hooks/useSPFxTenantKeyValueStore.js +572 -0
- package/lib/hooks/useSPFxTenantKeyValueStore.js.map +1 -0
- package/lib/hooks/useSPFxTenantProperty.d.ts +23 -244
- package/lib/hooks/useSPFxTenantProperty.d.ts.map +1 -1
- package/lib/hooks/useSPFxTenantProperty.js +85 -559
- package/lib/hooks/useSPFxTenantProperty.js.map +1 -1
- package/lib/hooks/useSPFxUserInfo.js +3 -4
- package/lib/hooks/useSPFxUserInfo.js.map +1 -1
- package/lib/hooks/useSPFxUserPhoto.js +76 -123
- package/lib/hooks/useSPFxUserPhoto.js.map +1 -1
- package/lib/utils/resize-observer.internal.js +6 -7
- package/lib/utils/resize-observer.internal.js.map +1 -1
- package/lib/utils/theme-subscription.internal.js +8 -8
- package/lib/utils/theme-subscription.internal.js.map +1 -1
- package/lib/utils/type-guards.internal.js +6 -6
- package/lib/utils/type-guards.internal.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.js +12 -37
- package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.d.ts.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.js +277 -336
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.js +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/HttpClientDemo.js +26 -86
- package/lib/webparts/spFxReactToolkitTest/components/demos/HttpClientDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPContextDemo.js +53 -113
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPContextDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPListDemo.js +49 -121
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPListDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPOperationsDemo.js +44 -103
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPOperationsDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchAdvancedDemo.js +15 -15
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchAdvancedDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchBasicDemo.js +18 -66
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchBasicDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchRefinersDemo.js +9 -9
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchRefinersDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchSuggestionsDemo.js +37 -86
- package/lib/webparts/spFxReactToolkitTest/components/demos/PnPSearchSuggestionsDemo.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/shared/InfoRow.js +6 -9
- package/lib/webparts/spFxReactToolkitTest/components/shared/InfoRow.js.map +1 -1
- package/lib/webparts/spFxReactToolkitTest/components/shared/StatusBadge.js +3 -6
- package/lib/webparts/spFxReactToolkitTest/components/shared/StatusBadge.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,61 +1,15 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
-
function step(op) {
|
|
15
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
-
switch (op[0]) {
|
|
20
|
-
case 0: case 1: t = op; break;
|
|
21
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
-
default:
|
|
25
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
-
if (t[2]) _.ops.pop();
|
|
30
|
-
_.trys.pop(); continue;
|
|
31
|
-
}
|
|
32
|
-
op = body.call(thisArg, _);
|
|
33
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
38
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
39
|
-
if (ar || !(i in from)) {
|
|
40
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
41
|
-
ar[i] = from[i];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
45
|
-
};
|
|
46
1
|
import * as React from 'react';
|
|
47
2
|
import styles from './SpFxReactToolkitTest.module.scss';
|
|
48
3
|
import { Stack, Pivot, PivotItem, TextField, PrimaryButton, DefaultButton, MessageBar, MessageBarType, Separator, Label, Icon, } from '@fluentui/react';
|
|
49
4
|
import { InfoRow, StatusBadge } from './shared';
|
|
50
5
|
import { HttpClientDemo, PnPContextDemo, PnPOperationsDemo, PnPListDemo, PnPSearchBasicDemo, PnPSearchAdvancedDemo, PnPSearchRefinersDemo, PnPSearchSuggestionsDemo, } from './demos';
|
|
51
6
|
// Import hooks from SPFx React Toolkit (used in main component)
|
|
52
|
-
import { useSPFxProperties, useSPFxThemeInfo, useSPFxUserInfo, useSPFxEnvironmentInfo, useSPFxSiteInfo, useSPFxDisplayMode, useSPFxInstanceInfo, useSPFxPageContext, useSPFxTeams, useSPFxListInfo, useSPFxLocaleInfo, useSPFxHubSiteInfo, useSPFxCorrelationInfo, useSPFxPermissions, useSPFxCrossSitePermissions, useSPFxContainerSize, useSPFxContainerInfo, useSPFxSessionStorage, useSPFxLocalStorage, useSPFxLogger, useSPFxPageType, useSPFxServiceScope, useSPFxSPHttpClient, useSPFxMSGraphClient, useSPFxAadHttpClient, useSPFxPerformance, useSPFxFluent9ThemeInfo, useSPFxOneDriveAppData, useSPFxTenantProperty, useSPFxUserPhoto, } from '../../../hooks';
|
|
7
|
+
import { useSPFxProperties, useSPFxThemeInfo, useSPFxUserInfo, useSPFxEnvironmentInfo, useSPFxSiteInfo, useSPFxDisplayMode, useSPFxInstanceInfo, useSPFxPageContext, useSPFxTeams, useSPFxListInfo, useSPFxLocaleInfo, useSPFxHubSiteInfo, useSPFxCorrelationInfo, useSPFxPermissions, useSPFxCrossSitePermissions, useSPFxContainerSize, useSPFxContainerInfo, useSPFxSessionStorage, useSPFxLocalStorage, useSPFxLogger, useSPFxPageType, useSPFxServiceScope, useSPFxSPHttpClient, useSPFxMSGraphClient, useSPFxAadHttpClient, useSPFxPerformance, useSPFxFluent9ThemeInfo, useSPFxOneDriveAppData, useSPFxTenantProperty, useSPFxTenantKeyValueStore, useSPFxUserPhoto, } from '../../../hooks';
|
|
53
8
|
import { SPPermission } from '@microsoft/sp-page-context';
|
|
54
9
|
// Helper function to safely stringify objects with circular references
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return JSON.stringify(obj, function (key, value) {
|
|
10
|
+
const safeStringify = (obj, indent = 2) => {
|
|
11
|
+
const seen = new WeakSet();
|
|
12
|
+
return JSON.stringify(obj, (key, value) => {
|
|
59
13
|
// Skip private properties and service scopes to avoid circular references
|
|
60
14
|
if (typeof key === 'string' && (key.indexOf('_') === 0 || key === 'serviceScope' || key === 'service')) {
|
|
61
15
|
return '[Circular/Private]';
|
|
@@ -69,298 +23,254 @@ var safeStringify = function (obj, indent) {
|
|
|
69
23
|
return value;
|
|
70
24
|
}, indent);
|
|
71
25
|
};
|
|
72
|
-
|
|
73
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
26
|
+
const SpFxReactToolkitTest = () => {
|
|
74
27
|
// Core Properties & Display
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
28
|
+
const { properties, setProperties } = useSPFxProperties();
|
|
29
|
+
const { isEdit } = useSPFxDisplayMode();
|
|
30
|
+
const { id, kind } = useSPFxInstanceInfo();
|
|
78
31
|
// Theme & Environment
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
32
|
+
const theme = useSPFxThemeInfo();
|
|
33
|
+
const fluent9ThemeInfo = useSPFxFluent9ThemeInfo();
|
|
34
|
+
const { type: envType } = useSPFxEnvironmentInfo();
|
|
35
|
+
const isDarkTheme = theme?.isInverted ?? false;
|
|
83
36
|
// User & Site Info
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
37
|
+
const { displayName } = useSPFxUserInfo();
|
|
38
|
+
const { title: siteTitle, webUrl, siteClassification } = useSPFxSiteInfo();
|
|
39
|
+
const localeInfo = useSPFxLocaleInfo();
|
|
87
40
|
// Teams Context
|
|
88
|
-
|
|
41
|
+
const { supported: hasTeamsContext, theme: teamsTheme } = useSPFxTeams();
|
|
89
42
|
// Page Context
|
|
90
|
-
|
|
91
|
-
|
|
43
|
+
const pageContext = useSPFxPageContext();
|
|
44
|
+
const pageTypeInfo = useSPFxPageType();
|
|
92
45
|
// List & Hub Info (can be undefined)
|
|
93
|
-
|
|
94
|
-
|
|
46
|
+
const listInfo = useSPFxListInfo();
|
|
47
|
+
const hubInfo = useSPFxHubSiteInfo();
|
|
95
48
|
// Container & Performance
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
49
|
+
const containerSize = useSPFxContainerSize();
|
|
50
|
+
const containerInfo = useSPFxContainerInfo();
|
|
51
|
+
const performance = useSPFxPerformance();
|
|
99
52
|
// Permissions
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
53
|
+
const { hasWebPermission } = useSPFxPermissions();
|
|
54
|
+
const canManageWeb = hasWebPermission(SPPermission.manageWeb);
|
|
55
|
+
const canManageLists = hasWebPermission(SPPermission.manageLists);
|
|
103
56
|
// Storage
|
|
104
|
-
|
|
105
|
-
|
|
57
|
+
const sessionStorage = useSPFxSessionStorage('demo-session-key', '');
|
|
58
|
+
const localStorage = useSPFxLocalStorage('demo-local-key', '');
|
|
106
59
|
// Advanced
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
60
|
+
const correlationInfo = useSPFxCorrelationInfo();
|
|
61
|
+
const logger = useSPFxLogger();
|
|
62
|
+
const serviceScope = useSPFxServiceScope();
|
|
110
63
|
// HTTP Clients
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
64
|
+
const spHttpClient = useSPFxSPHttpClient();
|
|
65
|
+
const msGraphClient = useSPFxMSGraphClient();
|
|
66
|
+
const aadHttpClient = useSPFxAadHttpClient();
|
|
114
67
|
// OneDrive AppData hook (using hook name as folder for demo)
|
|
115
|
-
|
|
68
|
+
const oneDriveData = useSPFxOneDriveAppData('test-data.json', { autoFetch: false, createIfMissing: true, defaultValue: { message: '', counter: 0, timestamp: 0 }, folder: 'useSPFxOneDriveAppData' });
|
|
116
69
|
// Tenant Property hook (tenant-wide configuration)
|
|
117
|
-
|
|
118
|
-
|
|
70
|
+
const tenantVersion = useSPFxTenantProperty('spfx-toolkit-test-version', false);
|
|
71
|
+
const tenantCounter = useSPFxTenantProperty('spfx-toolkit-test-counter', false);
|
|
72
|
+
// Tenant Key-Value Store hook (REST-based CRUD)
|
|
73
|
+
const tenantKVStore = useSPFxTenantKeyValueStore();
|
|
119
74
|
// User Photo hook (current user profile photo)
|
|
120
|
-
|
|
75
|
+
const userPhoto = useSPFxUserPhoto();
|
|
121
76
|
// Local state for interactive demos
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
77
|
+
const [descriptionInput, setDescriptionInput] = React.useState(properties?.description ?? '');
|
|
78
|
+
const [sessionStorageInput, setSessionStorageInput] = React.useState('');
|
|
79
|
+
const [localStorageInput, setLocalStorageInput] = React.useState('');
|
|
80
|
+
const [oneDriveMessage, setOneDriveMessage] = React.useState('');
|
|
81
|
+
const [tenantVersionInput, setTenantVersionInput] = React.useState('');
|
|
82
|
+
const [showMessage, setShowMessage] = React.useState(false);
|
|
83
|
+
const [messageText, setMessageText] = React.useState('');
|
|
84
|
+
const [performanceResult, setPerformanceResult] = React.useState('');
|
|
85
|
+
const [logMessages, setLogMessages] = React.useState([]);
|
|
86
|
+
const [crossSiteUrl, setCrossSiteUrl] = React.useState(undefined);
|
|
87
|
+
// Tenant Key-Value Store demo state
|
|
88
|
+
const [kvStoreKey, setKvStoreKey] = React.useState('');
|
|
89
|
+
const [kvStoreValue, setKvStoreValue] = React.useState('');
|
|
90
|
+
const [kvStoreDescription, setKvStoreDescription] = React.useState('');
|
|
91
|
+
const [kvStoreItems, setKvStoreItems] = React.useState([]);
|
|
92
|
+
const [kvStoreResult, setKvStoreResult] = React.useState('');
|
|
132
93
|
// Cross-site permissions (fetch only when URL is set)
|
|
133
|
-
|
|
94
|
+
const crossSitePermissions = useSPFxCrossSitePermissions(crossSiteUrl);
|
|
134
95
|
// Sync descriptionInput when properties change
|
|
135
|
-
React.useEffect(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}, [properties === null || properties === void 0 ? void 0 : properties.description]);
|
|
96
|
+
React.useEffect(() => {
|
|
97
|
+
setDescriptionInput(properties?.description ?? '');
|
|
98
|
+
}, [properties?.description]);
|
|
139
99
|
// Handlers
|
|
140
|
-
|
|
100
|
+
const handleUpdateProperties = React.useCallback(() => {
|
|
141
101
|
setProperties({ description: descriptionInput });
|
|
142
102
|
setMessageText('Properties updated successfully!');
|
|
143
103
|
setShowMessage(true);
|
|
144
|
-
setTimeout(
|
|
104
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
145
105
|
}, [descriptionInput, setProperties]);
|
|
146
|
-
|
|
106
|
+
const handleSaveSessionStorage = React.useCallback(() => {
|
|
147
107
|
sessionStorage.setValue(sessionStorageInput);
|
|
148
108
|
setSessionStorageInput('');
|
|
149
109
|
setMessageText('Value saved to session storage!');
|
|
150
110
|
setShowMessage(true);
|
|
151
|
-
setTimeout(
|
|
111
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
152
112
|
}, [sessionStorageInput, sessionStorage]);
|
|
153
|
-
|
|
113
|
+
const handleSaveLocalStorage = React.useCallback(() => {
|
|
154
114
|
localStorage.setValue(localStorageInput);
|
|
155
115
|
setLocalStorageInput('');
|
|
156
116
|
setMessageText('Value saved to local storage!');
|
|
157
117
|
setShowMessage(true);
|
|
158
|
-
setTimeout(
|
|
118
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
159
119
|
}, [localStorageInput, localStorage]);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return __generator(this, function (_a) {
|
|
166
|
-
switch (_a.label) {
|
|
167
|
-
case 0:
|
|
168
|
-
// Simulate async operation
|
|
169
|
-
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 500); })];
|
|
170
|
-
case 1:
|
|
171
|
-
// Simulate async operation
|
|
172
|
-
_a.sent();
|
|
173
|
-
return [2 /*return*/, 'Test completed'];
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
}); })];
|
|
177
|
-
case 1:
|
|
178
|
-
result = _a.sent();
|
|
179
|
-
setPerformanceResult("".concat(result.result, " in ").concat(result.durationMs.toFixed(2), "ms"));
|
|
180
|
-
return [2 /*return*/];
|
|
181
|
-
}
|
|
120
|
+
const handlePerformanceTest = React.useCallback(async () => {
|
|
121
|
+
const result = await performance.time('demo-test', async () => {
|
|
122
|
+
// Simulate async operation
|
|
123
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
124
|
+
return 'Test completed';
|
|
182
125
|
});
|
|
183
|
-
|
|
184
|
-
|
|
126
|
+
setPerformanceResult(`${result.result} in ${result.durationMs.toFixed(2)}ms`);
|
|
127
|
+
}, [performance]);
|
|
128
|
+
const handleLog = React.useCallback((level, message) => {
|
|
185
129
|
if (level === 'info')
|
|
186
130
|
logger.info(message);
|
|
187
131
|
else if (level === 'warning')
|
|
188
132
|
logger.warn(message);
|
|
189
133
|
else
|
|
190
134
|
logger.error(message);
|
|
191
|
-
setLogMessages(
|
|
135
|
+
setLogMessages(prev => [...prev.slice(-4), { level, message }]);
|
|
192
136
|
}, [logger]);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
_a.trys.push([1, 3, , 4]);
|
|
276
|
-
return [4 /*yield*/, tenantVersion.write(tenantVersionInput, 'Test version property from SPFx React Toolkit')];
|
|
277
|
-
case 2:
|
|
278
|
-
_a.sent();
|
|
279
|
-
setTenantVersionInput('');
|
|
280
|
-
setMessageText('Version saved to tenant properties!');
|
|
281
|
-
setShowMessage(true);
|
|
282
|
-
setTimeout(function () { return setShowMessage(false); }, 3000);
|
|
283
|
-
return [3 /*break*/, 4];
|
|
284
|
-
case 3:
|
|
285
|
-
error_3 = _a.sent();
|
|
286
|
-
setMessageText("Save failed: ".concat(error_3 instanceof Error ? error_3.message : 'Unknown error'));
|
|
287
|
-
setShowMessage(true);
|
|
288
|
-
setTimeout(function () { return setShowMessage(false); }, 5000);
|
|
289
|
-
return [3 /*break*/, 4];
|
|
290
|
-
case 4: return [2 /*return*/];
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
}); }, [tenantVersionInput, tenantVersion]);
|
|
294
|
-
var handleIncrementTenantCounter = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
295
|
-
var newValue, error_4;
|
|
296
|
-
var _a;
|
|
297
|
-
return __generator(this, function (_b) {
|
|
298
|
-
switch (_b.label) {
|
|
299
|
-
case 0:
|
|
300
|
-
if (!tenantCounter.canWrite) {
|
|
301
|
-
setMessageText('Insufficient permissions to write tenant properties');
|
|
302
|
-
setShowMessage(true);
|
|
303
|
-
setTimeout(function () { return setShowMessage(false); }, 5000);
|
|
304
|
-
return [2 /*return*/];
|
|
305
|
-
}
|
|
306
|
-
_b.label = 1;
|
|
307
|
-
case 1:
|
|
308
|
-
_b.trys.push([1, 3, , 4]);
|
|
309
|
-
newValue = ((_a = tenantCounter.data) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
310
|
-
return [4 /*yield*/, tenantCounter.write(newValue, 'Test counter property from SPFx React Toolkit')];
|
|
311
|
-
case 2:
|
|
312
|
-
_b.sent();
|
|
313
|
-
setMessageText("Counter incremented to ".concat(newValue, "!"));
|
|
314
|
-
setShowMessage(true);
|
|
315
|
-
setTimeout(function () { return setShowMessage(false); }, 3000);
|
|
316
|
-
return [3 /*break*/, 4];
|
|
317
|
-
case 3:
|
|
318
|
-
error_4 = _b.sent();
|
|
319
|
-
setMessageText("Increment failed: ".concat(error_4 instanceof Error ? error_4.message : 'Unknown error'));
|
|
320
|
-
setShowMessage(true);
|
|
321
|
-
setTimeout(function () { return setShowMessage(false); }, 5000);
|
|
322
|
-
return [3 /*break*/, 4];
|
|
323
|
-
case 4: return [2 /*return*/];
|
|
137
|
+
const handleLoadOneDrive = React.useCallback(async () => {
|
|
138
|
+
await oneDriveData.load();
|
|
139
|
+
setMessageText('OneDrive load completed. Check status below (missing file sets isNotFound=true).');
|
|
140
|
+
setShowMessage(true);
|
|
141
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
142
|
+
}, [oneDriveData]);
|
|
143
|
+
const handleSaveOneDrive = React.useCallback(async () => {
|
|
144
|
+
try {
|
|
145
|
+
const newData = {
|
|
146
|
+
message: oneDriveMessage,
|
|
147
|
+
counter: (oneDriveData.data?.counter ?? 0) + 1,
|
|
148
|
+
timestamp: Date.now(),
|
|
149
|
+
};
|
|
150
|
+
await oneDriveData.write(newData);
|
|
151
|
+
setOneDriveMessage('');
|
|
152
|
+
setMessageText('Data saved to OneDrive successfully!');
|
|
153
|
+
setShowMessage(true);
|
|
154
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
setMessageText(`Save failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
158
|
+
setShowMessage(true);
|
|
159
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
160
|
+
}
|
|
161
|
+
}, [oneDriveMessage, oneDriveData]);
|
|
162
|
+
const handleLoadTenantProperty = React.useCallback(async () => {
|
|
163
|
+
try {
|
|
164
|
+
await Promise.all([
|
|
165
|
+
tenantVersion.load(),
|
|
166
|
+
tenantCounter.load()
|
|
167
|
+
]);
|
|
168
|
+
setMessageText('Tenant properties loaded successfully!');
|
|
169
|
+
setShowMessage(true);
|
|
170
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
setMessageText(`Load failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
174
|
+
setShowMessage(true);
|
|
175
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
176
|
+
}
|
|
177
|
+
}, [tenantVersion, tenantCounter]);
|
|
178
|
+
const handleSaveTenantVersion = React.useCallback(async () => {
|
|
179
|
+
setMessageText('Write operations are no longer supported via REST API. Use PowerShell instead.');
|
|
180
|
+
setShowMessage(true);
|
|
181
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
182
|
+
}, []);
|
|
183
|
+
const handleIncrementTenantCounter = React.useCallback(async () => {
|
|
184
|
+
setMessageText('Write operations are no longer supported via REST API. Use PowerShell instead.');
|
|
185
|
+
setShowMessage(true);
|
|
186
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
187
|
+
}, []);
|
|
188
|
+
const handleRemoveTenantProperty = React.useCallback(async (_propertyName) => {
|
|
189
|
+
setMessageText('Remove operations are no longer supported via REST API. Use PowerShell instead.');
|
|
190
|
+
setShowMessage(true);
|
|
191
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
192
|
+
}, []);
|
|
193
|
+
// Tenant Key-Value Store handlers
|
|
194
|
+
const handleKVStoreList = React.useCallback(async () => {
|
|
195
|
+
try {
|
|
196
|
+
const items = await tenantKVStore.list();
|
|
197
|
+
setKvStoreItems(items);
|
|
198
|
+
setMessageText(`Listed ${items.length} item(s) from tenant key-value store.`);
|
|
199
|
+
setShowMessage(true);
|
|
200
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
setMessageText(`List failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
204
|
+
setShowMessage(true);
|
|
205
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
206
|
+
}
|
|
207
|
+
}, [tenantKVStore]);
|
|
208
|
+
const handleKVStoreGet = React.useCallback(async () => {
|
|
209
|
+
if (!kvStoreKey) {
|
|
210
|
+
setMessageText('Please enter a key to look up.');
|
|
211
|
+
setShowMessage(true);
|
|
212
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const item = await tenantKVStore.get(kvStoreKey);
|
|
217
|
+
if (item) {
|
|
218
|
+
setKvStoreResult(`Key: ${item.key}, Value: ${typeof item.value === 'object' ? JSON.stringify(item.value) : String(item.value)}${item.description ? `, Description: ${item.description}` : ''}`);
|
|
324
219
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
var handleRemoveTenantProperty = React.useCallback(function (propertyName) { return __awaiter(void 0, void 0, void 0, function () {
|
|
328
|
-
var hook, error_5;
|
|
329
|
-
return __generator(this, function (_a) {
|
|
330
|
-
switch (_a.label) {
|
|
331
|
-
case 0:
|
|
332
|
-
hook = propertyName === 'version' ? tenantVersion : tenantCounter;
|
|
333
|
-
if (!hook.canWrite) {
|
|
334
|
-
setMessageText('Insufficient permissions to remove tenant properties');
|
|
335
|
-
setShowMessage(true);
|
|
336
|
-
setTimeout(function () { return setShowMessage(false); }, 5000);
|
|
337
|
-
return [2 /*return*/];
|
|
338
|
-
}
|
|
339
|
-
if (!confirm("Are you sure you want to remove the ".concat(propertyName, " property?"))) {
|
|
340
|
-
return [2 /*return*/];
|
|
341
|
-
}
|
|
342
|
-
_a.label = 1;
|
|
343
|
-
case 1:
|
|
344
|
-
_a.trys.push([1, 3, , 4]);
|
|
345
|
-
return [4 /*yield*/, hook.remove()];
|
|
346
|
-
case 2:
|
|
347
|
-
_a.sent();
|
|
348
|
-
setMessageText("".concat(propertyName, " property removed!"));
|
|
349
|
-
setShowMessage(true);
|
|
350
|
-
setTimeout(function () { return setShowMessage(false); }, 3000);
|
|
351
|
-
return [3 /*break*/, 4];
|
|
352
|
-
case 3:
|
|
353
|
-
error_5 = _a.sent();
|
|
354
|
-
setMessageText("Remove failed: ".concat(error_5 instanceof Error ? error_5.message : 'Unknown error'));
|
|
355
|
-
setShowMessage(true);
|
|
356
|
-
setTimeout(function () { return setShowMessage(false); }, 5000);
|
|
357
|
-
return [3 /*break*/, 4];
|
|
358
|
-
case 4: return [2 /*return*/];
|
|
220
|
+
else {
|
|
221
|
+
setKvStoreResult('(not found)');
|
|
359
222
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
223
|
+
setMessageText(item ? `Found key "${kvStoreKey}".` : `Key "${kvStoreKey}" not found.`);
|
|
224
|
+
setShowMessage(true);
|
|
225
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
setMessageText(`Get failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
229
|
+
setShowMessage(true);
|
|
230
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
231
|
+
}
|
|
232
|
+
}, [tenantKVStore, kvStoreKey]);
|
|
233
|
+
const handleKVStoreSave = React.useCallback(async () => {
|
|
234
|
+
if (!kvStoreKey || !kvStoreValue) {
|
|
235
|
+
setMessageText('Please enter both a key and a value.');
|
|
236
|
+
setShowMessage(true);
|
|
237
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
await tenantKVStore.save(kvStoreKey, kvStoreValue, kvStoreDescription || undefined);
|
|
242
|
+
setMessageText(`Saved key "${kvStoreKey}" successfully.`);
|
|
243
|
+
setShowMessage(true);
|
|
244
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
setMessageText(`Save failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
248
|
+
setShowMessage(true);
|
|
249
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
250
|
+
}
|
|
251
|
+
}, [tenantKVStore, kvStoreKey, kvStoreValue, kvStoreDescription]);
|
|
252
|
+
const handleKVStoreRemove = React.useCallback(async () => {
|
|
253
|
+
if (!kvStoreKey) {
|
|
254
|
+
setMessageText('Please enter a key to remove.');
|
|
255
|
+
setShowMessage(true);
|
|
256
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
await tenantKVStore.remove(kvStoreKey);
|
|
261
|
+
setKvStoreResult('');
|
|
262
|
+
setMessageText(`Removed key "${kvStoreKey}" successfully.`);
|
|
263
|
+
setShowMessage(true);
|
|
264
|
+
setTimeout(() => setShowMessage(false), 3000);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
setMessageText(`Remove failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
268
|
+
setShowMessage(true);
|
|
269
|
+
setTimeout(() => setShowMessage(false), 5000);
|
|
270
|
+
}
|
|
271
|
+
}, [tenantKVStore, kvStoreKey]);
|
|
272
|
+
return (React.createElement("section", { className: `${styles.spFxReactToolkitTest} ${hasTeamsContext ? styles.teams : ''}` },
|
|
273
|
+
showMessage && (React.createElement(MessageBar, { messageBarType: MessageBarType.success, onDismiss: () => setShowMessage(false) }, messageText)),
|
|
364
274
|
React.createElement(Pivot, { "aria-label": "SPFx React Toolkit Demo Tabs", style: { marginTop: '20px' } },
|
|
365
275
|
React.createElement(PivotItem, { headerText: "Overview", itemIcon: "Home" },
|
|
366
276
|
React.createElement(Stack, { tokens: { childrenGap: 4 }, styles: { root: { marginTop: '16px' } } },
|
|
@@ -379,7 +289,7 @@ var SpFxReactToolkitTest = function () {
|
|
|
379
289
|
React.createElement(Icon, { iconName: "Settings", style: { marginRight: '8px' } }),
|
|
380
290
|
"Properties Editor",
|
|
381
291
|
React.createElement(Separator, null)),
|
|
382
|
-
React.createElement(TextField, { label: "Description Property", value: descriptionInput, onChange:
|
|
292
|
+
React.createElement(TextField, { label: "Description Property", value: descriptionInput, onChange: (_, newValue) => setDescriptionInput(newValue ?? ''), placeholder: "Enter description..." }),
|
|
383
293
|
React.createElement(PrimaryButton, { text: "Update Properties", onClick: handleUpdateProperties, iconProps: { iconName: 'Save' } }),
|
|
384
294
|
React.createElement(Label, null,
|
|
385
295
|
React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
@@ -389,8 +299,8 @@ var SpFxReactToolkitTest = function () {
|
|
|
389
299
|
React.createElement(Icon, { iconName: "Resize", style: { marginRight: '8px' } }),
|
|
390
300
|
"Container Information",
|
|
391
301
|
React.createElement(Separator, null)),
|
|
392
|
-
React.createElement(InfoRow, { label: "Width", value:
|
|
393
|
-
React.createElement(InfoRow, { label: "Height", value:
|
|
302
|
+
React.createElement(InfoRow, { label: "Width", value: `${containerSize.width}px`, icon: "ArrowRight" }),
|
|
303
|
+
React.createElement(InfoRow, { label: "Height", value: `${containerSize.height}px`, icon: "ArrowUp" }),
|
|
394
304
|
React.createElement(InfoRow, { label: "DOM Element", value: containerInfo.element ? 'Available' : 'N/A', icon: "DOM" }),
|
|
395
305
|
React.createElement(InfoRow, { label: "Size Tracking", value: containerInfo.size ? 'Active' : 'Inactive', icon: "RadioBullet" }))))),
|
|
396
306
|
React.createElement(PivotItem, { headerText: "Context", itemIcon: "Contact" },
|
|
@@ -414,7 +324,7 @@ var SpFxReactToolkitTest = function () {
|
|
|
414
324
|
React.createElement(InfoRow, { label: "Text Direction", value: localeInfo.isRtl ? 'Right-to-Left (RTL)' : 'Left-to-Right (LTR)', icon: "TextAlignLeft" }),
|
|
415
325
|
localeInfo.timeZone && (React.createElement(React.Fragment, null,
|
|
416
326
|
React.createElement(InfoRow, { label: "Time Zone", value: localeInfo.timeZone.description, icon: "Clock" }),
|
|
417
|
-
React.createElement(InfoRow, { label: "UTC Offset", value:
|
|
327
|
+
React.createElement(InfoRow, { label: "UTC Offset", value: `${localeInfo.timeZone.offset} minutes`, icon: "DateTime" }),
|
|
418
328
|
React.createElement(Label, null,
|
|
419
329
|
React.createElement(Icon, { iconName: "Info", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
420
330
|
"Current time: ",
|
|
@@ -435,7 +345,7 @@ var SpFxReactToolkitTest = function () {
|
|
|
435
345
|
"Microsoft Teams Context",
|
|
436
346
|
React.createElement(Separator, null)),
|
|
437
347
|
React.createElement(InfoRow, { label: "Teams Supported", value: "Yes", icon: "CompletedSolid" }),
|
|
438
|
-
React.createElement(InfoRow, { label: "Teams Theme", value: teamsTheme
|
|
348
|
+
React.createElement(InfoRow, { label: "Teams Theme", value: teamsTheme ?? 'default', icon: "Color" }))),
|
|
439
349
|
listInfo && (React.createElement(Stack, { tokens: { childrenGap: 2 } },
|
|
440
350
|
React.createElement("h3", null,
|
|
441
351
|
React.createElement(Icon, { iconName: "BulletedList", style: { marginRight: '8px' } }),
|
|
@@ -447,7 +357,7 @@ var SpFxReactToolkitTest = function () {
|
|
|
447
357
|
listInfo.isDocumentLibrary && (React.createElement(Label, null,
|
|
448
358
|
React.createElement(Icon, { iconName: "FabricFolder", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
449
359
|
"Document Library")))),
|
|
450
|
-
|
|
360
|
+
hubInfo?.isHubSite && (React.createElement(Stack, { tokens: { childrenGap: 2 } },
|
|
451
361
|
React.createElement("h3", null,
|
|
452
362
|
React.createElement(Icon, { iconName: "NetworkTower", style: { marginRight: '8px' } }),
|
|
453
363
|
"Hub Site Association",
|
|
@@ -474,7 +384,7 @@ var SpFxReactToolkitTest = function () {
|
|
|
474
384
|
React.createElement(Label, null,
|
|
475
385
|
React.createElement(Icon, { iconName: "Info", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
476
386
|
"Check permissions on a different site (auto-fetch when URL is provided)"),
|
|
477
|
-
React.createElement(TextField, { label: "Target Site URL", value: crossSiteUrl || '', onChange:
|
|
387
|
+
React.createElement(TextField, { label: "Target Site URL", value: crossSiteUrl || '', onChange: (_, value) => setCrossSiteUrl(value?.trim() || undefined), placeholder: "https://contoso.sharepoint.com/sites/targetsite", description: "Enter a site URL - permissions will be fetched automatically" }),
|
|
478
388
|
crossSitePermissions.isLoading && (React.createElement(MessageBar, { messageBarType: MessageBarType.info },
|
|
479
389
|
"Loading permissions from ",
|
|
480
390
|
crossSiteUrl,
|
|
@@ -554,7 +464,7 @@ var SpFxReactToolkitTest = function () {
|
|
|
554
464
|
React.createElement(InfoRow, { label: "Is Not Found", value: oneDriveData.isNotFound ? 'Yes' : 'No', icon: "BlockedSiteSolid12" }))) : (React.createElement(Label, null, oneDriveData.isNotFound
|
|
555
465
|
? 'No file found yet. Click "Save to OneDrive" to create it.'
|
|
556
466
|
: 'No data loaded yet. Click "Load" to fetch from OneDrive.')),
|
|
557
|
-
React.createElement(TextField, { label: "New Message", value: oneDriveMessage, onChange:
|
|
467
|
+
React.createElement(TextField, { label: "New Message", value: oneDriveMessage, onChange: (_, newValue) => setOneDriveMessage(newValue ?? ''), placeholder: "Enter a message to save...", disabled: oneDriveData.isWriting || oneDriveData.isLoading }),
|
|
558
468
|
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
|
|
559
469
|
React.createElement(PrimaryButton, { text: "Load from OneDrive", onClick: handleLoadOneDrive, disabled: oneDriveData.isLoading || oneDriveData.isWriting, iconProps: { iconName: 'CloudDownload' } }),
|
|
560
470
|
React.createElement(PrimaryButton, { text: oneDriveData.isWriting ? 'Saving...' : 'Save to OneDrive', onClick: handleSaveOneDrive, disabled: !oneDriveMessage || oneDriveData.isWriting || oneDriveData.isLoading, iconProps: { iconName: 'CloudUpload' } })),
|
|
@@ -571,38 +481,69 @@ var SpFxReactToolkitTest = function () {
|
|
|
571
481
|
React.createElement(Separator, null)),
|
|
572
482
|
(tenantVersion.error || tenantCounter.error) && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
|
|
573
483
|
"Load Error: ",
|
|
574
|
-
|
|
575
|
-
(tenantVersion.writeError || tenantCounter.writeError) && (React.createElement(MessageBar, { messageBarType: MessageBarType.warning },
|
|
576
|
-
"Write Error: ",
|
|
577
|
-
((_e = tenantVersion.writeError) === null || _e === void 0 ? void 0 : _e.message) || ((_f = tenantCounter.writeError) === null || _f === void 0 ? void 0 : _f.message))),
|
|
484
|
+
tenantVersion.error?.message || tenantCounter.error?.message)),
|
|
578
485
|
(tenantVersion.isLoading || tenantCounter.isLoading) ? (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "Loading from tenant app catalog...")) : (tenantVersion.data || tenantCounter.data) ? (React.createElement(Stack, { tokens: { childrenGap: 1 } },
|
|
579
|
-
React.createElement(InfoRow, { label: "Version", value:
|
|
486
|
+
React.createElement(InfoRow, { label: "Version", value: tenantVersion.data ?? '(not set)', icon: "ServerEnviroment" }),
|
|
580
487
|
tenantVersion.description && (React.createElement(Label, null,
|
|
581
488
|
React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
582
489
|
tenantVersion.description)),
|
|
583
|
-
React.createElement(InfoRow, { label: "Counter", value: String(
|
|
490
|
+
React.createElement(InfoRow, { label: "Counter", value: String(tenantCounter.data ?? 0), icon: "NumberField" }),
|
|
584
491
|
tenantCounter.description && (React.createElement(Label, null,
|
|
585
492
|
React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
586
493
|
tenantCounter.description)),
|
|
587
|
-
React.createElement(InfoRow, { label: "
|
|
588
|
-
React.createElement(TextField, { label: "New Version", value: tenantVersionInput, onChange:
|
|
494
|
+
React.createElement(InfoRow, { label: "Mode", value: "Read-only (REST write blocked by Microsoft)", icon: "Permissions" }))) : (React.createElement(Label, null, "No data loaded yet. Click \"Load\" to fetch from tenant properties.")),
|
|
495
|
+
React.createElement(TextField, { label: "New Version", value: tenantVersionInput, onChange: (_, newValue) => setTenantVersionInput(newValue ?? ''), placeholder: "e.g., 1.0.0", disabled: tenantVersion.isLoading }),
|
|
589
496
|
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
|
|
590
497
|
React.createElement(PrimaryButton, { text: "Load Properties", onClick: handleLoadTenantProperty, disabled: tenantVersion.isLoading || tenantCounter.isLoading, iconProps: { iconName: 'CloudDownload' } }),
|
|
591
|
-
React.createElement(PrimaryButton, { text:
|
|
592
|
-
React.createElement(PrimaryButton, { text:
|
|
498
|
+
React.createElement(PrimaryButton, { text: "Save Version (disabled)", onClick: handleSaveTenantVersion, disabled: true, iconProps: { iconName: 'Save' } }),
|
|
499
|
+
React.createElement(PrimaryButton, { text: "Increment Counter (disabled)", onClick: handleIncrementTenantCounter, disabled: true, iconProps: { iconName: 'Add' } })),
|
|
593
500
|
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
|
|
594
|
-
React.createElement(DefaultButton, { text: "Remove Version", onClick:
|
|
595
|
-
React.createElement(DefaultButton, { text: "Remove Counter", onClick:
|
|
501
|
+
React.createElement(DefaultButton, { text: "Remove Version (disabled)", onClick: () => handleRemoveTenantProperty('version'), disabled: true, iconProps: { iconName: 'Delete' } }),
|
|
502
|
+
React.createElement(DefaultButton, { text: "Remove Counter (disabled)", onClick: () => handleRemoveTenantProperty('counter'), disabled: true, iconProps: { iconName: 'Delete' } })),
|
|
596
503
|
React.createElement(Label, null,
|
|
597
504
|
React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
598
|
-
"Properties are
|
|
505
|
+
"Properties are read-only via REST API. Microsoft has blocked SetStorageEntity and RemoveStorageEntity endpoints."),
|
|
599
506
|
React.createElement(Label, null,
|
|
600
507
|
React.createElement(Icon, { iconName: "Info", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
601
508
|
"Keys: spfx-toolkit-test-version (string), spfx-toolkit-test-counter (number)"),
|
|
602
509
|
React.createElement(Label, null,
|
|
603
510
|
React.createElement(Icon, { iconName: "Warning", style: { marginRight: '4px', color: '#d83b01' } }),
|
|
604
|
-
"
|
|
605
|
-
|
|
511
|
+
"Use PowerShell (Set-PnPStorageEntity) to write tenant properties. For REST CRUD, use useSPFxTenantKeyValueStore."),
|
|
512
|
+
React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "\u2139\uFE0F Write operations require PowerShell. Use useSPFxTenantKeyValueStore for REST-based CRUD.")),
|
|
513
|
+
React.createElement(Stack, { tokens: { childrenGap: 2 } },
|
|
514
|
+
React.createElement("h3", null,
|
|
515
|
+
React.createElement(Icon, { iconName: "TableGroup", style: { marginRight: '8px' } }),
|
|
516
|
+
"Tenant Key-Value Store Demo",
|
|
517
|
+
React.createElement(Separator, null)),
|
|
518
|
+
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 8 } },
|
|
519
|
+
React.createElement(StatusBadge, { label: "Ready", available: tenantKVStore.isReady }),
|
|
520
|
+
React.createElement(StatusBadge, { label: "Can Write", available: tenantKVStore.canWrite })),
|
|
521
|
+
tenantKVStore.error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
|
|
522
|
+
"Read Error: ",
|
|
523
|
+
tenantKVStore.error.message)),
|
|
524
|
+
tenantKVStore.writeError && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
|
|
525
|
+
"Write Error: ",
|
|
526
|
+
tenantKVStore.writeError.message)),
|
|
527
|
+
React.createElement(TextField, { label: "Key", value: kvStoreKey, onChange: (_, v) => setKvStoreKey(v ?? ''), placeholder: "e.g., apiEndpoint" }),
|
|
528
|
+
React.createElement(TextField, { label: "Value", value: kvStoreValue, onChange: (_, v) => setKvStoreValue(v ?? ''), placeholder: "e.g., https://api.example.com" }),
|
|
529
|
+
React.createElement(TextField, { label: "Description (optional)", value: kvStoreDescription, onChange: (_, v) => setKvStoreDescription(v ?? ''), placeholder: "e.g., Production API endpoint" }),
|
|
530
|
+
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
|
|
531
|
+
React.createElement(PrimaryButton, { text: "List All", onClick: handleKVStoreList, disabled: tenantKVStore.isLoading || !tenantKVStore.isReady, iconProps: { iconName: 'BulletedList' } }),
|
|
532
|
+
React.createElement(PrimaryButton, { text: "Get", onClick: handleKVStoreGet, disabled: tenantKVStore.isLoading || !tenantKVStore.isReady, iconProps: { iconName: 'Search' } }),
|
|
533
|
+
React.createElement(PrimaryButton, { text: "Save", onClick: handleKVStoreSave, disabled: tenantKVStore.isWriting || !tenantKVStore.isReady, iconProps: { iconName: 'Save' } }),
|
|
534
|
+
React.createElement(DefaultButton, { text: "Remove", onClick: handleKVStoreRemove, disabled: tenantKVStore.isWriting || !tenantKVStore.isReady, iconProps: { iconName: 'Delete' } })),
|
|
535
|
+
kvStoreResult && (React.createElement(InfoRow, { label: "Get Result", value: kvStoreResult, icon: "StatusCircleCheckmark" })),
|
|
536
|
+
kvStoreItems.length > 0 && (React.createElement(Stack, { tokens: { childrenGap: 1 } },
|
|
537
|
+
React.createElement(Label, null,
|
|
538
|
+
React.createElement(Icon, { iconName: "BulletedList", style: { marginRight: '4px' } }),
|
|
539
|
+
"All Items (",
|
|
540
|
+
kvStoreItems.length,
|
|
541
|
+
")"),
|
|
542
|
+
kvStoreItems.map(item => (React.createElement(InfoRow, { key: item.id, label: item.key, value: typeof item.value === 'object' ? JSON.stringify(item.value) : String(item.value), icon: "Variable" }))))),
|
|
543
|
+
(tenantKVStore.isLoading || tenantKVStore.isWriting) && (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, tenantKVStore.isWriting ? 'Writing...' : 'Loading...')),
|
|
544
|
+
React.createElement(Label, null,
|
|
545
|
+
React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
546
|
+
"Uses hidden list \"TenantKeyValueStore\" in tenant app catalog. Requires Site Collection Admin for write.")),
|
|
606
547
|
React.createElement(Stack, { tokens: { childrenGap: 2 } },
|
|
607
548
|
React.createElement("h3", null,
|
|
608
549
|
React.createElement(Icon, { iconName: "Database", style: { marginRight: '8px' } }),
|
|
@@ -610,9 +551,9 @@ var SpFxReactToolkitTest = function () {
|
|
|
610
551
|
React.createElement(Separator, null)),
|
|
611
552
|
React.createElement(InfoRow, { label: "Current Value", value: sessionStorage.value || '(empty)', icon: "Variable" }),
|
|
612
553
|
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
|
|
613
|
-
React.createElement(TextField, { value: sessionStorageInput, onChange:
|
|
554
|
+
React.createElement(TextField, { value: sessionStorageInput, onChange: (_, newValue) => setSessionStorageInput(newValue ?? ''), placeholder: "Enter value...", styles: { root: { flexGrow: 1 } } }),
|
|
614
555
|
React.createElement(PrimaryButton, { text: "Save", onClick: handleSaveSessionStorage, iconProps: { iconName: 'Save' } }),
|
|
615
|
-
React.createElement(DefaultButton, { text: "Clear", onClick:
|
|
556
|
+
React.createElement(DefaultButton, { text: "Clear", onClick: () => sessionStorage.remove(), iconProps: { iconName: 'Delete' } })),
|
|
616
557
|
React.createElement(Label, null,
|
|
617
558
|
React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
618
559
|
"Persists only for current tab/session")),
|
|
@@ -623,9 +564,9 @@ var SpFxReactToolkitTest = function () {
|
|
|
623
564
|
React.createElement(Separator, null)),
|
|
624
565
|
React.createElement(InfoRow, { label: "Current Value", value: localStorage.value || '(empty)', icon: "Variable" }),
|
|
625
566
|
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
|
|
626
|
-
React.createElement(TextField, { value: localStorageInput, onChange:
|
|
567
|
+
React.createElement(TextField, { value: localStorageInput, onChange: (_, newValue) => setLocalStorageInput(newValue ?? ''), placeholder: "Enter value...", styles: { root: { flexGrow: 1 } } }),
|
|
627
568
|
React.createElement(PrimaryButton, { text: "Save", onClick: handleSaveLocalStorage, iconProps: { iconName: 'Save' } }),
|
|
628
|
-
React.createElement(DefaultButton, { text: "Clear", onClick:
|
|
569
|
+
React.createElement(DefaultButton, { text: "Clear", onClick: () => localStorage.remove(), iconProps: { iconName: 'Delete' } })),
|
|
629
570
|
React.createElement(Label, null,
|
|
630
571
|
React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
|
|
631
572
|
"Persists across sessions and page reloads")),
|
|
@@ -642,17 +583,17 @@ var SpFxReactToolkitTest = function () {
|
|
|
642
583
|
"Logger Demo",
|
|
643
584
|
React.createElement(Separator, null)),
|
|
644
585
|
React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
|
|
645
|
-
React.createElement(DefaultButton, { text: "Info", onClick:
|
|
646
|
-
React.createElement(DefaultButton, { text: "Warning", onClick:
|
|
647
|
-
React.createElement(DefaultButton, { text: "Error", onClick:
|
|
586
|
+
React.createElement(DefaultButton, { text: "Info", onClick: () => handleLog('info', 'This is an info message'), iconProps: { iconName: 'Info' } }),
|
|
587
|
+
React.createElement(DefaultButton, { text: "Warning", onClick: () => handleLog('warning', 'This is a warning message'), iconProps: { iconName: 'Warning' } }),
|
|
588
|
+
React.createElement(DefaultButton, { text: "Error", onClick: () => handleLog('error', 'This is an error message'), iconProps: { iconName: 'Error' } })),
|
|
648
589
|
logMessages.length > 0 && (React.createElement(Stack, { tokens: { childrenGap: 2 }, styles: { root: { marginTop: '8px' } } },
|
|
649
590
|
React.createElement(Label, null, "Recent Logs (check browser console):"),
|
|
650
|
-
logMessages.map(
|
|
651
|
-
|
|
591
|
+
logMessages.map((log, idx) => {
|
|
592
|
+
const levelClass = log.level === 'info' ? styles.info :
|
|
652
593
|
log.level === 'warning' ? styles.warning :
|
|
653
594
|
log.level === 'error' ? styles.error :
|
|
654
595
|
styles.verbose;
|
|
655
|
-
return (React.createElement("div", { key: idx, className:
|
|
596
|
+
return (React.createElement("div", { key: idx, className: `${styles.logMessage} ${levelClass}` },
|
|
656
597
|
React.createElement("strong", null,
|
|
657
598
|
"[",
|
|
658
599
|
log.level.toUpperCase(),
|
|
@@ -674,9 +615,9 @@ var SpFxReactToolkitTest = function () {
|
|
|
674
615
|
"Theme Information",
|
|
675
616
|
React.createElement(Separator, null)),
|
|
676
617
|
React.createElement(InfoRow, { label: "Is Dark Theme", value: isDarkTheme ? 'Yes' : 'No', icon: "Brightness" }),
|
|
677
|
-
React.createElement(InfoRow, { label: "Body Background", value:
|
|
678
|
-
React.createElement(InfoRow, { label: "Body Text", value:
|
|
679
|
-
React.createElement(InfoRow, { label: "Link Color", value:
|
|
618
|
+
React.createElement(InfoRow, { label: "Body Background", value: theme?.semanticColors?.bodyBackground ?? 'N/A', icon: "FabricFolderFill" }),
|
|
619
|
+
React.createElement(InfoRow, { label: "Body Text", value: theme?.semanticColors?.bodyText ?? 'N/A', icon: "Font" }),
|
|
620
|
+
React.createElement(InfoRow, { label: "Link Color", value: theme?.semanticColors?.link ?? 'N/A', icon: "Link" })),
|
|
680
621
|
React.createElement(Stack, { tokens: { childrenGap: 2 } },
|
|
681
622
|
React.createElement("h3", null,
|
|
682
623
|
React.createElement(Icon, { iconName: "Color", style: { marginRight: '8px' } }),
|