@arcblock/did-connect-service 4.1.12 → 4.1.14
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/dist/_generated/asset-bytes.js +1 -1
- package/dist/_generated/asset-manifest.js +4 -4
- package/dist/_generated/login-bundle-string.d.ts +1 -1
- package/dist/_generated/login-bundle-string.d.ts.map +1 -1
- package/dist/_generated/login-bundle-string.js +1 -1
- package/dist/_generated/login-bundle-string.js.map +1 -1
- package/dist/access/change-role.d.ts +48 -0
- package/dist/access/change-role.d.ts.map +1 -0
- package/dist/access/change-role.js +52 -0
- package/dist/access/change-role.js.map +1 -0
- package/dist/assets/{admin-core.cbbdbe6d.js → admin-core.a63bbc69.js} +16 -17
- package/dist/assets/{admin-extra.35b91f98.js → admin-extra.5b309e5e.js} +8 -4
- package/dist/assets/{admin.c26bb17a.css → admin.dfeedbe4.css} +10 -0
- package/dist/assets/login.76c483c2.js +720 -0
- package/dist/blocklet-service.d.ts.map +1 -1
- package/dist/blocklet-service.js +5 -1
- package/dist/blocklet-service.js.map +1 -1
- package/dist/handler-errors.d.ts +118 -0
- package/dist/handler-errors.d.ts.map +1 -0
- package/dist/handler-errors.js +38 -0
- package/dist/handler-errors.js.map +1 -0
- package/dist/handlers/access-key-connect-handler.d.ts +3 -0
- package/dist/handlers/access-key-connect-handler.d.ts.map +1 -1
- package/dist/handlers/access-key-connect-handler.js +7 -1
- package/dist/handlers/access-key-connect-handler.js.map +1 -1
- package/dist/handlers/admin-instance-handler.d.ts.map +1 -1
- package/dist/handlers/admin-instance-handler.js +2 -1
- package/dist/handlers/admin-instance-handler.js.map +1 -1
- package/dist/handlers/auth-handler.d.ts.map +1 -1
- package/dist/handlers/auth-handler.js +33 -9
- package/dist/handlers/auth-handler.js.map +1 -1
- package/dist/handlers/branding-handler.d.ts.map +1 -1
- package/dist/handlers/branding-handler.js +12 -9
- package/dist/handlers/branding-handler.js.map +1 -1
- package/dist/handlers/did-connect-handler.d.ts.map +1 -1
- package/dist/handlers/did-connect-handler.js +6 -5
- package/dist/handlers/did-connect-handler.js.map +1 -1
- package/dist/handlers/email-login-handler.d.ts +1 -1
- package/dist/handlers/email-login-handler.d.ts.map +1 -1
- package/dist/handlers/email-login-handler.js +63 -12
- package/dist/handlers/email-login-handler.js.map +1 -1
- package/dist/handlers/federation-admin-handler.d.ts +2 -0
- package/dist/handlers/federation-admin-handler.d.ts.map +1 -1
- package/dist/handlers/federation-admin-handler.js +105 -51
- package/dist/handlers/federation-admin-handler.js.map +1 -1
- package/dist/handlers/oauth-handler.d.ts.map +1 -1
- package/dist/handlers/oauth-handler.js +23 -12
- package/dist/handlers/oauth-handler.js.map +1 -1
- package/dist/handlers/passkey-handler.d.ts.map +1 -1
- package/dist/handlers/passkey-handler.js +5 -4
- package/dist/handlers/passkey-handler.js.map +1 -1
- package/dist/handlers/team-handler.d.ts.map +1 -1
- package/dist/handlers/team-handler.js +19 -19
- package/dist/handlers/team-handler.js.map +1 -1
- package/dist/identity/refresh-tokens.d.ts +21 -0
- package/dist/identity/refresh-tokens.d.ts.map +1 -0
- package/dist/identity/refresh-tokens.js +45 -0
- package/dist/identity/refresh-tokens.js.map +1 -0
- package/dist/identity/session-context.d.ts +12 -0
- package/dist/identity/session-context.d.ts.map +1 -1
- package/dist/identity/session-context.js +12 -0
- package/dist/identity/session-context.js.map +1 -1
- package/dist/identity/session-tokens.d.ts +15 -0
- package/dist/identity/session-tokens.d.ts.map +1 -0
- package/dist/identity/session-tokens.js +15 -0
- package/dist/identity/session-tokens.js.map +1 -0
- package/dist/locale.d.ts +1 -1
- package/dist/locale.d.ts.map +1 -1
- package/dist/og/templates.d.ts.map +1 -1
- package/dist/og/templates.js +33 -4
- package/dist/og/templates.js.map +1 -1
- package/dist/pages/admin/i18n.d.ts.map +1 -1
- package/dist/pages/admin/i18n.js +33 -9
- package/dist/pages/admin/i18n.js.map +1 -1
- package/dist/pages/admin/scripts/api-client.d.ts +1 -1
- package/dist/pages/admin/scripts/api-client.d.ts.map +1 -1
- package/dist/pages/admin/scripts/api-client.js +4 -4
- package/dist/pages/admin/scripts/utils.d.ts +1 -1
- package/dist/pages/admin/scripts/utils.d.ts.map +1 -1
- package/dist/pages/admin/scripts/utils.js +7 -8
- package/dist/pages/admin/scripts/utils.js.map +1 -1
- package/dist/pages/admin/styles.d.ts +1 -1
- package/dist/pages/admin/styles.d.ts.map +1 -1
- package/dist/pages/admin/styles.js +10 -0
- package/dist/pages/admin/styles.js.map +1 -1
- package/dist/pages/admin/tab-access-keys.d.ts +1 -1
- package/dist/pages/admin/tab-access-keys.d.ts.map +1 -1
- package/dist/pages/admin/tab-access-keys.js +4 -4
- package/dist/pages/admin/tab-invitations.d.ts +1 -1
- package/dist/pages/admin/tab-invitations.d.ts.map +1 -1
- package/dist/pages/admin/tab-invitations.js +2 -2
- package/dist/pages/admin/tab-members.d.ts +1 -1
- package/dist/pages/admin/tab-members.d.ts.map +1 -1
- package/dist/pages/admin/tab-members.js +7 -3
- package/dist/pages/admin/tab-members.js.map +1 -1
- package/dist/pages/admin/tab-profile-accounts.js +1 -1
- package/dist/pages/admin-instances-page.d.ts +1 -1
- package/dist/pages/admin-instances-page.d.ts.map +1 -1
- package/dist/pages/admin-instances-page.js +195 -65
- package/dist/pages/admin-instances-page.js.map +1 -1
- package/dist/pages/gen-access-key-page.d.ts +1 -1
- package/dist/pages/gen-access-key-page.d.ts.map +1 -1
- package/dist/pages/gen-access-key-page.js +163 -35
- package/dist/pages/gen-access-key-page.js.map +1 -1
- package/dist/pages/homepage.d.ts.map +1 -1
- package/dist/pages/homepage.js +0 -4
- package/dist/pages/homepage.js.map +1 -1
- package/dist/pages/invite-page.d.ts +1 -1
- package/dist/pages/invite-page.d.ts.map +1 -1
- package/dist/pages/invite-page.js +91 -21
- package/dist/pages/invite-page.js.map +1 -1
- package/dist/pages/oauth-callback-page.d.ts.map +1 -1
- package/dist/pages/oauth-callback-page.js +7 -3
- package/dist/pages/oauth-callback-page.js.map +1 -1
- package/dist/store/d1-store.d.ts +55 -1
- package/dist/store/d1-store.d.ts.map +1 -1
- package/dist/store/d1-store.js +162 -9
- package/dist/store/d1-store.js.map +1 -1
- package/migrations/0011_refresh_tokens.sql +23 -0
- package/package.json +7 -7
- package/dist/assets/admin-core.a13c2729.js +0 -1461
- package/dist/assets/admin-core.c0b5af61.js +0 -1393
- package/dist/assets/admin-core.e83fd379.js +0 -1397
- package/dist/assets/admin-extra.7ca9c16b.js +0 -2529
- package/dist/assets/admin-extra.841b2bbe.js +0 -2530
- package/dist/assets/admin-extra.afcb3651.js +0 -2528
- package/dist/assets/login.d3f05790.js +0 -720
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const ROLE_LEVEL = { owner: 3, admin: 2, member: 1, guest: 0 };
|
|
2
|
+
const ASSIGNABLE_ROLES = new Set(["admin", "member", "guest"]);
|
|
3
|
+
export async function changeMembershipRole(params) {
|
|
4
|
+
const { store, instanceDid, callerDid, callerRole, targetDid, newRole, ip } = params;
|
|
5
|
+
if (!newRole || !ASSIGNABLE_ROLES.has(newRole)) {
|
|
6
|
+
return {
|
|
7
|
+
ok: false,
|
|
8
|
+
status: 400,
|
|
9
|
+
code: "VALIDATION_ERROR",
|
|
10
|
+
message: "Invalid role. Must be 'admin', 'member', or 'guest'",
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (targetDid === callerDid) {
|
|
14
|
+
return { ok: false, status: 409, code: "CONFLICT", message: "Cannot change your own role" };
|
|
15
|
+
}
|
|
16
|
+
// Only owner can assign admin role
|
|
17
|
+
if (newRole === "admin" && callerRole !== "owner") {
|
|
18
|
+
return {
|
|
19
|
+
ok: false,
|
|
20
|
+
status: 403,
|
|
21
|
+
code: "FORBIDDEN",
|
|
22
|
+
message: "Only the owner can assign admin role",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const membership = await store.getMembership(targetDid, instanceDid);
|
|
26
|
+
if (!membership) {
|
|
27
|
+
return { ok: false, status: 404, code: "NOT_FOUND", message: "Member not found" };
|
|
28
|
+
}
|
|
29
|
+
const oldRole = membership.role;
|
|
30
|
+
const callerLevel = ROLE_LEVEL[callerRole] ?? 0;
|
|
31
|
+
const targetLevel = ROLE_LEVEL[oldRole] ?? 0;
|
|
32
|
+
// Cannot modify someone at same or higher level (admin can't change admin/owner)
|
|
33
|
+
if (targetLevel >= callerLevel) {
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
status: 403,
|
|
37
|
+
code: "FORBIDDEN",
|
|
38
|
+
message: "Cannot change the role of a member with equal or higher privileges",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
await store.updateMembershipRole(targetDid, instanceDid, newRole, callerDid);
|
|
42
|
+
await store.createAuditLog({
|
|
43
|
+
action: "user.role_change",
|
|
44
|
+
operatorDid: callerDid,
|
|
45
|
+
targetDid,
|
|
46
|
+
metadata: { oldRole, newRole },
|
|
47
|
+
ip,
|
|
48
|
+
instanceDid,
|
|
49
|
+
});
|
|
50
|
+
return { ok: true, oldRole };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=change-role.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-role.js","sourceRoot":"","sources":["../../src/access/change-role.ts"],"names":[],"mappings":"AAwBA,MAAM,UAAU,GAA2B,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AACvF,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAqB/D,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAkC;IAElC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC;IAErF,IAAI,CAAC,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,qDAAqD;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC;IAC9F,CAAC;IAED,mCAAmC;IACnC,IAAI,OAAO,KAAK,OAAO,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAClD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,sCAAsC;SAChD,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACrE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IACpF,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC;IAChC,MAAM,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,iFAAiF;IACjF,IAAI,WAAW,IAAI,WAAW,EAAE,CAAC;QAC/B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,oEAAoE;SAC9E,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,CAAC,oBAAoB,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC7E,MAAM,KAAK,CAAC,cAAc,CAAC;QACzB,MAAM,EAAE,kBAAkB;QAC1B,WAAW,EAAE,SAAS;QACtB,SAAS;QACT,QAAQ,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE;QAC9B,EAAE;QACF,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -35,12 +35,11 @@ function relativeTime(iso) {
|
|
|
35
35
|
var h = Math.floor(m / 60);
|
|
36
36
|
var d = Math.floor(h / 24);
|
|
37
37
|
var label;
|
|
38
|
-
if (d > 0) label =
|
|
39
|
-
else if (h > 0) label =
|
|
40
|
-
else if (m > 0) label = m
|
|
41
|
-
else
|
|
42
|
-
|
|
43
|
-
return future ? "in " + label : label + " ago";
|
|
38
|
+
if (d > 0) label = __t("time.dh", { d: d, h: (h % 24) });
|
|
39
|
+
else if (h > 0) label = __t("time.hm", { h: h, m: (m % 60) });
|
|
40
|
+
else if (m > 0) label = __t("time.min", { m: m });
|
|
41
|
+
else return __t("time.justNow");
|
|
42
|
+
return future ? __t("time.in", { label: label }) : __t("time.ago", { label: label });
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
function absoluteTime(iso) {
|
|
@@ -53,7 +52,7 @@ function absoluteTime(iso) {
|
|
|
53
52
|
function copyToClipboard(text) {
|
|
54
53
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
55
54
|
navigator.clipboard.writeText(text).then(function() {
|
|
56
|
-
showToast("
|
|
55
|
+
showToast(__t("common.copied"), "success");
|
|
57
56
|
}).catch(function() {
|
|
58
57
|
fallbackCopy(text);
|
|
59
58
|
});
|
|
@@ -69,7 +68,7 @@ function fallbackCopy(text) {
|
|
|
69
68
|
input.select();
|
|
70
69
|
document.execCommand("copy");
|
|
71
70
|
input.remove();
|
|
72
|
-
showToast("
|
|
71
|
+
showToast(__t("common.copied"), "success");
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
// Delegate to the canonical implementation from @arcblock/did-connect-core
|
|
@@ -154,19 +153,19 @@ async function api(method, path, body, callOpts) {
|
|
|
154
153
|
|
|
155
154
|
if (res.status === 401) {
|
|
156
155
|
location.href = "/.well-known/service/api/did/logout";
|
|
157
|
-
return { ok: false, error: "
|
|
156
|
+
return { ok: false, error: __t("common.sessionExpired"), code: "UNAUTHENTICATED" };
|
|
158
157
|
}
|
|
159
158
|
if (res.status === 403 && data.code === "BLOCKED") {
|
|
160
159
|
location.href = "/.well-known/service/api/did/logout";
|
|
161
|
-
return { ok: false, error: "
|
|
160
|
+
return { ok: false, error: __t("common.accountBlocked"), code: "BLOCKED" };
|
|
162
161
|
}
|
|
163
162
|
if (!res.ok) {
|
|
164
|
-
if (!callOpts.silent) showToast(data.error || "
|
|
163
|
+
if (!callOpts.silent) showToast(data.error || __t("common.requestFailed"), "error");
|
|
165
164
|
return { ok: false, error: data.error, code: data.code };
|
|
166
165
|
}
|
|
167
166
|
return data;
|
|
168
167
|
} catch (err) {
|
|
169
|
-
if (!callOpts.silent) showToast("
|
|
168
|
+
if (!callOpts.silent) showToast(__t("common.networkError"), "error");
|
|
170
169
|
return { ok: false, error: err.message, code: "NETWORK_ERROR" };
|
|
171
170
|
}
|
|
172
171
|
}
|
|
@@ -848,7 +847,7 @@ function connectOAuth(provider) {
|
|
|
848
847
|
var left = (screen.width - w) / 2, top = (screen.height - h) / 2;
|
|
849
848
|
var popup = window.open(url, "oauth_bind", "width=" + w + ",height=" + h + ",left=" + left + ",top=" + top);
|
|
850
849
|
if (!popup) {
|
|
851
|
-
showToast("
|
|
850
|
+
showToast(__t("common.popupBlocked"), "error");
|
|
852
851
|
return;
|
|
853
852
|
}
|
|
854
853
|
|
|
@@ -1233,10 +1232,10 @@ function renderAccessKeys(keys, paging) {
|
|
|
1233
1232
|
|
|
1234
1233
|
function openCreateAkDialog() {
|
|
1235
1234
|
var callerRole = __caller.role;
|
|
1236
|
-
var roleOptions = '<option value="guest">
|
|
1237
|
-
if (callerRole === "member" || callerRole === "admin" || callerRole === "owner") roleOptions += '<option value="member"' + (callerRole === "member" ? ' selected' : '') + '>
|
|
1238
|
-
if (callerRole === "admin" || callerRole === "owner") roleOptions += '<option value="admin"' + (callerRole === "admin" ? ' selected' : '') + '>
|
|
1239
|
-
if (callerRole === "owner") roleOptions += '<option value="owner">
|
|
1235
|
+
var roleOptions = '<option value="guest">' + __t("common.guest") + '</option>';
|
|
1236
|
+
if (callerRole === "member" || callerRole === "admin" || callerRole === "owner") roleOptions += '<option value="member"' + (callerRole === "member" ? ' selected' : '') + '>' + __t("common.member") + '</option>';
|
|
1237
|
+
if (callerRole === "admin" || callerRole === "owner") roleOptions += '<option value="admin"' + (callerRole === "admin" ? ' selected' : '') + '>' + __t("common.admin") + '</option>';
|
|
1238
|
+
if (callerRole === "owner") roleOptions += '<option value="owner">' + __t("common.owner") + '</option>';
|
|
1240
1239
|
|
|
1241
1240
|
var expiryOptions = '<option value="">' + __t("accessKeys.expirations.never") + '</option><option value="7d">' + __t("accessKeys.expirations.days7") + '</option><option value="30d">' + __t("accessKeys.expirations.days30") + '</option><option value="90d">' + __t("accessKeys.expirations.days90") + '</option><option value="custom">' + __t("accessKeys.expirations.custom") + '</option>';
|
|
1242
1241
|
|
|
@@ -158,8 +158,12 @@ async function loadMembers(page) {
|
|
|
158
158
|
|
|
159
159
|
function renderMembersTable(users, paging) {
|
|
160
160
|
var wrap = document.getElementById("members-table-wrap");
|
|
161
|
+
// Aggregated (cross-instance "All Instances") view can't tell which instance
|
|
162
|
+
// a role change should apply to, so per-row actions are disabled there — see
|
|
163
|
+
// canOperate below. Surface why, instead of silently hiding the buttons.
|
|
164
|
+
var aggregatedHint = __membersAggregated ? '<p class="text-muted" style="font-size:13px;margin-bottom:12px;">' + __t("members.aggregatedHint") + '</p>' : '';
|
|
161
165
|
if (!users || users.length === 0) {
|
|
162
|
-
wrap.innerHTML = '<div class="empty-state"><div class="empty-state-icon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg></div><div class="empty-state-title">' + __t("members.noMembers") + '</div><div class="empty-state-desc">' + __t("members.noMembersHint") + '</div></div>';
|
|
166
|
+
wrap.innerHTML = aggregatedHint + '<div class="empty-state"><div class="empty-state-icon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg></div><div class="empty-state-title">' + __t("members.noMembers") + '</div><div class="empty-state-desc">' + __t("members.noMembersHint") + '</div></div>';
|
|
163
167
|
document.getElementById("members-pagination").innerHTML = "";
|
|
164
168
|
return;
|
|
165
169
|
}
|
|
@@ -167,7 +171,7 @@ function renderMembersTable(users, paging) {
|
|
|
167
171
|
var instanceSel = document.getElementById("members-instance-filter");
|
|
168
172
|
var instanceVisible = instanceSel && instanceSel.style.display !== 'none';
|
|
169
173
|
var showInstance = instanceVisible && instanceSel.value === "all";
|
|
170
|
-
var html = '<table class="table"><thead><tr>';
|
|
174
|
+
var html = aggregatedHint + '<table class="table"><thead><tr>';
|
|
171
175
|
html += sortableTh("name", __t("members.col.member"));
|
|
172
176
|
html += sortableTh("role", __t("members.col.role"));
|
|
173
177
|
if (showInstance) html += '<th>' + __t("members.col.instance") + '</th>';
|
|
@@ -521,7 +525,7 @@ function renderInvitationsTable(invitations, paging) {
|
|
|
521
525
|
var uses = inv.useCount + " / " + inv.maxUses;
|
|
522
526
|
if (inv.useCount >= inv.maxUses) uses += ' <span class="badge badge-blocked">' + __t("invitations.closed") + '</span>';
|
|
523
527
|
var expired = new Date(inv.expireAt) < new Date();
|
|
524
|
-
var expireText = expired ? '<span class="badge badge-expired">expired</span>' : '<span class="cell-date">' + escapeHtml(relativeTime(inv.expireAt)) + '</span>';
|
|
528
|
+
var expireText = expired ? '<span class="badge badge-expired">' + __t("common.expired") + '</span>' : '<span class="cell-date">' + escapeHtml(relativeTime(inv.expireAt)) + '</span>';
|
|
525
529
|
var isActive = !expired && inv.status !== "closed" && inv.useCount < inv.maxUses;
|
|
526
530
|
var inviter = inv.inviterName ? escapeHtml(inv.inviterName) : '<span class="text-muted">—</span>';
|
|
527
531
|
|
|
@@ -580,7 +584,7 @@ async function deleteInvitation(id) {
|
|
|
580
584
|
function initInviteRoleOptions() {
|
|
581
585
|
var select = document.getElementById("invite-role");
|
|
582
586
|
if (__caller.role === "owner") {
|
|
583
|
-
select.innerHTML = '<option value="guest">
|
|
587
|
+
select.innerHTML = '<option value="guest">' + __t("common.guest") + '</option><option value="member">' + __t("common.member") + '</option><option value="admin">' + __t("common.admin") + '</option>';
|
|
584
588
|
}
|
|
585
589
|
}
|
|
586
590
|
|
|
@@ -1157,11 +1157,20 @@
|
|
|
1157
1157
|
max-width: 520px;
|
|
1158
1158
|
width: 90%;
|
|
1159
1159
|
box-shadow: var(--shadow-lg);
|
|
1160
|
+
max-height: calc(100vh - 32px);
|
|
1161
|
+
max-height: calc(100dvh - 32px);
|
|
1160
1162
|
overflow: hidden;
|
|
1161
1163
|
animation: modalIn 0.2s ease;
|
|
1162
1164
|
}
|
|
1165
|
+
dialog[open] {
|
|
1166
|
+
display: flex;
|
|
1167
|
+
flex-direction: column;
|
|
1168
|
+
}
|
|
1163
1169
|
dialog::backdrop { background: rgba(0,0,0,0.7); }
|
|
1164
1170
|
.dialog-content {
|
|
1171
|
+
min-height: 0;
|
|
1172
|
+
overflow-y: auto;
|
|
1173
|
+
overscroll-behavior: contain;
|
|
1165
1174
|
padding: 24px;
|
|
1166
1175
|
}
|
|
1167
1176
|
.dialog-content h3 {
|
|
@@ -1179,6 +1188,7 @@
|
|
|
1179
1188
|
}
|
|
1180
1189
|
.dialog-actions {
|
|
1181
1190
|
display: flex;
|
|
1191
|
+
flex: 0 0 auto;
|
|
1182
1192
|
justify-content: flex-end;
|
|
1183
1193
|
gap: 8px;
|
|
1184
1194
|
padding: 16px 24px;
|