datastake-daf 0.6.808 → 0.6.809

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.
Files changed (38) hide show
  1. package/dist/components/index.js +2104 -1654
  2. package/dist/hooks/index.js +11 -4
  3. package/dist/pages/index.js +222 -208
  4. package/dist/services/index.js +19 -5
  5. package/dist/utils/index.js +24 -5
  6. package/package.json +1 -1
  7. package/src/@daf/core/components/AuthForm/index.jsx +12 -3
  8. package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/TopContributors/index.jsx +0 -1
  9. package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/UserGrowth/hook.js +0 -1
  10. package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/UserGrowth/index.jsx +1 -3
  11. package/src/@daf/core/components/Screens/Admin/AdminModals/CombineLocation/index.jsx +51 -51
  12. package/src/@daf/core/components/Screens/Admin/AdminModals/CombineSubjects/index.jsx +6 -1
  13. package/src/@daf/core/components/Screens/Admin/AdminModals/NewAccount/index.jsx +47 -12
  14. package/src/@daf/core/components/Screens/Admin/AdminModals/NewUser/index.jsx +36 -10
  15. package/src/@daf/core/components/Screens/Admin/AdminModals/TransferRights/index.jsx +1 -1
  16. package/src/@daf/core/components/Screens/Admin/AdminScreens/Accounts.jsx +1 -0
  17. package/src/@daf/core/components/Screens/Admin/AdminScreens/Dashboard.jsx +2 -2
  18. package/src/@daf/core/components/Screens/Admin/AdminTables/AccountTable/helper.js +22 -30
  19. package/src/@daf/core/components/Screens/Admin/AdminTables/AccountTable/index.jsx +4 -3
  20. package/src/@daf/core/components/Screens/Admin/AdminTables/LocationTable/index.jsx +6 -2
  21. package/src/@daf/core/components/Screens/Admin/AdminTables/SubjectsTable/index.jsx +14 -12
  22. package/src/@daf/core/components/Screens/Admin/AdminTables/UserTable/index.jsx +0 -1
  23. package/src/@daf/core/components/Screens/Admin/AdminTables/hook.js +3 -0
  24. package/src/@daf/core/components/Screens/Admin/AdminViews/components/Edit/index.jsx +12 -9
  25. package/src/@daf/core/components/Screens/Admin/AdminViews/components/Users/index.jsx +16 -4
  26. package/src/@daf/core/components/Screens/Admin/AdminViews/components/View/helpers.js +9 -17
  27. package/src/@daf/core/components/Screens/Admin/AdminViews/index.jsx +9 -8
  28. package/src/@daf/core/components/Screens/Admin/AppInvitation/index.jsx +124 -99
  29. package/src/@daf/hooks/useAdminDashboard.js +7 -4
  30. package/src/@daf/services/AdminService.js +15 -4
  31. package/src/@daf/services/DashboardService.js +3 -3
  32. package/src/@daf/utils/filters.js +13 -15
  33. package/src/constants/locales/en/translation.js +9 -0
  34. package/build/favicon.ico +0 -0
  35. package/build/logo192.png +0 -0
  36. package/build/logo512.png +0 -0
  37. package/build/manifest.json +0 -25
  38. package/build/robots.txt +0 -3
@@ -34,6 +34,7 @@ export default function Users({
34
34
  inviteCompanyAccount = () => {},
35
35
  companyId,
36
36
  handleError = () => {},
37
+
37
38
  }) {
38
39
  const [hasError, setHasError] = useState(false);
39
40
  const [showFilters, setShowFilters] = useState(false);
@@ -72,9 +73,9 @@ export default function Users({
72
73
  const onDeleteUserClick = useCallback(
73
74
  (id) => {
74
75
  Modal.confirm({
75
- title: t("sbg-admin::remove-user-title"),
76
+ title: t("Are-you-sure-you-want-to-remove-the-user-from-this-account?"),
76
77
  icon: <ExclamationCircleOutlined />,
77
- content: t("sbg-admin::remove-user-body"),
78
+ content: <span style={{ color: "#888" }}>{t("The-user-will-lose-access-to-the-application-and-to-all-data-created-for-this-account.")}</span>,
78
79
  okText: t("Yes"),
79
80
  cancelText: t("No"),
80
81
  onOk: () => {
@@ -87,8 +88,15 @@ export default function Users({
87
88
  );
88
89
 
89
90
  const data = useMemo(() => {
90
- const { users = [] } = accountData;
91
- let filtered = [...users];
91
+ const { users = [], pendingUsers = [] } = accountData;
92
+ let filtered = [
93
+ ...users,
94
+ ...pendingUsers.map(u => ({
95
+ ...u,
96
+ status: 'pending',
97
+ id: u.invitationToken || u.email // ensure pending users have an ID
98
+ }))
99
+ ];
92
100
 
93
101
  if (!isEmptyOrSpaces(activeFilters.search)) {
94
102
  const search = activeFilters.search.toLowerCase();
@@ -186,6 +194,10 @@ export default function Users({
186
194
  inviteCompanyAccount={inviteCompanyAccount}
187
195
  companyId={companyId}
188
196
  handleError={handleError}
197
+ existingEmails={[
198
+ ...(accountData?.users || []).map(u => u.email?.toLowerCase()),
199
+ ...(accountData?.pendingUsers || []).map(u => u.email?.toLowerCase()),
200
+ ].filter(Boolean)}
189
201
  />
190
202
  </div>
191
203
  );
@@ -1,23 +1,15 @@
1
1
  import { Tag } from "antd";
2
2
 
3
3
  export const renderStatus = ({ val, t = (s) => s }) => {
4
- // switch (val) {
5
- // case "active":
6
- // return <Tag color="green">{t("Active")}</Tag>;
7
- // case "unsaved":
8
- // return <Tag color="red">{t("Unsaved")}</Tag>;
9
- // case "inactive":
10
- // case "suspended":
11
- // return <Tag color="red">{t("Suspended")}</Tag>;
12
- // case "pending":
13
- // return <Tag color="orange">{t("Pending")}</Tag>;
14
- // default:
15
- // return <Tag color="default">{t("Unknown")}</Tag>;
16
- // }
17
-
18
- if (val) {
4
+ if (val === 'pending') {
5
+ return <Tag color="orange">{t("Pending")}</Tag>;
6
+ }
7
+ if (val === 'unsaved') {
8
+ return <Tag color="red">{t("Unsaved")}</Tag>;
9
+ }
10
+ if (val === 'active' || val === true) {
19
11
  return <Tag color="green">{t("Active")}</Tag>;
20
- } else {
21
- return <Tag color="red">{t("Suspended")}</Tag>;
22
12
  }
13
+
14
+ return <Tag color="red">{t("Suspended")}</Tag>;
23
15
  };
@@ -172,14 +172,15 @@ function AdminView({
172
172
  try {
173
173
  const { pendingCompanyId, status, ...userDataToInvite } = user;
174
174
  console.log('Sending invitation for:', user.email, userDataToInvite);
175
- await inviteCompanyAccount({
176
- companyId: editData.id,
177
- data: {
178
- ...userDataToInvite,
179
- pendingCompanyId,
180
- },
181
- });
182
- console.log('Invitation sent successfully for:', user.email);
175
+ // Use the standalone invite function, don't mix it with updateAccount
176
+ // await inviteCompanyAccount({
177
+ // companyId: editData.id,
178
+ // data: {
179
+ // ...userDataToInvite,
180
+ // pendingCompanyId,
181
+ // },
182
+ // });
183
+ // console.log('Invitation sent successfully for:', user.email);
183
184
  } catch (inviteError) {
184
185
  console.error('Failed to invite user:', user.email, inviteError);
185
186
  handleError(inviteError);
@@ -1,30 +1,30 @@
1
1
  import React, { useState, useEffect } from "react";
2
- import { Checkbox, Form, Input, message } from 'antd';
2
+ import { Checkbox, message } from 'antd';
3
3
  import DafButton from '../../../Button/index.jsx';
4
4
  import Loading from "../../../Loading/index.jsx";
5
+ import AuthForm from "../../../AuthForm/index.jsx";
5
6
 
7
+
8
+
9
+ const theme = window.theme;
6
10
  export default function AppInvitation({
7
- // Redux State
8
11
  errors,
9
12
  user,
10
13
  invitationSuccess,
11
- // Actions
12
14
  confirmInvitation,
13
15
  getUserFromInvitation,
14
- // Configuration
16
+ theme,
15
17
  Layout,
16
18
  redirectPath = "/",
17
19
  loginPath = "/login",
18
20
  appRedirectPath = "/app",
19
21
  params: propParams = {},
22
+ goTo,
23
+ isMobile = false,
24
+ t,
20
25
  }) {
21
- const { t } = useTranslation();
22
- const routeParams = useParams();
23
- const { app, companyCode, userCode } = { ...routeParams, ...propParams };
24
- const [passwords] = Form.useForm();
26
+ const { app, companyCode, userCode } = propParams;
25
27
  const [checking, setChecking] = useState(true);
26
- const goTo = useNavigate();
27
- const [termsAgreed, setTermsAgreed] = useState(false);
28
28
  const [passwordReseted, setPasswordReseted] = useState(false);
29
29
 
30
30
  useEffect(() => {
@@ -46,36 +46,125 @@ export default function AppInvitation({
46
46
  localStorage.setItem('token', data.token);
47
47
  }
48
48
  message.success(t('Invitation accepted'));
49
- // Fix: ensure we don't rely on a variable from useParams that might not exist
50
- // Just use the configured redirectPath
51
- goTo(redirectPath);
49
+ if (goTo && typeof goTo === 'function') {
50
+ goTo(redirectPath);
51
+ } else {
52
+ window.location.href = redirectPath;
53
+ }
52
54
  },
53
55
  { companyCode, userCode }
54
56
  );
55
57
  }
56
58
  }, [invitationSuccess, user, confirmInvitation, goTo, redirectPath, companyCode, userCode, t]);
57
59
 
58
- const displayError = (name) => {
59
- return errors && errors[name] && errors[name].length > 0 && {
60
- help: errors[name][0],
61
- validateStatus: 'error',
62
- };
63
- };
60
+
61
+ useEffect(() => {
62
+
63
+ const isInInvitationFlow = checking ||
64
+ (invitationSuccess && user && user.inviteToken) ||
65
+ (invitationSuccess && user && !user.inviteToken);
66
+
67
+ if (!isInInvitationFlow) {
68
+ if (user) {
69
+ if (goTo && typeof goTo === 'function') {
70
+ goTo(appRedirectPath);
71
+ } else {
72
+ window.location.href = appRedirectPath;
73
+ }
74
+ } else {
75
+ if (goTo && typeof goTo === 'function') {
76
+ goTo(redirectPath);
77
+ } else {
78
+ window.location.href = redirectPath;
79
+ }
80
+ }
81
+ }
82
+ }, [user, goTo, appRedirectPath, redirectPath, checking, invitationSuccess]);
64
83
 
65
84
  const subTitle = !passwordReseted ? 'Set up your password and agree with out terms and conditions.' :
66
85
  isMobile ? 'Your account has been successfully set up. To log in use a desktop device.'
67
86
  : 'Your account has been successfully set up. Please click the button below to log in.';
68
87
  const title = passwordReseted ? 'Thank You!' : undefined;
69
88
 
89
+ const fields = [
90
+ {
91
+ name: 'email',
92
+ label: t("Email"),
93
+ type: 'input',
94
+ disabled: true,
95
+ },
96
+ {
97
+ name: 'password',
98
+ label: t("Password"),
99
+ type: 'password',
100
+ required: true,
101
+ rules: [{
102
+ required: true,
103
+ message: t("errors::password should not be empty")
104
+ }],
105
+ placeholder: t("Password"),
106
+ },
107
+ {
108
+ name: 'confirmPassword',
109
+ label: t("Confirm Password"),
110
+ type: 'password',
111
+ required: true,
112
+ dependencies: ['password'],
113
+ rules: [
114
+ {
115
+ required: true,
116
+ message: t("errors::password should not be empty"),
117
+ },
118
+ ({ getFieldValue }) => ({
119
+ validator(rule, value) {
120
+ if (!value || getFieldValue('password') === value) {
121
+ return Promise.resolve();
122
+ }
123
+ return Promise.reject(t('errors::passwordNotMatch'));
124
+ },
125
+ }),
126
+ ],
127
+ placeholder: t("Confirm Password"),
128
+ },
129
+ {
130
+ name: 'mailUpdates',
131
+ type: 'custom',
132
+ valuePropName: 'checked',
133
+ component: <Checkbox>{t("Sign up to receive updates")}</Checkbox>,
134
+ },
135
+ {
136
+ name: 'agreeTerms',
137
+ type: 'custom',
138
+ valuePropName: 'checked',
139
+ rules: [{
140
+ validator: (_, value) => value ? Promise.resolve() : Promise.reject(new Error(t('You must agree to the terms and conditions')))
141
+ }],
142
+ component: (
143
+ <Checkbox>
144
+ <p className="mb-0">
145
+ {t('Agree to the Terms of Use of this application and the Privacy Policy')}
146
+ </p>
147
+ </Checkbox>
148
+ ),
149
+ }
150
+ ];
151
+
152
+ const handleSubmit = (values) => {
153
+ const { password, mailUpdates } = values;
154
+ confirmInvitation(
155
+ { password, mailUpdates },
156
+ () => { },
157
+ { companyCode, userCode }
158
+ );
159
+ setPasswordReseted(true);
160
+ };
161
+
70
162
  if (checking && !invitationSuccess) {
71
163
  return <Loading />;
72
164
  }
73
165
 
74
- // If auto-confirming (inviteToken present), we might want to show loading or nothing until redirect
75
166
  if (invitationSuccess && user && user.inviteToken) {
76
- // The useEffect will handle the redirect/confirm.
77
- // We can show loading here too or just return null.
78
- // Original code: checks invitationSuccess && !user.inviteToken for form, else redirect.
167
+
79
168
  return <Loading />;
80
169
  }
81
170
 
@@ -88,6 +177,7 @@ export default function AppInvitation({
88
177
  <DafButton
89
178
  type="primary"
90
179
  className="normal-br"
180
+ style={theme || window.theme ? { backgroundColor: (theme || window.theme).colorPrimary, borderColor: (theme || window.theme).colorPrimary } : {}}
91
181
  onClick={() => {
92
182
  window.location.href = loginPath;
93
183
  }}
@@ -97,86 +187,21 @@ export default function AppInvitation({
97
187
  )}
98
188
  </div>
99
189
  ) : (
100
- <>
101
- <Form name="password" layout="vertical" form={passwords} >
102
- <Form.Item
103
- required
104
- name="password"
105
- {...displayError('password')}
106
- label={t("Password")}
107
- rules={[{
108
- required: true,
109
- message: t("errors::password should not be empty")
110
- }]}>
111
- <Input.Password size="large" placeholder={t("Password")} />
112
- </Form.Item>
113
- <Form.Item
114
- required
115
- name="confirmPassword"
116
- {...displayError('confirmPassword')}
117
- label={t("Confirm Password")}
118
- dependencies={['password']}
119
- rules={[
120
- {
121
- required: true,
122
- message: t("errors::password should not be empty"),
123
- },
124
- ({ getFieldValue }) => ({
125
- validator(rule, value) {
126
- if (!value || getFieldValue('password') === value) {
127
- return Promise.resolve();
128
- }
129
- return Promise.reject(t('errors::passwordNotMatch'));
130
- },
131
- }),
132
- ]}>
133
- <Input.Password size="large" placeholder={t("Confirm Password")} />
134
- </Form.Item>
135
- <Form.Item
136
- name="mailUpdates" valuePropName="checked" noStyle>
137
- <Checkbox>{t("Sign up to receive updates")}</Checkbox>
138
- </Form.Item>
139
- <Form.Item
140
- name="agreeTerms" valuePropName="checked" noStyle>
141
- <Checkbox
142
- checked={termsAgreed}
143
- onChange={(e) => setTermsAgreed(e.target.checked)}
144
- >
145
- <p className="mb-0">
146
- {t('Agree to the Terms of Use of this application and the Privacy Policy')}
147
- </p>
148
- </Checkbox>
149
- </Form.Item>
150
- </Form>
151
- <div className="buttons">
152
- <DafButton
153
- className="normal-br"
154
- type="primary"
155
- block
156
- size="large"
157
- disabled={!termsAgreed}
158
- onClick={() => {
159
- passwords.validateFields().then(data => {
160
- const { password, mailUpdates } = data;
161
- confirmInvitation(
162
- { password, mailUpdates },
163
- () => { },
164
- { companyCode, userCode }
165
- );
166
- setPasswordReseted(true);
167
- });
168
- }}
169
- >
170
- {t("Confirm")}
171
- </DafButton>
172
- </div>
173
- </>
190
+ <AuthForm
191
+ fields={fields}
192
+ onSubmit={handleSubmit}
193
+ submitText={t("Confirm")}
194
+ initialValues={{ email: user?.email }}
195
+ errors={errors}
196
+ t={t}
197
+ executeRecaptcha={() => Promise.resolve(true)}
198
+ theme={theme || window.theme}
199
+ />
174
200
  )}
175
201
  </>
176
202
  );
177
203
 
178
204
  if (Layout) {
179
- // Assuming Layout accepts these props as per Nashiriki AuthLayout
180
205
  return <Layout app={app} step={1} subTitle={subTitle} title={title}>{Content}</Layout>;
181
206
  }
182
207
 
@@ -189,5 +214,5 @@ export default function AppInvitation({
189
214
  );
190
215
  }
191
216
 
192
- return user ? <Navigate to={appRedirectPath} /> : <Navigate to={redirectPath} />;
217
+ return null;
193
218
  }
@@ -46,15 +46,20 @@ export function useAdminDashboard({ dashboardService, onError }) {
46
46
  }, [dashboardService, onError]);
47
47
 
48
48
  const fetchUserGrowth = useCallback(
49
- async (params) => {
49
+ async (activeFilter) => {
50
50
  if (!dashboardService?.getUserGrowth) {
51
51
  console.warn("dashboardService.getUserGrowth not provided");
52
52
  return;
53
53
  }
54
54
 
55
+ if (activeFilter === undefined || activeFilter === null) {
56
+ console.warn("activeFilter not provided to fetchUserGrowth");
57
+ return;
58
+ }
59
+
55
60
  setUserGrowthDataLoading(true);
56
61
  try {
57
- const response = await dashboardService.getUserGrowth(params);
62
+ const response = await dashboardService.getUserGrowth(activeFilter);
58
63
  setUserGrowthData(response || []);
59
64
  } catch (err) {
60
65
  if (onError) {
@@ -68,11 +73,9 @@ export function useAdminDashboard({ dashboardService, onError }) {
68
73
  },
69
74
  [dashboardService, onError]
70
75
  );
71
-
72
76
  useEffect(() => {
73
77
  fetchDashboardData();
74
78
  }, [fetchDashboardData]);
75
-
76
79
  return {
77
80
  data,
78
81
  loading,
@@ -17,6 +17,8 @@ class AdminService extends BaseService {
17
17
  }
18
18
 
19
19
 
20
+
21
+
20
22
  inviteCompanyAccount({ companyId, data }) {
21
23
  return this.apiPost({
22
24
  url: `/accounts/${companyId}/invite`,
@@ -24,6 +26,10 @@ class AdminService extends BaseService {
24
26
  })
25
27
  }
26
28
 
29
+
30
+
31
+
32
+
27
33
  inviteAccount(data) {
28
34
  return this.apiPost({
29
35
  url: `/accounts/inviteAccount`,
@@ -166,7 +172,7 @@ class AdminService extends BaseService {
166
172
  const type = subject === 'location' ? 'location' : 'stakeholder';
167
173
  return this.apiPut({
168
174
  url: `/management/subject/${type}/${id}`,
169
- data: filterCreateData(data),
175
+ data: data,
170
176
  });
171
177
  }
172
178
 
@@ -177,15 +183,20 @@ class AdminService extends BaseService {
177
183
  });
178
184
  }
179
185
 
180
- getUserGrowth(activeFilter) {
181
- return this.apiGet({
186
+ async getUserGrowth(activeFilter) {
187
+ const { data } = await this.apiGet({
182
188
  url: `/accounts/dashboard/user-growth`,
183
189
  isUserManager: true,
184
190
  params: { activeFilter },
185
191
  });
192
+ return data;
186
193
  }
187
194
 
188
-
195
+ removeUserFromAccount({ accountId, userId }) {
196
+ return this.apiDelete({
197
+ url: `/accounts/${accountId}/users/${userId}`,
198
+ })
199
+ }
189
200
  }
190
201
 
191
202
  export default createLazyService(AdminService);
@@ -9,13 +9,13 @@ class DashboardService extends BaseService {
9
9
  isApp: true,
10
10
  });
11
11
  }
12
-
13
- getUserGrowth(activeFilter) {
14
- return this.apiGet({
12
+ async getUserGrowth(activeFilter) {
13
+ const { data } = await this.apiGet({
15
14
  url: `/accounts/dashboard/user-growth`,
16
15
  isUserManager: true,
17
16
  params: { activeFilter },
18
17
  });
18
+ return data;
19
19
  }
20
20
 
21
21
  getAdminDashboard() {
@@ -63,29 +63,19 @@ export const getDefaultActiveFilters = (
63
63
  };
64
64
 
65
65
  const NEW_PAGINATION_APPS = ["nashiriki"];
66
-
67
66
  export const filterParams = (value, module) => {
68
67
  const { activeFilters, ...rest } = value;
69
68
 
70
- const {
71
- page = 1,
72
- pageSize = 20,
73
- sortDir,
74
- sortBy,
75
- search,
76
- searchParams,
77
- ...filters
78
- } = activeFilters || {};
69
+ const { page, pageSize, sortDir, sortBy, search, searchParams, ...filters } =
70
+ activeFilters || {};
79
71
 
80
72
  const params = {};
81
-
73
+
82
74
  params.pagination = JSON.stringify({
83
- page,
84
- pageSize,
75
+ [NEW_PAGINATION_APPS.includes(module) ? "skip" : "page"]: page,
76
+ [NEW_PAGINATION_APPS.includes(module) ? "take" : "pageSize"]: pageSize,
85
77
  });
86
78
 
87
- params.filters = JSON.stringify(filters);
88
-
89
79
  if (search && searchParams) {
90
80
  params.search = JSON.stringify({
91
81
  qs: search,
@@ -100,6 +90,14 @@ export const filterParams = (value, module) => {
100
90
  });
101
91
  }
102
92
 
93
+ if (Object.keys(filters).length) {
94
+ if (value.sourceId && value.sourceId === "overview") {
95
+ params.filters = JSON.stringify(filters);
96
+ } else {
97
+ params.filters = JSON.stringify({ ...filters, authorId: undefined });
98
+ }
99
+ }
100
+
103
101
  return { ...rest, ...params };
104
102
  };
105
103
 
@@ -1,4 +1,13 @@
1
1
  const en = {
2
+ "edit-account": "Edit Account",
3
+ "Are-you-sure-you-want-to-remove-the-user-from-this-account?": "Are you sure you want to remove the user from this account?",
4
+ "The-user-will-lose-access-to-the-application-and-to-all-data-created-for-this-account.": "The user will lose access to the application and to all data created for this account.",
5
+ "merge": "Merge",
6
+ "Are-you-sure-you-want-to-suspend-this-account?": "Are you sure you want to suspend this account?",
7
+ "Associated-users-will-lose-access-to-the-application-and-to-all-data-created-for-this-account.": "Associated users will lose access to the application and to all data created for this account.",
8
+ "current_subjects": "Current Subjects",
9
+ "merged_output": "Merged Output",
10
+ "merge-subjects": "Merge Subjects",
2
11
  "All Data": "All Data",
3
12
  "sbg-admin::remove-user-title":"Remove User Title",
4
13
  "sbg-admin::remove-user-body":"Remove User Body",
package/build/favicon.ico DELETED
Binary file
package/build/logo192.png DELETED
Binary file
package/build/logo512.png DELETED
Binary file
@@ -1,25 +0,0 @@
1
- {
2
- "short_name": "React App",
3
- "name": "Create React App Sample",
4
- "icons": [
5
- {
6
- "src": "favicon.ico",
7
- "sizes": "64x64 32x32 24x24 16x16",
8
- "type": "image/x-icon"
9
- },
10
- {
11
- "src": "logo192.png",
12
- "type": "image/png",
13
- "sizes": "192x192"
14
- },
15
- {
16
- "src": "logo512.png",
17
- "type": "image/png",
18
- "sizes": "512x512"
19
- }
20
- ],
21
- "start_url": ".",
22
- "display": "standalone",
23
- "theme_color": "#000000",
24
- "background_color": "#ffffff"
25
- }
package/build/robots.txt DELETED
@@ -1,3 +0,0 @@
1
- # https://www.robotstxt.org/robotstxt.html
2
- User-agent: *
3
- Disallow: