@7365admin1/layer-common 3.2.2-staging.121 → 3.2.2-staging.123
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/assets/css/primitives.css +92 -0
- package/assets/css/tokens.css +16 -0
- package/components/AppButton.vue +10 -1
- package/components/StatusChip.vue +63 -0
- package/components/VisitorManagement.vue +20 -13
- package/nuxt.config.ts +6 -1
- package/package.json +22 -1
- package/plugins/vuetify.ts +37 -1
- package/utils/materialSymbols.ts +363 -0
- package/.changeset/README.md +0 -8
- package/.changeset/camera-wall-gated-endpoint.md +0 -47
- package/.changeset/camera-wall-plain-english.md +0 -60
- package/.changeset/camera-wall-selection-and-guidance.md +0 -65
- package/.changeset/config.json +0 -11
- package/.changeset/dark-primary-contrast.md +0 -39
- package/.changeset/dashboard-dark-theme-contrast.md +0 -15
- package/.changeset/notification-preferences.md +0 -17
- package/.changeset/pm-sidebar-grouping-and-list-scaffold.md +0 -27
- package/.changeset/service-provider-invitation-actions.md +0 -28
- package/.editorconfig +0 -12
- package/.github/workflows/main.yml +0 -17
- package/.github/workflows/publish-staging.yml +0 -47
- package/.github/workflows/publish.yml +0 -39
- package/PUBLISHING.md +0 -269
- package/components/ScheduleTaskAreaFormDialog.vue +0 -141
- package/components/ScheduleTaskAreaUpdateMoreAction.vue +0 -104
- package/components/TableWithButton.vue +0 -94
- package/test/visitor-socket.test.mjs +0 -36
- package/tools/render-harness/README.md +0 -87
- package/tools/render-harness/baselines.json +0 -117
- package/tools/render-harness/harness-init.ps1 +0 -127
- package/tools/render-harness/probe.mjs +0 -229
- package/tools/render-harness/render-check.mjs +0 -306
- package/tools/render-harness/render-check.selftest.mjs +0 -129
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
"@7365admin1/layer-common": patch
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
Group the sidebar's sections and give the list screens the design's page
|
|
6
|
-
scaffold.
|
|
7
|
-
|
|
8
|
-
- `withSections()` walked each application's menu in the order it was given and
|
|
9
|
-
printed a heading whenever the section changed, so Property Management drew
|
|
10
|
-
SERVICE DESK, PROPERTY and SECURITY OPERATIONS **twice each**. Items are now
|
|
11
|
-
grouped under one heading per section, in the order the design lists them,
|
|
12
|
-
with the application's own order kept inside each section. No menu item is
|
|
13
|
-
added, hidden, renamed, re-routed or re-gated.
|
|
14
|
-
- `ServiceProviderMain`, `FeedbackMain`, `InvitationMain` and `WorkOrder/Main`
|
|
15
|
-
had no page title, put their primary action top-left, floated the search
|
|
16
|
-
outside the card, and stacked the refresh/pager on a bar above the tabs. They
|
|
17
|
-
now use `PageHeader` / `AppCard` / `CardToolbar` / `AppButton` / `AppField`:
|
|
18
|
-
a 22px title with the action on the right, then one in-card row with the tabs
|
|
19
|
-
on the left and search, count and pager on the right.
|
|
20
|
-
- `SwitchContext` and the rail's application name print in full instead of
|
|
21
|
-
truncating to "Seventh Cond…" / "Property Managem…".
|
|
22
|
-
- The security dashboard's `ACTIVE PATROL` / `STAFF STATUS` panel headings are
|
|
23
|
-
written the way the design writes them, matching their sibling panels.
|
|
24
|
-
|
|
25
|
-
Placement and wording only: the same buttons open the same dialogs under the
|
|
26
|
-
same permissions, the same tabs load the same lists, and the tables, columns,
|
|
27
|
-
filters and row menus are untouched.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
"@7365admin1/layer-common": minor
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
Make the Pending tab's invitation actions reachable, and say which state an invitation is really in
|
|
6
|
-
|
|
7
|
-
The row menu in the service-provider list was drawn only for provider rows, so a
|
|
8
|
-
pending invitation offered no actions at all — including the cancel that was
|
|
9
|
-
already wired up behind it. Invitation rows now carry Cancel, Resend and Delete,
|
|
10
|
-
each behind a confirmation that names the company and the site, and Resend is
|
|
11
|
-
disabled with the reason while Seven365 has not approved the invitation yet.
|
|
12
|
-
|
|
13
|
-
Every invitation also used to read "Pending" whatever had happened to it. Rows
|
|
14
|
-
now show the state they are actually in — Waiting for Seven365, Waiting for the
|
|
15
|
-
provider, Not approved, Declined, Cancelled, Expired — in those words, with
|
|
16
|
-
Seven365's reason shown underneath a rejected one.
|
|
17
|
-
|
|
18
|
-
Also here: a new ServiceProviderInvitationPrompt, which is how an existing
|
|
19
|
-
provider answers an invitation from inside the app they already use, with no
|
|
20
|
-
sign-up and no one-time code.
|
|
21
|
-
|
|
22
|
-
Three contrast fixes found while rendering these screens: the list's tab strip
|
|
23
|
-
was a hardcoded light grey that turned into a white slab in dark mode and took
|
|
24
|
-
the tab labels with it; the service type column read the raw stored slug
|
|
25
|
-
("security_agency") instead of "Security"; and `on-warning`, `on-info` and
|
|
26
|
-
dark's `on-error` are now set explicitly, because Vuetify derives white for them
|
|
27
|
-
and that measures 2.37:1, 3.12:1 and 3.60:1 on those fills — every filled
|
|
28
|
-
warning, info and error chip, alert and button in the product.
|
package/.editorconfig
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- "**"
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
build:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
steps:
|
|
11
|
-
- uses: actions/checkout@v4
|
|
12
|
-
- uses: actions/setup-node@v4
|
|
13
|
-
with:
|
|
14
|
-
node-version: 20.x
|
|
15
|
-
cache: "yarn"
|
|
16
|
-
- run: yarn install --frozen-lockfile && yarn dev:prepare
|
|
17
|
-
- run: yarn build
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
name: Publish Staging
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- staging
|
|
6
|
-
|
|
7
|
-
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
publish:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
steps:
|
|
13
|
-
- uses: actions/checkout@v4
|
|
14
|
-
|
|
15
|
-
- uses: actions/setup-node@v4
|
|
16
|
-
with:
|
|
17
|
-
node-version: 20.x
|
|
18
|
-
cache: "yarn"
|
|
19
|
-
cache-dependency-path: yarn.lock
|
|
20
|
-
|
|
21
|
-
- run: yarn install --immutable
|
|
22
|
-
|
|
23
|
-
- run: yarn build
|
|
24
|
-
|
|
25
|
-
- name: Create .npmrc for publishing
|
|
26
|
-
run: |
|
|
27
|
-
echo '//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}' > ~/.npmrc
|
|
28
|
-
|
|
29
|
-
- name: Set staging prerelease version
|
|
30
|
-
run: |
|
|
31
|
-
BASE=$(node -p "const [x,y,z]=require('./package.json').version.split('-')[0].split('.'); [x,y,+z+1].join('.')")
|
|
32
|
-
npm version "$BASE-staging.${{ github.run_number }}" --no-git-tag-version
|
|
33
|
-
node -p "'Publishing ' + require('./package.json').version"
|
|
34
|
-
|
|
35
|
-
- name: Publish to npm with staging tag
|
|
36
|
-
run: npm publish --tag staging --registry https://registry.npmjs.org
|
|
37
|
-
|
|
38
|
-
- name: Notify Discord on failure
|
|
39
|
-
if: failure()
|
|
40
|
-
env:
|
|
41
|
-
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
42
|
-
run: |
|
|
43
|
-
MESSAGE="@everyone :rotating_light: **Publish Staging** failed in \`${{ github.repository }}\` (\`${{ github.workflow }}\`)
|
|
44
|
-
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
45
|
-
curl -s -X POST -H "Content-Type: application/json" \
|
|
46
|
-
-d "$(jq -n --arg content "$MESSAGE" '{content: $content}')" \
|
|
47
|
-
"$DISCORD_WEBHOOK_URL"
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
name: Publish
|
|
2
|
-
on:
|
|
3
|
-
workflow_run:
|
|
4
|
-
workflows: [CI]
|
|
5
|
-
branches: [main]
|
|
6
|
-
types: [completed]
|
|
7
|
-
|
|
8
|
-
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
9
|
-
|
|
10
|
-
permissions:
|
|
11
|
-
contents: write
|
|
12
|
-
pull-requests: write
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
publish:
|
|
16
|
-
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
17
|
-
runs-on: ubuntu-latest
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v4
|
|
20
|
-
|
|
21
|
-
- uses: actions/setup-node@v4
|
|
22
|
-
with:
|
|
23
|
-
node-version: 20.x
|
|
24
|
-
cache: "yarn" # Use yarn for caching
|
|
25
|
-
cache-dependency-path: yarn.lock # Cache Yarn lockfile
|
|
26
|
-
|
|
27
|
-
- run: yarn install --immutable # Install dependencies with immutable lockfile
|
|
28
|
-
|
|
29
|
-
- name: Create .npmrc for publishing
|
|
30
|
-
run: |
|
|
31
|
-
echo '//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}' > ~/.npmrc
|
|
32
|
-
|
|
33
|
-
- name: Create Release Pull Request or Publish
|
|
34
|
-
id: changesets
|
|
35
|
-
uses: changesets/action@v1
|
|
36
|
-
with:
|
|
37
|
-
publish: yarn release # Use yarn for publishing
|
|
38
|
-
env:
|
|
39
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/PUBLISHING.md
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
# Publishing Guide
|
|
2
|
-
|
|
3
|
-
This document explains how to publish new versions of `@7365admin1/layer-common` to npm using changesets and GitHub Actions.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The package uses an automated publishing workflow powered by [Changesets](https://github.com/changesets/changesets) and GitHub Actions. When you make changes and create a changeset, the workflow automatically:
|
|
8
|
-
|
|
9
|
-
1. Creates a "Version Packages" PR with version bumps
|
|
10
|
-
2. Publishes to npm when you merge that PR
|
|
11
|
-
|
|
12
|
-
## Quick Start
|
|
13
|
-
|
|
14
|
-
### 1. Make Your Changes
|
|
15
|
-
|
|
16
|
-
Make your code changes in a new branch as usual.
|
|
17
|
-
|
|
18
|
-
### 2. Create a Changeset
|
|
19
|
-
|
|
20
|
-
Before committing, create a changeset to document your changes:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npx changeset
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
You'll be prompted to:
|
|
27
|
-
- Select the type of change: `patch`, `minor`, or `major`
|
|
28
|
-
- Write a summary of your changes
|
|
29
|
-
|
|
30
|
-
This creates a `.changeset/[random-name].md` file.
|
|
31
|
-
|
|
32
|
-
### 3. Commit and Push
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
git add .
|
|
36
|
-
git commit -m "feat: your feature description"
|
|
37
|
-
git push
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### 4. Create a Pull Request
|
|
41
|
-
|
|
42
|
-
Create a PR to merge your branch into `main`.
|
|
43
|
-
|
|
44
|
-
### 5. Merge Your PR
|
|
45
|
-
|
|
46
|
-
Once approved, merge your PR to `main`.
|
|
47
|
-
|
|
48
|
-
### 6. Bot Creates Version PR (Automatic)
|
|
49
|
-
|
|
50
|
-
After merging, the GitHub Actions bot will automatically:
|
|
51
|
-
- Detect your changeset
|
|
52
|
-
- Create a new PR titled "Version Packages"
|
|
53
|
-
- Update `package.json` with the new version
|
|
54
|
-
- Update `CHANGELOG.md`
|
|
55
|
-
- Remove the changeset file
|
|
56
|
-
|
|
57
|
-
### 7. Merge the Version PR
|
|
58
|
-
|
|
59
|
-
Review and merge the "Version Packages" PR. This will:
|
|
60
|
-
- Bump the version in `package.json`
|
|
61
|
-
- Automatically publish to npm 🚀
|
|
62
|
-
|
|
63
|
-
## Workflow Diagram
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
You: Make changes + create changeset
|
|
67
|
-
↓
|
|
68
|
-
You: Push and create PR
|
|
69
|
-
↓
|
|
70
|
-
You: Merge PR to main
|
|
71
|
-
↓
|
|
72
|
-
Bot: Creates "Version Packages" PR (automatic)
|
|
73
|
-
↓
|
|
74
|
-
You: Merge "Version Packages" PR
|
|
75
|
-
↓
|
|
76
|
-
Bot: Publishes to npm (automatic)
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Version Types
|
|
80
|
-
|
|
81
|
-
When creating a changeset, you'll choose a version bump type:
|
|
82
|
-
|
|
83
|
-
- **patch** (1.8.0 → 1.8.1): Bug fixes, minor changes
|
|
84
|
-
- **minor** (1.8.0 → 1.9.0): New features, backward compatible
|
|
85
|
-
- **major** (1.8.0 → 2.0.0): Breaking changes
|
|
86
|
-
|
|
87
|
-
## Common Commands
|
|
88
|
-
|
|
89
|
-
### Create a Changeset
|
|
90
|
-
```bash
|
|
91
|
-
npx changeset
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Create an Empty Changeset
|
|
95
|
-
```bash
|
|
96
|
-
npx changeset add --empty
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Check Which Packages Would Be Published
|
|
100
|
-
```bash
|
|
101
|
-
npx changeset status
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Manually Version (Local Testing Only)
|
|
105
|
-
```bash
|
|
106
|
-
npx changeset version
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Manually Publish (Not Recommended)
|
|
110
|
-
```bash
|
|
111
|
-
yarn run release
|
|
112
|
-
```
|
|
113
|
-
> ⚠️ **Note**: Manual publishing requires 2FA or an automation token. Use GitHub Actions instead.
|
|
114
|
-
|
|
115
|
-
## GitHub Setup
|
|
116
|
-
|
|
117
|
-
### Required Secrets
|
|
118
|
-
|
|
119
|
-
The repository needs the following GitHub secret:
|
|
120
|
-
|
|
121
|
-
**`NPM_TOKEN`**
|
|
122
|
-
- Location: Settings → Secrets and variables → Actions
|
|
123
|
-
- Type: Granular Access Token (Automation)
|
|
124
|
-
- Value: Your npm automation token
|
|
125
|
-
- Permissions: Read and Write for packages, with 2FA bypass enabled
|
|
126
|
-
|
|
127
|
-
### Workflow Files
|
|
128
|
-
|
|
129
|
-
- `.github/workflows/main.yml` - CI workflow (builds and tests)
|
|
130
|
-
- `.github/workflows/publish.yml` - Publish workflow (creates PRs and publishes)
|
|
131
|
-
|
|
132
|
-
## Configuration Files
|
|
133
|
-
|
|
134
|
-
### `.changeset/config.json`
|
|
135
|
-
|
|
136
|
-
```json
|
|
137
|
-
{
|
|
138
|
-
"$schema": "https://unpkg.com/@changesets/config@3.0.5/schema.json",
|
|
139
|
-
"changelog": "@changesets/cli/changelog",
|
|
140
|
-
"commit": false,
|
|
141
|
-
"access": "public",
|
|
142
|
-
"baseBranch": "main"
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Key settings:
|
|
147
|
-
- `"access": "public"` - Package is published as public (free)
|
|
148
|
-
- `"baseBranch": "main"` - PRs are created against main
|
|
149
|
-
|
|
150
|
-
### `package.json`
|
|
151
|
-
|
|
152
|
-
```json
|
|
153
|
-
{
|
|
154
|
-
"name": "@7365admin1/layer-common",
|
|
155
|
-
"version": "1.8.1",
|
|
156
|
-
"author": "7365admin1",
|
|
157
|
-
"publishConfig": {
|
|
158
|
-
"access": "public"
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Key settings:
|
|
164
|
-
- `"publishConfig.access": "public"` - Ensures scoped package is public
|
|
165
|
-
|
|
166
|
-
## Troubleshooting
|
|
167
|
-
|
|
168
|
-
### "Version didn't update on npm"
|
|
169
|
-
|
|
170
|
-
**Solution**: Make sure you merged the bot's "Version Packages" PR. The version only publishes after merging that PR, not your original PR.
|
|
171
|
-
|
|
172
|
-
### "No Version Packages PR was created"
|
|
173
|
-
|
|
174
|
-
**Possible causes**:
|
|
175
|
-
1. No changeset file was committed
|
|
176
|
-
2. CI workflow failed
|
|
177
|
-
3. Check GitHub Actions logs for errors
|
|
178
|
-
|
|
179
|
-
**Solution**: Run `npx changeset status` locally to verify changesets exist.
|
|
180
|
-
|
|
181
|
-
### "402 Payment Required" Error
|
|
182
|
-
|
|
183
|
-
**Cause**: Scoped packages (`@username/package`) are private by default and require payment.
|
|
184
|
-
|
|
185
|
-
**Solution**: Ensure `publishConfig.access` is set to `"public"` in `package.json`.
|
|
186
|
-
|
|
187
|
-
### "403 Forbidden" or "401 Unauthorized"
|
|
188
|
-
|
|
189
|
-
**Cause**: Invalid or expired npm token.
|
|
190
|
-
|
|
191
|
-
**Solution**:
|
|
192
|
-
1. Generate a new Granular Access Token (Automation type) on npmjs.com
|
|
193
|
-
2. Update the `NPM_TOKEN` secret in GitHub
|
|
194
|
-
3. Ensure token has "Bypass 2FA" enabled
|
|
195
|
-
|
|
196
|
-
### "Changeset not found" Error
|
|
197
|
-
|
|
198
|
-
**Cause**: Changeset file wasn't committed or was deleted.
|
|
199
|
-
|
|
200
|
-
**Solution**: Run `npx changeset` again and commit the generated `.changeset/*.md` file.
|
|
201
|
-
|
|
202
|
-
## Best Practices
|
|
203
|
-
|
|
204
|
-
### 1. Always Create Changesets
|
|
205
|
-
|
|
206
|
-
Never merge code changes without a changeset. It ensures:
|
|
207
|
-
- Version tracking
|
|
208
|
-
- Changelog updates
|
|
209
|
-
- Proper npm publishing
|
|
210
|
-
|
|
211
|
-
### 2. Write Clear Changeset Summaries
|
|
212
|
-
|
|
213
|
-
Your changeset summary becomes the changelog entry. Make it:
|
|
214
|
-
- Clear and concise
|
|
215
|
-
- User-focused (what changed, not how)
|
|
216
|
-
- Action-oriented (e.g., "Added X feature" not "Adding X feature")
|
|
217
|
-
|
|
218
|
-
### 3. Don't Skip the Version PR
|
|
219
|
-
|
|
220
|
-
Always review and merge the "Version Packages" PR. It shows exactly what will be published.
|
|
221
|
-
|
|
222
|
-
### 4. Use Yarn for Local Development
|
|
223
|
-
|
|
224
|
-
The project uses Yarn for dependency management:
|
|
225
|
-
|
|
226
|
-
```bash
|
|
227
|
-
yarn install
|
|
228
|
-
yarn dev
|
|
229
|
-
yarn build
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### 5. Keep `.npmrc` Private
|
|
233
|
-
|
|
234
|
-
The `.npmrc` file contains your authentication token. It's in `.gitignore` - **never commit it!**
|
|
235
|
-
|
|
236
|
-
## Security
|
|
237
|
-
|
|
238
|
-
### npm Authentication
|
|
239
|
-
|
|
240
|
-
- **GitHub Actions**: Uses `NPM_TOKEN` secret (automation token)
|
|
241
|
-
- **Local Publishing**: Uses `.npmrc` file (not committed to git)
|
|
242
|
-
|
|
243
|
-
### Token Types
|
|
244
|
-
|
|
245
|
-
- **Automation tokens**: Bypass 2FA, designed for CI/CD
|
|
246
|
-
- **Publish tokens**: Require 2FA, for manual publishing
|
|
247
|
-
|
|
248
|
-
Always use automation tokens for GitHub Actions.
|
|
249
|
-
|
|
250
|
-
## Package Information
|
|
251
|
-
|
|
252
|
-
- **Name**: `@7365admin1/layer-common`
|
|
253
|
-
- **Registry**: https://registry.npmjs.org/
|
|
254
|
-
- **Package Page**: https://www.npmjs.com/package/@7365admin1/layer-common
|
|
255
|
-
- **Author**: 7365admin1
|
|
256
|
-
- **License**: MIT
|
|
257
|
-
|
|
258
|
-
## Need Help?
|
|
259
|
-
|
|
260
|
-
If you encounter issues:
|
|
261
|
-
|
|
262
|
-
1. Check the [Changesets documentation](https://github.com/changesets/changesets)
|
|
263
|
-
2. Review GitHub Actions workflow logs
|
|
264
|
-
3. Verify npm token is valid and has correct permissions
|
|
265
|
-
4. Ensure `.changeset/config.json` has `"access": "public"`
|
|
266
|
-
|
|
267
|
-
---
|
|
268
|
-
|
|
269
|
-
**Last Updated**: January 2026
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<v-dialog
|
|
3
|
-
:model-value="modelValue"
|
|
4
|
-
@update:model-value="(v) => emit('update:modelValue', v)"
|
|
5
|
-
max-width="520"
|
|
6
|
-
>
|
|
7
|
-
<!-- 520px is the handoff's `--modal-w`, and the card wears `.screen-modal`
|
|
8
|
-
for the 16px corner, the `--card` surface and the modal shadow. The
|
|
9
|
-
two `v-toolbar`s standing in for the title row and the footer were
|
|
10
|
-
fixed grey slabs that stay grey on the dark theme, and the Create
|
|
11
|
-
button was a hardcoded `color="black"` fill on a `rounded-0` square. -->
|
|
12
|
-
<v-card class="screen-modal">
|
|
13
|
-
<template v-if="$slots.header">
|
|
14
|
-
<slot
|
|
15
|
-
name="header"
|
|
16
|
-
:title="
|
|
17
|
-
mode === 'edit' ? `Edit ${entityType}` : `Add New ${entityType}`
|
|
18
|
-
"
|
|
19
|
-
:onClose="onClose"
|
|
20
|
-
/>
|
|
21
|
-
</template>
|
|
22
|
-
<v-card-title v-else class="text-capitalize">{{
|
|
23
|
-
mode === "edit" ? `Edit ${entityType}` : `Add New ${entityType}`
|
|
24
|
-
}}</v-card-title>
|
|
25
|
-
|
|
26
|
-
<v-card-text class="screen-modal__body">
|
|
27
|
-
<v-form ref="formRef" v-model="valid">
|
|
28
|
-
<v-row>
|
|
29
|
-
<v-col cols="12">
|
|
30
|
-
<InputLabel for="name" :title="label" required />
|
|
31
|
-
<!-- Still a `v-text-field`: Submit is gated on `valid`, which
|
|
32
|
-
only exists because this `:rules` runs. `.filter-field` gives
|
|
33
|
-
it the design's 40px / 10px / 13.5px shape without taking the
|
|
34
|
-
validation away. -->
|
|
35
|
-
<v-text-field
|
|
36
|
-
v-model="nameValue"
|
|
37
|
-
class="filter-field"
|
|
38
|
-
:rules="[requiredRule]"
|
|
39
|
-
/>
|
|
40
|
-
</v-col>
|
|
41
|
-
</v-row>
|
|
42
|
-
</v-form>
|
|
43
|
-
</v-card-text>
|
|
44
|
-
|
|
45
|
-
<div class="screen-modal__footer">
|
|
46
|
-
<v-btn
|
|
47
|
-
variant="outlined"
|
|
48
|
-
class="screen-btn-ghost"
|
|
49
|
-
@click="close"
|
|
50
|
-
>
|
|
51
|
-
Cancel
|
|
52
|
-
</v-btn>
|
|
53
|
-
|
|
54
|
-
<!-- Kept a `v-btn`: `loading` is the only in-flight signal this form
|
|
55
|
-
has, and `AppButton` has no equivalent. -->
|
|
56
|
-
<v-btn
|
|
57
|
-
variant="flat"
|
|
58
|
-
class="screen-btn-primary"
|
|
59
|
-
:loading="submitting"
|
|
60
|
-
@click="submit"
|
|
61
|
-
>
|
|
62
|
-
{{ mode === "edit" ? "Save" : "Create" }}
|
|
63
|
-
</v-btn>
|
|
64
|
-
</div>
|
|
65
|
-
</v-card>
|
|
66
|
-
</v-dialog>
|
|
67
|
-
</template>
|
|
68
|
-
|
|
69
|
-
<script setup lang="ts">
|
|
70
|
-
const props = defineProps({
|
|
71
|
-
modelValue: { type: Boolean, required: true },
|
|
72
|
-
mode: { type: String as PropType<"add" | "edit">, default: "add" },
|
|
73
|
-
area: { type: Object as PropType<Record<string, any> | null>, default: null },
|
|
74
|
-
label: { type: String, default: "Name" },
|
|
75
|
-
nameModel: { type: String as PropType<string | null>, default: null },
|
|
76
|
-
entityType: { type: String, default: "Area" }, // values: "Area", "Unit"
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const emit = defineEmits([
|
|
80
|
-
"update:modelValue",
|
|
81
|
-
"saved",
|
|
82
|
-
"update:nameModel",
|
|
83
|
-
] as const);
|
|
84
|
-
|
|
85
|
-
const formRef = ref(null);
|
|
86
|
-
const valid = ref(false);
|
|
87
|
-
const submitting = ref(false);
|
|
88
|
-
|
|
89
|
-
const form = reactive({ name: "", description: "", status: "active" });
|
|
90
|
-
|
|
91
|
-
watchEffect(() => {
|
|
92
|
-
if (props.area) {
|
|
93
|
-
form.name = props.area.name || "";
|
|
94
|
-
form.description = props.area.description || "";
|
|
95
|
-
form.status = props.area.status || "active";
|
|
96
|
-
} else {
|
|
97
|
-
form.name = "";
|
|
98
|
-
form.description = "";
|
|
99
|
-
form.status = "active";
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const { requiredRule } = useUtils();
|
|
104
|
-
|
|
105
|
-
const nameValue = computed({
|
|
106
|
-
get: () => {
|
|
107
|
-
return props.nameModel !== null ? props.nameModel : form.name;
|
|
108
|
-
},
|
|
109
|
-
set: (v: string) => {
|
|
110
|
-
if (props.nameModel !== null) {
|
|
111
|
-
emit("update:nameModel", v);
|
|
112
|
-
} else {
|
|
113
|
-
form.name = v;
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
function close() {
|
|
119
|
-
emit("update:modelValue", false);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const onClose = () => close();
|
|
123
|
-
|
|
124
|
-
async function submit() {
|
|
125
|
-
if (!valid.value) return;
|
|
126
|
-
submitting.value = true;
|
|
127
|
-
try {
|
|
128
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
129
|
-
emit("saved", { ...form, _id: props.area?._id || Date.now().toString() });
|
|
130
|
-
|
|
131
|
-
form.name = "";
|
|
132
|
-
form.description = "";
|
|
133
|
-
form.status = "active";
|
|
134
|
-
|
|
135
|
-
emit("update:modelValue", false);
|
|
136
|
-
} catch (e) {
|
|
137
|
-
} finally {
|
|
138
|
-
submitting.value = false;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
</script>
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<!-- The schedule-area copy of `Dialog/UpdateMoreAction`, converted the same
|
|
3
|
-
way: two `v-toolbar`s (fixed grey slabs that stay grey on the dark
|
|
4
|
-
theme) for the title row and the footer, and a hardcoded `color="black"`
|
|
5
|
-
fill on a square 48px tile. -->
|
|
6
|
-
<v-card class="screen-modal" width="100%">
|
|
7
|
-
<template v-if="$slots.header">
|
|
8
|
-
<slot name="header" :title="title" :onClose="onClose" />
|
|
9
|
-
</template>
|
|
10
|
-
<v-card-title v-else class="text-capitalize">{{ title }}</v-card-title>
|
|
11
|
-
|
|
12
|
-
<v-card-text class="screen-modal__body pb-0">
|
|
13
|
-
<slot name="content" />
|
|
14
|
-
</v-card-text>
|
|
15
|
-
|
|
16
|
-
<div class="screen-modal__footer">
|
|
17
|
-
<v-btn
|
|
18
|
-
variant="outlined"
|
|
19
|
-
class="screen-btn-ghost"
|
|
20
|
-
@click="emit('close')"
|
|
21
|
-
>
|
|
22
|
-
Close
|
|
23
|
-
</v-btn>
|
|
24
|
-
|
|
25
|
-
<v-menu>
|
|
26
|
-
<template #activator="{ props }">
|
|
27
|
-
<v-btn
|
|
28
|
-
variant="flat"
|
|
29
|
-
class="screen-btn-primary"
|
|
30
|
-
v-bind="props"
|
|
31
|
-
>
|
|
32
|
-
More actions
|
|
33
|
-
</v-btn>
|
|
34
|
-
</template>
|
|
35
|
-
|
|
36
|
-
<!-- Dropdown shape left as Vuetify draws it - the handoff specifies
|
|
37
|
-
the profile dropdown only. `text-red` (Vuetify's fixed #f44336,
|
|
38
|
-
the same red on both themes) becomes `text-error`, which is
|
|
39
|
-
`--v-theme-error`, i.e. the design's `--err`, matching the
|
|
40
|
-
handoff's "red Logout row (err color, err-bg hover)". -->
|
|
41
|
-
<v-list class="pa-0 area-more__list">
|
|
42
|
-
<v-list-item v-if="canUpdate" @click="emit('edit')">
|
|
43
|
-
<v-list-item-title>
|
|
44
|
-
{{ editButtonLabel }}
|
|
45
|
-
</v-list-item-title>
|
|
46
|
-
</v-list-item>
|
|
47
|
-
|
|
48
|
-
<v-list-item
|
|
49
|
-
v-if="canDelete"
|
|
50
|
-
@click="emit('delete')"
|
|
51
|
-
class="text-error"
|
|
52
|
-
>
|
|
53
|
-
<v-list-item-title>
|
|
54
|
-
{{ deleteButtonLabel }}
|
|
55
|
-
</v-list-item-title>
|
|
56
|
-
</v-list-item>
|
|
57
|
-
</v-list>
|
|
58
|
-
</v-menu>
|
|
59
|
-
</div>
|
|
60
|
-
</v-card>
|
|
61
|
-
</template>
|
|
62
|
-
|
|
63
|
-
<script setup lang="ts">
|
|
64
|
-
const prop = defineProps({
|
|
65
|
-
canUpdate: {
|
|
66
|
-
type: Boolean,
|
|
67
|
-
default: true,
|
|
68
|
-
},
|
|
69
|
-
canDelete: {
|
|
70
|
-
type: Boolean,
|
|
71
|
-
default: true,
|
|
72
|
-
},
|
|
73
|
-
editButtonLabel: {
|
|
74
|
-
type: String,
|
|
75
|
-
default: "Edit Area",
|
|
76
|
-
},
|
|
77
|
-
deleteButtonLabel: {
|
|
78
|
-
type: String,
|
|
79
|
-
default: "Delete Area",
|
|
80
|
-
},
|
|
81
|
-
title: {
|
|
82
|
-
type: String,
|
|
83
|
-
default: "Area Actions",
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
const emit = defineEmits(["close", "manage", "edit", "delete"]);
|
|
88
|
-
const {
|
|
89
|
-
canUpdate,
|
|
90
|
-
editButtonLabel,
|
|
91
|
-
deleteButtonLabel,
|
|
92
|
-
manageButtonLabel,
|
|
93
|
-
title,
|
|
94
|
-
} = prop;
|
|
95
|
-
</script>
|
|
96
|
-
|
|
97
|
-
<style scoped>
|
|
98
|
-
/* `text-subtitle-2` was Vuetify's 0.875rem/500; the handoff names no type for
|
|
99
|
-
a menu row, so it takes the established cell type. */
|
|
100
|
-
.area-more__list :deep(.v-list-item-title) {
|
|
101
|
-
font-size: var(--fs-cell);
|
|
102
|
-
font-weight: var(--fw-cell);
|
|
103
|
-
}
|
|
104
|
-
</style>
|